Tile Rendering with Mapnik (Part 1 of n, where n is large)

In my last blog post, I explained a little about the process by which you can overlay raster data on Bing Maps, by geo-referencing the source data (if necessary), projecting into the appropriate spherical Mercator projection, then cutting the resulting image into 256px x 256px tiles named according to the quadkey tile numbering system.

The application I used in the last example to do this was Microsoft Mapcruncher. Mapcruncher has got a lot of benefits:

  • It’s free
  • It’s a windows application with no special dependencies and easy to install
  • It’s got a nice GUI that’s very easy to use
  • It will perform geo-referencing/warping/tile-cutting for you as part of a single process

Mapcruncher is great if you have a relatively small raster image that you want to integrate into Bing Maps / Google Maps as part of a one-off process. However, there are many occasions when you might need a little more than that. As part of a current project, for example, I need to create a tileset that covers an area of approximately 60km x 50km (not that small), based on data held in SQL Server 2008 (not raster), that will be updated approximately every month (not one-off).

So I set out to evaluate alternatives, and the first I considered was mapnik.

Installing Mapnik

Mapnik is an open-source mapping toolkit. It’s what openstreetmap uses to render the tiles used in their base map imagery. They’ve got over 220Gb of XML data in the planet.osm file, covering the whole world, with thousands of updates every day, so if mapnik can render that I’m pretty certain it should be able to cope with my modest requirements.

Mapnik tiles in Open Street Map

Installing and configuring mapnik, unfortunately, turned out to be quite a challenge, and has taken me a significant amount of time to get a working installation. In fact, had I realised quite how many steps would be involved, I’d probably have taken more care to document them carefully. As it is, I’m going to try to note down in this post what I did while they’re still relatively fresh in my mind.

What about using pre-compiled Windows binaries?

Mapnik, like many open source applications, is primarily targeted at a UNIX stack. That means that a large part of the documentation will refer to commands like sudo apt-get, which will look fairly alien to many Windows users. There’s also a lot of dependencies on other packages – python, libboost, libpng, etc. which you may not be familiar with.

Now, fortunately, some kind people have taken the time to prepare pre-compiled Windows binaries of these various tools, and even packaged them together in convenient download format.

For example, the OSGeo4W package contains windows binary executables for Mapnik, along with the GDAL library (used for importing, converting of various spatial data formats), QGIS (open source desktop GIS application), and many other useful open source spatial goodies. The problem is that, with trying to keep track of all those separate dependencies, the package itself can become out-of-date quite quickly. The latest build of OSGeo4W, for example, is still based on python 2.5.2-1. The current build of the 2.x branch of python is 2.7.1, and even that represents the end-of-life release for the 2.x branch. The latest version of python is actually 3.2. I didn’t really want to start a project on software that had already been deprecated.

Likewise, the excellent FWTools project, which also bundles together many of the same packages as OSGeo4W still comes bundled with Python 2.3.4 and version 1.7 of the GDAL library. Crucially, for me, GDAL introduced support for SQL Server as a spatial data source only in version 1.8, so using FWTools wasn’t an option either.

What’s more, Mapnik itself seems to have forked into two versions – the current stable release being 0.7.1, but with many comments being made about breaking changes in the new 2.x development version. The only precompiled windows binaries I could find were of the 0.7 version and, again, I didn’t want to invest a lot of time setting up a project based on software that was about to go out of date.

So, precompiled binaries was, at this stage, a no-go.

Build-It-Yourself

I decided I was going to have to build my own installation, and here was my wish list:

  • Python 3.2
  • GDAL 1.8
  • Mapnik 2.x

Python was (thankfully) easy to install – there’s an installer package available from http://python.org/ftp/python/3.2/python-3.2.msi

GDAL was also not too bad – there are x86 and x64 packages (bundled with mapserver) that you can download from http://www.gisinternals.com/sdk/

Now onto Mapnik. And it is here, with retrospect, that I wish I’d stated taking notes. You can download the source for mapnik from here. However, before compiling mapnik itself, you need to download and/or compile its required dependencies. These are: proj4, boost, zlib, freetype, icu, libxml2, libpng, libjpeg, and libtiff.

Now, you could download the source for each of these and build them separately but fortunately, once again, some kind soul has done much of this work for us. If you go to the gnuwin32 project on sourceforge, you’ll find links to download most of these libraries. For those packages not included in gbuwin32, ICU is available from here, and you can get the latest zlib from here.

Once you’ve got all the dependencies sorted out, it’s onto the configuration changes. If you follow the article at http://trac.mapnik.org/wiki/Python3k you’ll see a number of steps required to rebuild the python bindings with Mapnik to target Python 3.x. After some fiddling about with these and a bit of guesswork, I managed eventually to get everything built.

Testing it Out

Mapnik comes with a test script so, gingerly, I tried running it. Lots of errors – couldn’t find xxx etc. I realised this was because I hadn’t set the environment variables and paths correctly so, after sorting this out, I had another go. This time looked a lot more promising:

image

And, lo and behold, here was the (beautiful) example image generated:

demo_high

Over-confident of my new found ability, I then tried altering the example rundemo.py script to point at a SQL Server datasource. Mapnik supports OGR datasources, so I first created a virtual layer that connected to my SQL Server. For the purposes of testing, I decided to select a set of data from the OS VectorMap District settlement area data (note that I’m not sure if OGR can deal with SQL Server’s native binary geography/geometry format, so I use STAsText() to get the WKT representation and then specify WKT encoding in the GeometryField):

<OGRVRTDataSource>
  <OGRVRTLayer name="AASQLlayer">
    <SrcDataSource>MSSQL:server=.\SQLEXPRESS;database=OSVectorMap;trusted_connection=yes</SrcDataSource> 
    <SrcSQL>SELECT geom27700.STAsText() AS geomWKT FROM TG11_Settlement_Area</SrcSQL>
    <GeometryField encoding="WKT" field="geomWKT"/>
  </OGRVRTLayer>
</OGRVRTDataSource>

Testing the virtual layer with ogrinfo seemed to suggest that everything was working ok:

image

So then I modifed the python script to add the new layer. Note that OS Vectormap data is defined using the OSGB British National Grid coordinate system (EPSG:27700), and mapnik expects the parameters for the srs property to use PROJ4 syntax, which you can get from http://spatialreference.org/ref/epsg/27700/proj4/:

vectormap_lyr = mapnik.Layer('OS Vectormap')
vectormap_lyr.srs = "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs"

vectormap_lyr.datasource = mapnik.Ogr(file='MSSQL.ovf',layer="AASQLlayer")

Unfortunately, here I hit another problem:

image

And it seems here my luck has run out, because I simply can’t work out how to get round this one. The error message is simply “Failed to open datasource”, yet ogrinfo confirms that the datasource is fine, and other GDAL/OGR components can read from it, so I don’t know if it’s because I built mapnik wrong or forgot to change/include a particular setting.

I did just notice that there’s a Google Summer of Code Project to improve Mapnik installation on Windows, and I’m really hoping it’s successful because the results generated by Mapnik are beautiful.

As a workaround, I actually used OGR2OGR to export my data from SQL Server into a shapefile called MSSQL_export.shp, and then used that as a datasource in Mapnik by changing the python datasource to:

vectormap_lyr.datasource = mapnik.Shapefile(file='MSSQL_export')

Finally, after a bit of XML styling, I was able to get the following image (click for full size):

image

I’m actually really pleased with the image quality, but until I can get Mapnik to retrieve data directly from SQL Server there’s not much point proceeding with the tilecutting process – I can’t really justify an additional step of exporting from SQL Server to shapefile just to get Mapnik to load it.

If anyone has had any success of getting Mapnik and SQL Server to play nicely together, please let me know!

This entry was posted in Bing Maps, Open Street Maps, Spatial and tagged , , . Bookmark the permalink.

10 Responses to Tile Rendering with Mapnik (Part 1 of n, where n is large)

  1. John says:

    Great article, as someone who got about 10% through this process before giving up I admire your commitment. Great place for others to pickup and sort that final hurdle. Look forward to the follow up 🙂

  2. Isaac says:

    Hi and thank you for posting this writeup. One question, where on http://www.gisinternals.com/sdk/ did you find a package that had GDAL for Python 3.2? I can only find one for Python 3.1 and older versions. If you could post the link, it would be much appreciated.

    Thanks,
    Isaac

    • alastaira says:

      If I’d have known at the time how much effort would have been involved in setting this all up, I’d have kept a lot more notes about exactly where I had to get all the components from and how I had to configure them! (but then, isn’t hindsight a wonderful thing?). The content of this post only skims the surface of about 5 nights of trying to get this to work, and at the end of it I’d installed so many different versions of different bits of software, I can’t even remember what versions I got to work in the end, so I’m afraid I’m not even sure if I definitely got GDAL from that link – I might have had to build that from source too.

      To be honest, after I wrote this post I noticed some other weird goings on with my home-built frankenstein’s monster of a mapnik installation – anti-aliasing didn’t work correctly and some file formats weren’t supported – presumeably because I hadn’t built/linked to the right libraries at the right time during the build. As a result, I’ve now gone back to using the version of mapnik that comes shipped with OSGEO4W. It’s not the latest (and I still can’t get it to connect to SQL Server), but it does work for rendering shapefiles and other OGR sources which is the best I can get for now.

  3. leozncanger says:

    Thanks for the great article. I have tried the new mapnik 2.0 for windows RC and it works! The ogrinfo 1.9 also has no problem of connecting to sql server. I can render an image using mapnik and geometry data in my sql server database.

  4. yudong says:

    The wkt from sql server works for me, so I want to try to use wkb as data source, because wkb is faster. So I changed the ovf to the following:

    MSSQL:server=localhost;database=adcitest1;trusted_connection=yes
    SELECT top 10 geom.STAsBinary() AS gWKB FROM [adcitest1].[dbo].[xxxx_table]

    but when I run `ogrinfo -al mssql.ovf`, I got the following error:

    ERROR 1: Unable to identify source field ‘gWKB’ for geometry
    and
    ERROR 1: GetNextRawFeature(): Corrupt data
    for each row of data.

    Do you have any idea about this error?
    Thanks

  5. Ngoc says:

    i didnt see my map in pictures is exported. only background 😦

  6. yudong says:

    Did you build mapnik on windows? If yes, could you tell me what tools did you use? Thanks very much

  7. Steve says:

    Great post Alistair and exactly the experience I’ve had.

    I’m wanting to write up my own WMS that leverages from spatial data stored in MSSQL, custom map symbology defined in my own database and tiles generated using Mapnik (with labels).

    I’ll be displaying all these tiles using OpenLayers or Leaflet, but currently can’t get the Mapnik rendering part of the solutions sorted (which is the first step!).

    Would be keen to chat more about this and see whether we could make progress on this. Are you still interested in this issue/task? Btw, I’ve got your SQL Spatial book on my shelf here and refer to it quite a bit. Thanks for writing it.

  8. hi.I have one question. I make new style file(that’s xml) and restart server My map change style but even loaded tile do not change..how can I change the map tile style without cash tile?

Leave a comment