basemaps icon indicating copy to clipboard operation
basemaps copied to clipboard

Missing parts on rivers

Open mxzinke opened this issue 8 months ago • 14 comments

Impacted Features/Layers

Long rivers like the "Elbe" or "Danupe" are kind of cluttered on low zooms (~7). This also happens in various other places/rivers.

Screenshots

Image High Zoom (~8) Image Low Zoom (~7)

My thoughts on the issue/solution:

I suspect that the reason for this issue comes from the complex relations within OSM dataset, which splits it into multiple polygons. I am not really into the planetiler framework, but I think it would make sense to add some relation management for rivers/streams/canals/riverbanks and combine into MultiPolygons in post-process.


I would appreciate it if someone could me give me some feedback on my thoughts and a brief overview of how the relations should be implemented. I would be happy to implement this, but I failed so far.

mxzinke avatar Apr 24 '25 09:04 mxzinke

Thanks for opening this issue @mxzinke!

When refactoring Water.java we worked a bit on rivers breaking up at low zoom levels. Probably the issue is not related to feature selection based on tags and relations, because when you zoom in, the full river is there. If we had a problem with selecting river polygons based on way/relation tags, then parts would be missing at all zoom levels...

What is more likely to be the cause is that parts of a river polygon fall below the minimal area during post-processing here:

https://github.com/protomaps/basemaps/blob/11807bba74dcb35f27338e4b9274509c838330d4/tiles/src/main/java/com/protomaps/basemap/layers/Water.java#L437

This includes only features in the tiles which are larger than Earth.MIN_AREA (linear dimension in tile pixels, so 1 means a 1x1 square, 2 means a 2x2 square etc).

You can experiment with the function mergeNearbyPolygons and change some settings. Buffer and min feature size has quite some effect on the visual output. Let me know if you need any help getting started.

wipfli avatar Apr 25 '25 06:04 wipfli

River polygons in OpenStreetMap can be split into multiple ways, e.g., something like this:

Image

The middle section shares nodes with the outer sections. To merge them into one polygon, we need to apply a buffer and run merge nearby polygons. This should create something like

Image

However, if you apply too much buffering then the result on S-shaped rivers like this example:

Image

Will become something like this:

Image

So it will look a bit like a string of pearls, which is probably also not what we want.

wipfli avatar Apr 25 '25 06:04 wipfli

Note that FeatureMerge.mergeNearbyPolygons works on tile pixels, and each tile has 256 pixels. If we consider zoom 7, that means a pixel width of roughly

earth circumference / 2 ** 7 / 256 = 1200 m

At zoom 8 it would be

earth circumference / 2 ** 8 / 256 = 600 m

So you see that as the zoom level increases, the buffering decreases...

wipfli avatar Apr 25 '25 06:04 wipfli

Okay, thanks @wipfli for clarifying. I took a deeper look into it.

First, I can clearly say that its really just about rivers. Impacted zoom are 7 and 8. On 9 it is already correctly put together. On zoom 6 or lower, river should be hidden since they are too small anyway.

I also noticed, I can add the waterway lines on lower zooms and add them in the style as a layer below the river polygons. But's an ugly fix. So I looked into you suggesting increase of buffering. Here are my results:

Image Image

Here the code I used for that in Water.java layer class:

  @Override
  public List<VectorTile.Feature> postProcess(int zoom, List<VectorTile.Feature> items) throws GeometryException {
    items = FeatureMerge.mergeLineStrings(items, 0.5, Earth.PIXEL_TOLERANCE, 4.0);

    double mergeFactor = 1;
    if (zoom <= 7) {
      mergeFactor = 16;
    } else if (zoom <= 8) {
      mergeFactor = 12;
    } else if (zoom <= 9) {
      mergeFactor = 8;
    } else if (zoom <= 10) {
      mergeFactor = 2;
    }

    double buffer = Earth.BUFFER;
    if (zoom >= 7) {
      buffer = Earth.BUFFER * Math.pow(2, (zoom - 6) / 2);
    }
    
    return FeatureMerge.mergeNearbyPolygons(items, 0, Earth.MIN_AREA, 1 * mergeFactor, buffer);
  }

I modified the minArea to be zero (just to test out), gave a higher minDist for merging and a buffer scaling up exponentially

As you can see, not much of a difference. Just some minor details more. I also tested out a bigger Buffer, but this causes the issues already described...


Additionally, I looked into the planetiler-openmaptiles Planetiler-Profile and found out that they're using the osm relations to create WaterwayRelation internally. Could we do similar to make sure polygons relating to the same OSM-Way and are actually combined? Hope it's somehow clear, what I mean.

https://github.com/openmaptiles/planetiler-openmaptiles/blob/3f520f5ab3dc895800feac4764d0476bb0ddaa54/src/main/java/org/openmaptiles/layers/Waterway.java#L146C1-L155C4


Would be awesome to not just workaround these kind of issues, but actually find a robust solution. What do you think?

mxzinke avatar Apr 25 '25 12:04 mxzinke

Can you share an OpenStreetMap way id of a feature which does not get included at zoom 7?

wipfli avatar Apr 25 '25 12:04 wipfli

Example the 'Elbe' very long river - Relation 123822 - here are some examples:

Parts shown only on zoom 9 and higher - OSM Way IDs

Parts shown only on zoom 8 and higher - OSM Way IDs:

Is this helpful? Do you need more examples from other rivers?

mxzinke avatar Apr 25 '25 15:04 mxzinke

From what I can tell so far is that the river parts here have exactly the same tags as neighboring river tags. So I think they get through the process function in the same way. However, it probably fails during postProcess to merge and include them. Do you think that is correct?

wipfli avatar Apr 29 '25 14:04 wipfli

Could be the cause within postProcess, but wouldn't it be easier to handle the river parts similar to the boundaries layer - via OsmRelationPreprocessor / through the relations? Then we could merge all river parts with same relation in postProcess. Or do I miss something?

mxzinke avatar Apr 30 '25 08:04 mxzinke

It might be worth giving relation processing on rivers a try. Feel free to open a pull request. My understanding is just that during feature selection, all river parts get selected. So even with relation processing, you don't get more selected features. But then during post-processing, i.e., mergeNearbyPolygons, the river parts for some reason don't get merged, then they fall below the area limit and are removed...

wipfli avatar May 01 '25 06:05 wipfli

@wipfli Are they removed based on area before or after merge? (Since we set Earth.MIN_AREA as a min area on FeatureMerge.mergeNearbyPolygons() in post processing)

mxzinke avatar May 05 '25 14:05 mxzinke

I think they are dropped after merging, see https://github.com/onthegomap/planetiler/blob/2c91725f6d048fd60b02d3e7c29bb88838451048/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java#L361

wipfli avatar May 05 '25 18:05 wipfli

I am a bit of stuck with this issue. And in my eyes, it impacts the visual appeal of the map a lot.

@wipfli Do you know who knows more about it and maybe has more ideas on a potential solution?

mxzinke avatar Jun 02 '25 08:06 mxzinke

I don't unfortunately

wipfli avatar Jun 02 '25 12:06 wipfli

Tilezen for reference doesn't show many rivers until z8:

https://pmtiles.io/#map=7.12/50.91/12.549&url=https%3A%2F%2Fr2-public.protomaps.com%2Fprotomaps-sample-datasets%2Ftilezen.pmtiles

I can add the waterway lines on lower zooms and add them in the style as a layer below the river polygons. But's an ugly fix.

I think this is actually the correct solution, because any polygon representing a river's width is going to degenerate to 0 area as we zoom out, and it's not an efficient way to store a linear geometry (double the vertices).

That means at high zooms rivers are doubly represented by both their centerlines (LineString kind=river) and areas (Polygon kind=riverbank)

It looks like right now it's possible for some rivers/canals to have polygons at mid zooms but their centerlines are not appearing ....

bdon avatar Jun 05 '25 21:06 bdon