mapnik / python-mapnik

Python bindings for mapnik
GNU Lesser General Public License v2.1
160 stars 91 forks source link

Postgis: Empty map when using Python API instead of XML #170

Open oliverbienert opened 6 years ago

oliverbienert commented 6 years ago

Hi,

I have the following xml file:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="#b8dee6">

<Style name="water" filter-mode="first">
  <Rule>
    <PolygonSymbolizer fill="#1d4bd2" />
  </Rule>
</Style>
<Style name="water-outline" filter-mode="first">
  <Rule>
    <LineSymbolizer stroke="#000000" stroke-width="3" stroke-linejoin="round" />
  </Rule>
</Style>
<Layer name="water"
  srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
    <StyleName>water-outline</StyleName>
    <StyleName>water</StyleName>
    <Datasource>
       <Parameter name="type"><![CDATA[postgis]]></Parameter>
       <Parameter name="table"><![CDATA[(SELECT geometry, class FROM layer_water(!bbox!, z(!scale_denominator!))) as t]]></Parameter>
       <Parameter name="geometry_field"><![CDATA[geometry]]></Parameter>
       <Parameter name="extent"><![CDATA[1469505.29396, 6898879.19163, 1480562.84361, 6909936.74128]]></Parameter>
       <Parameter name="dbname"><![CDATA[openmaptiles]]></Parameter>
       <Parameter name="host"><![CDATA[localhost]]></Parameter>
       <Parameter name="port"><![CDATA[5433]]></Parameter>
       <Parameter name="user"><![CDATA[openmaptiles]]></Parameter>
       <Parameter name="password"><![CDATA[openmaptiles]]></Parameter>
       <Parameter name="srid"><![CDATA[900913]]></Parameter>
       <Parameter name="extent_from_subquery"><![CDATA[true]]></Parameter>
    </Datasource>
  </Layer>

</Map>

It renders perfectly:

    merc = Projection('+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over')

    box2d = Box2d(*data['bbox'])
    box2d = box2d.forward(merc)
    x, y = data['publish_extent']
    srs = merc.params()
    m = Map(x, y, srs)
    m.zoom_to_box(box2d)

    load_map(m, '/home/oliver/mapnik/Water_postgis_subquery.xml')

    filename = create_unique_filename(suffix='.png')
    render_to_file(m, filename, 'png')

    filename = create_unique_filename(suffix='.svg')
    surface = cairo.SVGSurface(filename, m.width, m.height)
    render(m, surface)
    surface.finish()

However, it renders an empty map when I try to use the Python API:

    m.background = Color('steelblue')

    s = Style()
    r = Rule()
    polygon_symbolizer = PolygonSymbolizer()
    polygon_symbolizer.fill = Color('#1d4bd2')
    r.symbols.append(polygon_symbolizer)
    line_symbolizer = LineSymbolizer()
    line_symbolizer.stroke = Color('#000000')
    line_symbolizer.stroke_width = 3
    line_symbolizer.stroke_linejoin = 'round'
    r.symbols.append(line_symbolizer)
    s.rules.append(r)
    m.append_style('Water', s)

    ds = PostGIS(
        host='localhost',
        port='5433',
        user='openmaptiles',
        password='openmaptiles',
        dbname='openmaptiles',
        srid=900913,
        table='(SELECT geometry, class FROM layer_water(!bbox!, z(!scale_denominator!))) as t',
        geometry_field='geometry',
        extent=', '.join(map(str, [box2d.minx, box2d.miny, box2d.maxx, box2d.maxy])),
        extent_from_subquery=True
    )

    layer = Layer('water')
    layer.datasource = ds
    layer.styles.append('Water')
    m.layers.append(layer)

It caused me headaches almost two days before I tried the xml way. And I can't spot the difference. The hardcoded extent string in the xml is exactly the same as returned by box2d, so that's not the culprit I think.

What do I miss here?

dorukozturk commented 6 years ago

@oliverbienert This happened to me before. I think you have to set the layer.srs.

layer.datasource = ds
layer.srs = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
layer.styles.append('Water')
m.layers.append(layer)

For example this.

oliverbienert commented 6 years ago

Thank you for spotting this! It's obvious, once you know it, isn't? In the xml, I actually did set the layer's srs. I'll try if that works for me in the next couple of days.