I'm trying to render a map to paper using Mapnik at a specific scale (such as 1:50k), but can't yet figure out how. So far I'm just using map.zoom_to_box:

map.zoom_to_box (mapnik.Envelope (101.5,3.2,102,3.3))

and play with MaxScaleDenominator and MinScaleDenominator in the styling rules..

But when done this way, I can only guess-work the map scale by adjusting the bounding box over and over, which is hard to obtain the exact 1:50k scale that I wanted.. I've also found this: map.scale_denominator() and map.scale(), but I think these are used only to display the map scale - not setting it..

Is there anyone here who can help me?

  • Hi Haziq, welcome to the forums. I'm not a Mapnik user so I haven't tested this, but here's a post regarding the same issue in OpenLayers, which might also be applicable? – Stephen Lead Sep 17 '12 at 3:22
  • Interesting syntax usages.. Don't know whether they'll work with Mapnik or not, so I'll try them on. Thanks @StephenLead! – user8723 Sep 17 '12 at 9:47
  • @StephenLead My python's a little rusty, so I can't get those to work with Mapnik.. – user8723 Sep 17 '12 at 11:24

I think I've found a workaround to my problem, but it's not a neat one. Basically:

  1. I used print map.scale_denominator() to figure out the scale of my current selection bounding box
  2. map.pan_and_zoom(+x,+y,z) to pan and zoom to the area that I wanted
  3. Used print map.envelope(). This will give out the current bounding box used after panning: Box2d(minlong,minlat,maxlong,maxlat)
  4. Adjust map.pan_and_zoom(+x,+y,z) z-values to zoom until map.scale_denominator() printout the scale value I wanted (50k)
  5. When the map is panned at the right location, I just read the current map.envelope() values and transfer them into the map.zoom_to_box as the new bounding box. I'll comment out map.pan_and_zoom(+x,+y,z) when I'm done.

The overall code will look something like this:

map = mapnik.Map (3000, 3000)
mapnik.load_map (map, "mapDefinition.xml")
map.zoom_to_box (mapnik.Envelope (101.789315885,3.1540902527,101.977962094,3.3427364622))
mapnik.render_to_file (map,"map.png")
print map.scale_denominator(), map.scale()
print map.envelope()

Like I said - messy. But it gets the job done.

  • Thanks for this. This "guessing" process can be easily automated, but it's a huge hack. Is there really no better way?! – kontextify Dec 26 '14 at 7:49
  • There should be (still waiting for a better answer). I haven't been using Mapnik for a while, and I've long stopped researching for a better answer. Maybe you should take a look at TileMill or Mapbox Studio, and see how they do it. – user8723 Dec 26 '14 at 8:23

This post should answer your question. Basically you should do a bit of math based on the resolution at which you want to print.

  • I've already delved into this blog post: that's where I got the idea on how to get the exact numbers for the scale. The problem is I don't where to plug-in that calculated scale-denominater value.. Thx for trying @gomatteo ! – user8723 Sep 17 '12 at 10:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy