maplibre / maplibre-native

MapLibre Native - Interactive vector tile maps for iOS, Android and other platforms.
https://maplibre.org
BSD 2-Clause "Simplified" License
1.01k stars 296 forks source link

Wrong rendering of island/areas near water - Geometry issue with complex polygons? #1843

Open christian2701 opened 10 months ago

christian2701 commented 10 months ago

Discussed in https://github.com/maplibre/maplibre-native/discussions/1836

Originally posted by **christian2701** November 3, 2023 Hello everyone, we are currently working on a conversion of our stack to Maplibre and would also like to provide the raster tiles via Tileserver/Maplibre Native. Unfortunately, there is sometimes a server crash/wrong rendering on islands/areas near water at certain zoom levels. Here is an example in the Venice area for 15/17506/11729.webp. For test purposes I have coloured the corresponding water area yellow: ![11729](https://github.com/maplibre/maplibre-native/assets/48522137/f0613c12-dad7-4572-825d-e3ba53493c05) At "raster" zoom level 14 the data is drawn in correctly: ![correct](https://github.com/maplibre/maplibre-native/assets/48522137/b722afc4-4ec2-4f68-a686-1ba7773ec730) I also have attached the corresponding mbiltes (please remove .txt at the end): [it-nord-est-latest-wateronly-lowres.mbtiles.txt](https://github.com/maplibre/maplibre-native/files/13251477/it-nord-est-latest-wateronly-lowres.mbtiles.txt) And the data in geojson format (please remove .txt at the end): [5864.geojson.txt](https://github.com/maplibre/maplibre-native/files/13251589/5864.geojson.txt) The problem are wrong generated water geometries. These are generated as follows (see also shortbread on which the tiles are based https://github.com/shortbread-tiles/shortbread-tilemaker/blob/main/process.lua#L378-419): ```lua function process_water_polygons(way, way_area) local waterway = way:Find("waterway") local natural = way:Find("natural") local water = way:Find("water") local landuse = way:Find("landuse") local mz = inf_zoom local kind = "" local is_river = (natural == "water" and water == "river") or waterway == "riverbank" if landuse == "reservoir" or landuse == "basin" or (natural == "water" and not is_river) or natural == "glacier" then mz = math.max(4, zmin_for_area(way, 0.01, way_area)) if mz >= 10 then mz = math.max(10, zmin_for_area(way, 0.1, way_area)) end if landuse == "reservoir" or landuse == "basin" then kind = landuse elseif natural == "water" or natural == "glacier" then kind = natural end elseif is_river or waterway == "dock" or waterway == "canal" then mz = math.max(4, zmin_for_area(way, 0.1, way_area)) kind = waterway if kind == "" then kind = water end end if mz < inf_zoom then local way_area = way_area way:Layer("water_polygons", true) way:MinZoom(mz) way:Attribute("kind", kind) way:AttributeNumeric("way_area", way_area) way:ZOrder(way_area) if way:Holds("name") then way:LayerAsCentroid("water_polygons_labels") -- way:MinZoom(13) way:MinZoom(10) way:Attribute("kind", kind) way:AttributeNumeric("way_area", way_area) way:ZOrder(way_area) setNameAttributes(way) end end end ``` The corresponding style for this layer: ```json { "id": "water-area", "type": "fill", "source": "smartmaps", "source-layer": "water_polygons", "minzoom": 12, "filter": [ "all", ["==", "kind", "water"] ], "layout": {"visibility": "visible"}, "paint": { "fill-color": "#a2c1f7", "fill-opacity": 1 } } ``` I have noticed that the water geometries created here sometimes look strange. Besides the actual geometry, a "border" in the upper right corner is created to close the geometry: ![wrong_geometry](https://github.com/maplibre/maplibre-native/assets/48522137/4cf5f62f-42da-4239-8ea2-cccd46d0a9f9) In comparison the OpenMapTiles geometry looks like this and is rendered correct: ![omt_correct_geometry](https://github.com/maplibre/maplibre-native/assets/48522137/bb1c4e29-38fb-41c6-aebf-d4862c6cb52c) In "vector mode" there isn't any issue, the problem only occurs when using the tile mode / raster images. Do you have any ideas or suggestions for analysing the problem in more detail? Thank you very much! Note: I already have mentioned the issue in the tileserver-repo, but I think it could be a maplibre-native issue.
geoneutrino commented 10 months ago

result of the discussion was that xvfb-run -a /opt/test7/mbntest/build/bin/mbgl-render --style=style.json --lat=45.446518 --lon=12.330183 --zoom=16 --width=4000 --height=4000 --output 4000.png with opacity 0.4 shows "something"wrong painted / different to mapliubre-js where this tile works

4000-2

geoneutrino commented 10 months ago

seems to be a "fill" error. Changing to type=line in style.json shows no geometry errors

stefankarschti commented 10 months ago

earcut is being used to triangulate fill polygons. It's very possible that in the above case the error is related to the self intersection of the segments generated to close the geometry in the upper & lower right corners.

acalcutt commented 10 months ago

I attempted to look at the geojson this creates with vt2geojson

vt2geojson https://tiles.wifidb.net/data/it-nord-est-latest-wateronly-lowres/14/8752/5864.pbf > 14-8752-5864.pbf.json

vt2geojson https://tiles.wifidb.net/data/it-nord-est-latest-wateronly-lowres/14/8753/5864.pbf > 14-8753-5864.pbf.json

and i got these two geojson files 14-8752-5864.pbf.json 14-8753-5864.pbf.json

One thing I notice looking at these in google earth is it seems like the main water polygon has some type of line going around the border if the tile image

acalcutt commented 10 months ago

btw, with the rest of the water polygons it doesn't looks like that line shows, just in that 3049430 polygon.

image

acalcutt commented 10 months ago

You can compare with this water layer export from my current planetiler mbtiles file. it doesn't get lines like that. wdb_14-8753-5864_water.pbf.json image

geoneutrino commented 10 months ago

Well spotted @acalcutt The line / border is caused by tilemaker on certain edge cases https://github.com/systemed/tilemaker/issues/574 Thererfore this is not a maplibre-native effect after all So i think we can 99% close this issue and the remaining 1% is the confusion from the start why maplibre-js doesn't show this behavior while native does - some display rules seem to work not 1:1 js vs native ?

systemed commented 10 months ago

Thererfore this is not a maplibre-native effect after all

I think it is at least worth noting, as @geoneutrino says, that Maplibre Native's behaviour here differs from Maplibre JS's. I've verified this with my own vector tiles - in fact I had been wondering why I had a few "burst" coastlines in my app but not when viewed on the web!