Beginning to make a custom map projection with mapnik and proj.4
Installing mapnik and linking to a custom, self-compiled proj.4 library
I manually compiled proj.4 from downloaded source code.
I edited the Homebrew formula for mapnik2 (couldn’t get it to work with mapnik 3) so that it would link the version of proj.4 I just compiled by setting the location of these libraries to where proj.4 make install puts them and not where Homebrew expects them:
Then I compiled and installed mapnik, using the cairo option because that seems to be the only way to get Homebrew to compile it/relink the proj.4 plibraries. Since the python driver for mapnik was always looking for the libraries in the same location, this will just work – but I need to force Python to reload them, which seems to require restarting the Python kernel.
Finally, if you try to load OSM data with this custom-built mapnik, you’ll get an error like the following:
This can be fixed by adding "INPUT_PLUGINS=osm" to the list of arguments used by scons.
The final mapnik2.rb formula
Writing a custom map projection
Proj.4 has many source files, prefixed with PJ_ that are used to convert coordinates from spherical or ellipsoidal points into rectangular ones. As an example, below is the source code to the Mercator implementation, PJ_merc.c:
Note the use of function definition compiler macros. Also note that the coordinates returned ((xy)) are somewhat arbitrary – they seem to vary dramatically from projection to projection.
Let’s try dividing the output x coordinate by two. One condition that proj.4/mapnik does enforce is a 1:1 aspect ratio between x and y, so this should compress the output image. Note that we had to multiply it by two in the inverse functions as well.
First, in the proj.4 directory, run
Then rebuild mapnik to relink the proj.4 (maybe there’s a better way of doing this?):
Using the new map projection
In your mapnik XML stylesheet, set the projection like so (this corresponds to web mercator):
With the original PJ_merc.c:
With the modified/stretched PJ_merc.c:
Obviously this is only the tip of the iceberg for defining a map projection – you just need a set of functions for performing the forward and inverse projection, and you’re ready to start rendering real maps with real data. You can even render tiled maps for use with maps browser such as Leaflet.