[Mapnik-devel] Prototype WMS interface to Mapnik (cherry_mapnik.py)

Matthew Perry perrygeo at gmail.com
Wed Apr 5 09:20:03 CEST 2006


Well sounds like you got alot further that I have! Let us know where
we can access the code and I'll take it for a spin. Will this
eventually become part of the mapnik distribution?

matt

On 4/4/06, Jean-François Doyon <jfdoyon at gmail.com> wrote:
> Cool!
>
> I've been working on a CGI/FastCGI OGC Server for Mapnik the last little
> while.
>
> I have a working WMS 1.3.0, but not client, so I'm going to implement a
> 1.1.1 very soon now :)
>
> It uses jonpy and ElementTree, and is also a framework to facilitate
> writing other OGC servers (like WFS or WCS).
>
> We'll see if I can get something committed tonight :)
>
> J.F.
>
> Matthew Perry wrote:
> > Hey mapnikers,
> >
> >   So the nice rainy sunday prompted me to resume my trials with
> > mapnik. I was able to build the latest SVN against the ubuntu 6.04
> > boost libraries and everything went well. Alot has changed since the
> > tutorial on the website and that threw me off for a few minutes until
> > I found the excellent demo script! Beautiful cartography. Beautiful
> > python.
> >
> >  I have also been working a bit evaluating python web application
> > frameworks and cherrypy impressed me with it's ease of use and very
> > "pythonic" approach.
> >
> >  So putting the two together, I worked up a simple pseudo-WMS server
> > as an interface to mapnik. I say pseudo-WMS server because it doesn't
> > even come close to complying with the WMS spec. The only thing it can
> > do is handle a simple GetMap request:
> >  http://localhost:8080/wms?VERSION=1.1.1&REQUEST=GetMap&LAYERS=states&FORMAT=image/jpeg&SRS=EPSG:4326&STYLES=&BBOX=-120,15,-70,65&width=400&height=400
> >
> > But for some very simple WMS clients, this is all you need. I set up a
> > nifty little interactive map using wms-map
> > (http://wms-map.sourceforge.net/)  which I'll make public as soon as I
> > get mapnik installed on a server somewhere.
> >
> > Cherrypy servers run as standalone servers bound to a specific port
> > but can optionally be put behind an apache server... Setting up this
> > WMS server as a standalone should be fairly simple. You'll need the
> > cherrypy and mapnik python modules to start. There is a createMap()
> > function that contains all the usual mapnik code which you can tweak
> > for your specific data. Then there is a WMS class that parses the WMS
> > requests and passes them off to createMap() which writes an image to
> > disk and returns the map image to the client. I didn't have alot of
> > time to spend so this only a proof-of-concept.
> >
> > My initial testing against a Mapserver-based WMS (running on the same
> > machine, same dataset) indicates that for single requests, Mapserver
> > is only about 15% faster. But for many simultaneous requests (such as
> > the tiled WMS clients make; 9 requests on every pan) mapnik/cherrypy
> > is 3-400% faster (!!) under a decent load. Put this behind an apache
> > server and you could have a fast, solid WMS server with mapnik on the
> > backend. Plus mapnik's image quality is by far the most impressive of
> > any map rendering engine i've seen! Here's a screenshot comparing the
> > WMS clients based on both mapserver and mapnik -
> > http://perrygeo.net/img/mapserver_mapnik.png (a screenshot of one of
> > my favorite places in the world. any guesses??). Just look at that
> > beautiful line work.. did I mention I was impressed?
> >
> > Attached is the code. Please give the prototype WMS server a shot and
> > let me know how it goes.  My understanding of both mapnik and cherrypy
> > is limited so please jump in and make suggestions.
> >
> > --
> > Matt Perry
> > perrygeo at gmail.com
> > http://www.perrygeo.net
> >
> > ------------------------------------------------------------------------
> >
> > #!/usr/bin/env python
> > """
> >  cherry_mapnik.py
> >
> >  Description:
> >    Proof of concept WMS server using cherrypy as the web framework and
> >    mapnik as the map rendering engine
> >
> >  Author:
> >    Matthew Perry
> >
> >  Last Modified:
> >    04/02/06
> >
> >  License:
> >    Free to use and modify for any purpose. ABSOLUTELY NO WARRANTY OF ANY KIND.
> >
> >  Caveat:
> >    Does not even come close to complying with the WMS spec.
> >    Only very limited GetMap requests supported
> >
> >  Example:
> >    start the server with "python cherry_mapnik.py"
> >    point your browser to http://localhost:8080/wms?VERSION=1.1.1&REQUEST=GetMap&LAYERS=states&FORMAT=image/jpeg&SRS=EPSG:4326&STYLES=&BBOX=-120,15,-70,65&width=400&height=400
> > """
> >
> > import cherrypy, random
> > from mapnik import *
> > from cherrypy.lib import cptools
> >
> > def createMap(envelope,mapsize,imagetype,layers):
> >
> >     #=========================#
> >     # System-specific variables
> >
> >     # The polygon shapefile (minus the .shp extension)
> >     shpfile  = '/home/perrygeo/data/states/statesp020'
> >
> >     # The output image directory where mapnik will cache images
> >     # It really helps to have a cron task to clean out this dir!
> >     imagedir = '/home/perrygeo/www/tmp'
> >
> >     #=========================#
> >
> >     # Set up the Mapnik Map
> >     m = Map(mapsize[0],mapsize[1])
> >     m.background = Color('#525367')
> >
> >     # Turn on 'states' layer if requested
> >     if 'states' in layers:
> >         states_lyr = Layer(name='states', type='shape', file=shpfile)
> >         states_style = Style()
> >         states_rule = Rule()
> >         states_rule.symbols.append(PolygonSymbolizer(Color(248,216,136)))
> >         states_rule.symbols.append(LineSymbolizer(Color(48,48,48),1))
> >         states_style.rules.append( states_rule )
> >         m.append_style('states', states_style)
> >         states_lyr.styles.append('states')
> >         m.layers.append(states_lyr)
> >
> >     # Set the BBOX extent
> >     m.zoom_to_box(envelope)
> >
> >     # Get the proper image type and file extensions
> >     if imagetype=='png': ext='png'
> >     if imagetype=='jpeg' or imagetype=='jpg':
> >       ext='jpg'
> >       imagetype='jpeg'
> >
> >     # Generate an image with random filename
> >     rand = random.randint(0,90000000)
> >     prefix = "mapnik_%s" % rand
> >     path = imagedir + '/'  + prefix + '.' + ext
> >
> >     render_to_file(m, path, imagetype)
> >     return path
> >
> > class WMS:
> >     def getCapabilities(self):
> >         xml = '<test>Capabilities not supported yet </test>'
> >         return xml
> >
> >     def wms(self, *args, **kwargs):
> >         # WMS spec calls for case insensitive parameter names
> >         lc = {}
> >         for k,v in kwargs.iteritems():
> >             lc[str(k).lower()] = v
> >
> >         if lc['request']=='GetCapabilities' and lc['service']=='WMS':
> >             cherrypy.response.headerMap['Content-Type']= 'text/xml'
> >             return self.getCapabilities()
> >         elif lc['request']=='GetMap':
> >             corners = lc['bbox'].split(',')
> >             envelope = Envelope(float(corners[0]),float(corners[1]), \
> >                             float(corners[2]),float(corners[3]))
> >             imagetype = lc['format'].replace('image/','')
> >             mapsize=(int( lc['width'] ),int( lc['height'] ))
> >             layers = lc['layers'].split(',')
> >
> >             path = createMap(envelope,mapsize,imagetype,layers)
> >             return cptools.serveFile(path)
> >         else:
> >            cherrypy.response.headerMap['Content-Type']= 'text/xml'
> >            return "<test>You gotta request something</test>"
> >
> >     wms.exposed = True
> >
> > if __name__ == '__main__':
> >     cherrypy.root = WMS()
> >     cherrypy.config.update({
> >             'global': {
> >                 'server.socket_port' : 8080,
> >                 'server.thread_pool' : 10,
> >                 'logDebugInfoFilter.on' : False }})
> >     cherrypy.server.start()
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
>
>


--
Matt Perry
perrygeo at gmail.com
http://www.perrygeo.net



More information about the Mapnik-devel mailing list