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

Reply via email to