systemed / tilemaker

Make OpenStreetMap vector tiles without the stack
https://tilemaker.org/
Other
1.5k stars 232 forks source link

Polylabel algorithm operation #785

Open pavel-avilov opened 2 days ago

pavel-avilov commented 2 days ago

Hi, could you please explain how does the polylabel algorithm work in the LayerAsCentroid/Centroid methods.

As I understand, the polylabel algorithm should find the point that is the most distant from any edge. I've noticed that some of the house numbers are located a little strangely. I've used the LayerAsCentroid method (just like in your process-openmaptiles.lua) to save the house number info.

Examples of strange housenumber placement with default styles:

hn1 hn2

For example, on the last screenshot the house number for way is located at the following coordinates: lat: 51.536720348065 lon: -0.1600334265625

hn3

In OSM it looks like this:

osm1

I decided to double-check the work of polylabel on this house using Python-Polylabel

I ran the following:

polylabel([[51.5372152, -0.1604443], [51.5371332, -0.1606558], [51.5365747, -0.1600228], [51.5365893, -0.1599317], [51.5366517, -0.1597992], [51.5372152, -0.1604443]])
The code as I checked: ``` from OSMPythonTools.overpass import Overpass from polylabel import polylabel overpass = Overpass() way_id = '501460502' query = f'way({way_id}); out geom;' result = overpass.query(query) all_coord = [] # Get way coords for way in result.ways(): print(f'Way ID: {way.id()}') print('Coordinates:') for coord in way.nodes(): print(f'Latitude: {coord.lat()}, Longitude: {coord.lon()}') all_coord.append([coord.lat(), coord.lon()]) print(f"polylabel({all_coord}) >") print(polylabel([all_coord])) ```

and then I got lat: 51.53688964928815 lon: -0.16022586209752077 In OSM it looks like this:

osm2

Actually, tell me pls, is this behaviour normal? Why does LayerAsCentroid place the housenumber for https://www.openstreetmap.org/way/501460502 at 51.536720348065, -0.1600334265625, not at 51.53688964928815, -0.16022586209752077?

cldellow commented 2 days ago

tilemaker's polylabel is mainly a port of MapBox's.

One difference might be the default value of the precision parameter. MapBox's precision is 1 (this appears to be the same for python-polylabel), but tilemaker's is 0.00001.

tilemaker chose the smaller precision because tilemaker operates in terms of longitude and latitude, and from MapBox's readme:

Be careful to pick precision appropriate for the input units. E.g. in case of geographic coordinates (longitude and latitude), 0.000001 is appropriate, while the default (1.0) would be too imprecise.

Do you get the same results as tilemaker if you choose a precision of 0.00001?