2

I was wondering if someone could help me with a problem that I'm having rendering some maps with mapnik and OSM data.

I'm imported the Australia OSM data from geofabrik into postgis, using osm2pgsql, and this import was successful.

I've then downloaded the OSM world_boundaries shapefile from https://planet.openstreetmap.org/historical-shapefiles/world_boundaries-spherical.tgz

I've setup my basic test style for mapnik like so:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map background-color="#aad3df">
  <Parameters>
    <Parameter name="scale">1</Parameter>
    <Parameter name="metatile">2</Parameter>
    <Parameter name="name"><![CDATA[Victorian Map]]></Parameter>
    <Parameter name="description"><![CDATA[Map of Victoria, based on OpenStreetMap data]]></Parameter>
    <Parameter name="bounds">140.9567,-39.69608,150.56381,-33.9715</Parameter>
    <Parameter name="center">144,-36,4</Parameter>
    <Parameter name="format"><![CDATA[png]]></Parameter>
    <Parameter name="minzoom">4</Parameter>
    <Parameter name="maxzoom">17</Parameter>
  </Parameters>
  <Style filter-mode="first" name="victoria">
    <Rule>
      <PolygonSymbolizer fill="#f2efe9" />
      <LineSymbolizer stroke="#666666" stroke-width="1" />
    </Rule>
  </Style>
  <Layer name="victoria" srs="+init=epsg:3857">
    <StyleName><![CDATA[victoria]]></StyleName>
    <Datasource>
      <Parameter name="file"><![CDATA[data/world_boundaries/world_boundaries.shp]]></Parameter>
      <Parameter name="type"><![CDATA[shape]]></Parameter>
    </Datasource>
  </Layer>
  <Style filter-mode="first" name="roads">
    <Rule>
      <LineSymbolizer stroke="#666666" stroke-width="4" />
    </Rule>
  </Style>
  <Layer name="roads" srs="+init=epsg:3857">
    <StyleName><![CDATA[roads]]></StyleName>
    <Datasource>
      <Parameter name="type"><![CDATA[postgis]]></Parameter>
      <Parameter name="user"><![CDATA[postgres]]></Parameter>
      <Parameter name="dbname"><![CDATA[osm]]></Parameter>
      <Parameter name="key_field"><![CDATA[]]></Parameter>
      <Parameter name="geometry_field"><![CDATA[way]]></Parameter>
      <Parameter name="extent"><![CDATA[-20037508,-20037508,20037508,20037508]]></Parameter>
      <Parameter name="table"><![CDATA[(SELECT name, way FROM planet_osm_roads WHERE highway IN ('motorway', 'trunk', 'primary')) AS major_highways]]></Parameter>
    </Datasource>
  </Layer>
</Map>

I'm also using the generate_image.py script to generate the image:

#!/usr/bin/env python

try:
    import mapnik2 as mapnik
except:
    import mapnik

import sys, os

# Set up projections
# spherical mercator (most common target map projection of osm data imported with osm2pgsql)
merc = 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 +nadgrids=@null +no_defs +over')

# long/lat in degrees, aka ESPG:4326 and "WGS 84" 
longlat = mapnik.Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
# can also be constructed as:
#longlat = mapnik.Projection('+init=epsg:4326')

# ensure minimum mapnik version
if not hasattr(mapnik,'mapnik_version') and not mapnik.mapnik_version() >= 600:
    raise SystemExit('This script requires Mapnik >=0.6.0)')

if __name__ == "__main__":
    try:
        mapfile = os.environ['MAPNIK_MAP_FILE']
    except KeyError:
        mapfile = "vic.xml"

    map_uri = "image.png"

    #---------------------------------------------------
    #  Change this to the bounding box you want
    #
    bounds = (140.9567,-39.69608, 150.56381,-33.9715)
    #---------------------------------------------------

    z = 10
    imgx = 500 * z
    imgy = 500 * z

    m = mapnik.Map(imgx,imgy)
    mapnik.load_map(m,mapfile)

    # ensure the target map projection is mercator
    m.srs = merc.params()

    if hasattr(mapnik,'Box2d'):
        bbox = mapnik.Box2d(*bounds)
    else:
        bbox = mapnik.Envelope(*bounds)

    # Our bounds above are in long/lat, but our map
    # is in spherical mercator, so we need to transform
    # the bounding box to mercator to properly position
    # the Map when we call `zoom_to_box()`
    transform = mapnik.ProjTransform(longlat,merc)
    merc_bbox = transform.forward(bbox)

    # Mapnik internally will fix the aspect ratio of the bounding box
    # to match the aspect ratio of the target image width and height
    # This behavior is controlled by setting the `m.aspect_fix_mode`
    # and defaults to GROW_BBOX, but you can also change it to alter
    # the target image size by setting aspect_fix_mode to GROW_CANVAS
    #m.aspect_fix_mode = mapnik.GROW_CANVAS
    # Note: aspect_fix_mode is only available in Mapnik >= 0.6.0
    m.zoom_to_box(merc_bbox)

    sys.stdout.write('output image to %s!\n' % map_uri)

    # Note: instead of creating an image, rendering to it, and then 
    # saving, we can also do this in one step like:
    mapnik.render_to_file(m, map_uri,'png')

When I generate my image, the roads seem to be in the water, which leads me to think my projections might be off? But I'm not sure, as it's using the default projections that come with the OSM data and the shape files?

OSM/mapnik issue

Does anyone know why this might be occurring?

  • @Juzzbott, what I see so far, the issue is related to the projection of your roads that you work with. Have you tried to establish one mutual EPSG? – Taras Sep 5 '18 at 12:16
  • In the xml, replace the +init=epsg:3857 with the full string from the .py file – AndreJ Sep 5 '18 at 18:26

Your Answer

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

Browse other questions tagged or ask your own question.