Udo Giacomozzi wrote:
I just set up my own Mapnik server that renders map tiles on demand
and saves them on disk so that they are efficiently cached. Currently
this is done using a PHP script (FastCGI handler with 5 instances)
that handles 404 errors and invokes a python script to render the
tile which then gets stored at the location that caused the 404 error.
Invoking python from PHP is suboptimal, I know, but I'm no Python
programmer, PHP lacks Mapnik support and so far this was only a proof
of concept.
I have set this up completely inside a webserver. Cherokee, no php, just
the python script that renders the thing on demand. Runs in production
for months now.
vserver!10!directory_index = index.html
vserver!10!document_root = /home/rullzer/tiles
vserver!10!domain!1 = tile.openstreetmap.nl
vserver!10!error_handler = error_redir
vserver!10!error_handler!404!show = 0
vserver!10!error_handler!404!url = /live/render.py
vserver!10!keepalive = 1
vserver!10!nick = default
vserver!10!rule!300!document_root = /home/rullzer/cgi-bin/
vserver!10!rule!300!encoder!deflate = 0
vserver!10!rule!300!encoder!gzip = 0
vserver!10!rule!300!handler = cgi
vserver!10!rule!300!handler!change_user = 1
vserver!10!rule!300!handler!check_file = 1
vserver!10!rule!300!handler!error_handler = 1
vserver!10!rule!300!handler!pass_req_headers = 0
vserver!10!rule!300!handler!xsendfile = 1
vserver!10!rule!300!match = directory
vserver!10!rule!300!match!directory = /live
vserver!10!rule!300!match!final = 1
vserver!10!rule!300!only_secure = 0
vserver!10!rule!100!encoder!deflate = 0
vserver!10!rule!100!encoder!gzip = 0
vserver!10!rule!100!expiration = time
vserver!10!rule!100!expiration!time = 1w
vserver!10!rule!100!handler = common
vserver!10!rule!100!handler!allow_dirlist = 0
vserver!10!rule!100!handler!allow_pathinfo = 0
vserver!10!rule!100!handler!date = 1
vserver!10!rule!100!handler!group = 0
vserver!10!rule!100!handler!iocache = 0
vserver!10!rule!100!handler!size = 1
vserver!10!rule!100!handler!symlinks = 1
vserver!10!rule!100!handler!theme = plain
vserver!10!rule!100!handler!user = 0
vserver!10!rule!100!match = default
vserver!10!rule!100!match!final = 1
vserver!10!rule!100!only_secure = 0
Stefan
#!/usr/bin/python
from math import pi,cos,sin,log,exp,atan
from subprocess import call
import sys, os, cgi, mapnik
import resource
DEG_TO_RAD = pi/180
RAD_TO_DEG = 180/pi
#Used some stuff from the generate_tiles.py script
def minmax (a,b,c):
a = max(a,b)
a = min(a,c)
return a
class GoogleProjection:
def __init__(self,levels=18):
self.Bc = []
self.Cc = []
self.zc = []
self.Ac = []
c = 256
for d in range(0,levels):
e = c/2;
self.Bc.append(c/360.0)
self.Cc.append(c/(2 * pi))
self.zc.append((e,e))
self.Ac.append(c)
c *= 2
def fromLLtoPixel(self,ll,zoom):
d = self.zc[zoom]
e = round(d[0] + ll[0] * self.Bc[zoom])
f = minmax(sin(DEG_TO_RAD * ll[1]),-0.9999,0.9999)
g = round(d[1] + 0.5*log((1+f)/(1-f))*-self.Cc[zoom])
return (e,g)
def fromPixelToLL(self,px,zoom):
e = self.zc[zoom]
f = (px[0] - e[0])/self.Bc[zoom]
g = (px[1] - e[1])/-self.Cc[zoom]
h = RAD_TO_DEG * ( 2 * atan(exp(g)) - 0.5 * pi)
return (f,h)
def render_tile(x, y, mapfile, tile_dir, z):
#fix dir
if not os.path.isdir(tile_dir):
os.mkdir(tile_dir)
#General tile setup stuff
gprj = GoogleProjection(z+1)
m = mapnik.Map(2 * 256,2 * 256)
prj = mapnik.Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0
+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgri...@null +no_defs +over")
mapnik.load_map(m,mapfile)
zoom = str(z);
if not os.path.isdir(tile_dir + zoom):
os.mkdir(tile_dir + zoom)
p0 = gprj.fromPixelToLL((x * 256.0, (y+1) * 256.0),z)
p1 = gprj.fromPixelToLL(((x+1) * 256.0, y * 256.0),z)
str_x = str(x)
str_y = str(y)
if not os.path.isdir(tile_dir + zoom + '/' + str_x):
os.mkdir(tile_dir + zoom + '/' + str_x)
# render a new tile and store it on filesystem
c0 = prj.forward(mapnik.Coord(p0[0],p0[1]))
c1 = prj.forward(mapnik.Coord(p1[0],p1[1]))
bbox = mapnik.Envelope(c0.x,c0.y,c1.x,c1.y)
bbox.width(bbox.width() * 2)
bbox.height(bbox.height() * 2)
m.zoom_to_box(bbox)
tile_uri = tile_dir + zoom + '/' + str_x + '/' + str_y + '.png'
im = mapnik.Image(512, 512)
mapnik.render(m, im)
view = im.view(128,128,256,256) # x,y,width,height
view.save(tile_uri ,'png')
#reduce that baby
#os.system('/opt/cherokee/bin/convert -colors 255 -alpha on ' + tile_uri + '
' + tile_uri)
def main():
#We assume it should be rendered within 60 seconds
#resource.setrlimit(resource.RLIMIT_CPU,(60,70))
#Get the URL
qstr = os.environ["REDIRECT_URL"]
qstr = qstr.split("/")
#Basic stuff
#mapfile = "/home/mapnik/mapnik/osm-local.xml"
mapfile = "/home/rullzer/stylesheets/osm.xml"
tiledir = "/home/rullzer/tiles/"
if (len(qstr) == 5):
layer = qstr[1]
zoom = int(qstr[2])
x = int(qstr[3])
y = int(qstr[4].split(".")[0])
if (layer == "basemap"):
mapfile = "/home/rullzer/stylesheets/osm-base-map.xml"
tiledir = "/home/rullzer/tiles/basemap/"
elif (layer == "fietsroutes"):
mapfile =
"/home/rullzer/stylesheets/osm-fietsroutes-overlay.xml"
tiledir = "/home/rullzer/tiles/fietsroutes/"
elif (layer == "roads"):
mapfile = "/home/rullzer/stylesheets/osm-roads.xml"
tiledir = "/home/rullzer/tiles/roads/"
elif (layer == "fietsroutes-ncn"):
mapfile =
"/home/rullzer/stylesheets/osm-fietsroutes-ncn-overlay.xml"
tiledir = "/home/rullzer/tiles/fietsroutes-ncn/"
elif (layer == "fietsroutes-rcn"):
mapfile =
"/home/rullzer/stylesheets/osm-fietsroutes-rcn-overlay.xml"
tiledir = "/home/rullzer/tiles/fietsroutes-rcn/"
elif (layer == "fietsroutes-lcn"):
mapfile =
"/home/rullzer/stylesheets/osm-fietsroutes-lcn-overlay.xml"
tiledir = "/home/rullzer/tiles/fietsroutes-lcn/"
elif (layer == "ov"):
mapfile = "/home/rullzer/stylesheets/osm-ov-overlay.xml"
tiledir = "/home/rullzer/tiles/ov/"
elif (layer == "wandelroutes"):
mapfile =
"/home/rullzer/stylesheets/osm-wandelroutes-overlay.xml"
tiledir = "/home/rullzer/tiles/wandelroutes/"
elif (layer == "pois"):
mapfile = "/home/rullzer/stylesheets/osm-pois.xml"
tiledir = "/home/rullzer/tiles/pois/"
elif (layer == "places"):
mapfile = "/home/rullzer/stylesheets/osm-places.xml"
tiledir = "/home/rullzer/tiles/places/"
elif (layer == "carnaval"):
mapfile =
"/home/rullzer/stylesheets/osm-local-carnaval.xml"
tiledir = "/home/rullzer/tiles/carnaval/"
elif (layer == "frysk"):
mapfile = "/home/rullzer/stylesheets/osm-local-fy.xml"
tiledir = "/home/rullzer/tiles/frysk/"
elif (layer == "detour"):
mapfile =
"/home/rullzer/stylesheets/osm-detour-routes.xml"
tiledir = "/home/rullzer/tiles/detour/"
elif (layer == "coffeeshop"):
mapfile =
"/home/rullzer/stylesheets/osm-coffeeshops.xml"
tiledir = "/home/rullzer/tiles/coffeeshop/"
elif (layer == "recreational"):
mapfile =
"/home/rullzer/stylesheets/osm-recreational-routes.xml"
tiledir = "/home/rullzer/tiles/recreational/"
else:
#Split URL
zoom = int(qstr[1])
x = int(qstr[2])
y = int(qstr[3].split(".")[0])
#render tile
#print "Content-type: plain/txt\n"
#print zoom, x, y
#return
render_tile(x, y, mapfile, tiledir, zoom)
filename = "/home/rullzer/tiles" + os.environ["REDIRECT_URL"]
if os.path.exists(filename) and os.path.isfile(filename):
print "Content-type: image/png\n"
print file(filename, 'rb').read()
else:
print 'Status: 500'
#Return the tile
#print "Content-type: image/png\n"
# AFBLIJVEN!
#print file("/home/rullzer/tiles" + os.environ["REDIRECT_URL"],
"rb").read()
#print "Location: " + os.environ["QUERY_STRING"] + "\n\n" a
#print "Location:" + os.environ["QUERY_STRING"]
#print "Status: 404"
#print "Content-type: text/plain\n"
#print os.environ
main()
_______________________________________________
dev mailing list
dev@openstreetmap.org
http://lists.openstreetmap.org/listinfo/dev