mapnik / python-mapnik

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

Bug? ignore_placement has no effect #216

Open larsga opened 4 years ago

larsga commented 4 years ago

Below is a complete, standalone test that uses the Natural Earth world shapefile and places two white dots on it, one at (10, 60) and one at (7, 57). Only one dot appears in the PNG output, despite ignore_placement = True. Changing the coordinates of the second dot to (6, 56) makes it appear.

Am I doing something wrong, or is the implementation of ignore_placement broken?

Here is the test case:

import json
import mapnik

m = mapnik.Map(1000, 500)
m.background = mapnik.Color('steelblue')

s = mapnik.Style()
r = mapnik.Rule()
polygon_symbolizer = mapnik.PolygonSymbolizer()
polygon_symbolizer.fill = mapnik.Color('#f2eff9')
r.symbols.append(polygon_symbolizer)
s.rules.append(r)

m.append_style('My Style',s)

ds = mapnik.Shapefile(file = '/Users/larsga/Desktop/ne_10m_admin_0_countries/ne_10m_admin_0_countries.shp')
layer = mapnik.Layer('world')

layer.datasource = ds
layer.styles.append('My Style')

m.layers.append(layer)

m.zoom_all()

### add in dots

with open('/tmp/white.svg', 'w') as f:
    f.write('''
            <svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
              <circle cx="5" cy="5" r="5" stroke="#000000" fill="#FFFFFF"/>
            </svg>
    ''')

point_symbolizer = mapnik.PointSymbolizer()
point_symbolizer.file = '/tmp/white.svg'
point_symbolizer.allow_overlap = True
point_symbolizer.ignore_placement = True

r = mapnik.Rule()
r.symbols.append(point_symbolizer)

s = mapnik.Style()
s.rules.append(r)

m.append_style('basic_style', s)

ds = mapnik.MemoryDatasource()

ctx = mapnik.Context()

f = mapnik.Feature.from_geojson(json.dumps({
    "type": "Feature",
    "geometry": {
        "type": "Point",
        "coordinates": [10, 60]
    }
}), ctx)
ds.add_feature(f)

f = mapnik.Feature.from_geojson(json.dumps({
    "type": "Feature",
    "geometry": {
        "type": "Point",
        "coordinates": [7, 57]
    }
}), ctx)
ds.add_feature(f)

l = mapnik.Layer('main_map')
l.datasource = ds
l.styles.append('basic_style')

m.layers.append(l)

mapnik.render_to_file(m,'world.png', 'png')
larsga commented 4 years ago

I was eventually able to work around this by putting each feature into a separate layer, and setting clear_label_cache = True.