Open bdon opened 1 year ago
My work around recommendation is to have -1, 0, 1, and a single new MapLibre style layer for "even higher bridges" (level = 2, 3, 4, 5, 6).
That way you avoid parsing the MVT in MapLibre "again, again, again" looking for features at those levels per style layer – when mostly no MVT data layer features are found to be eligible for the GL style layers.
Ideally the "inline" and "outline" are in the same GL style layer and could use the existing sort_key
from Tilezen (which would need a port over to this repo). But the explosion of MapLibre style layers for each kind
and the levels is already burdensome...
@nvkelso I don't think there is still any solve for what you described like tilezen sort_key
because of intersections? https://github.com/maplibre/maplibre/discussions/164#discussioncomment-4925345
So we need have 4 levels, say 5 road classes, and casings/inner strokes, 4x5x2 = 40 layers...
Unless you think we can combine all road classes into a single layer with expressions
Not so flexible alternative is this: https://github.com/wipfli/single-highway-layer
@wipfli what if styles weren't embedded in the properties, but you had a single layer for all classes, and the paint properties were a (very big) case statement? So a complete stack would be like
tunnels_casing
tunnels
ground_casing
ground
bridges_casing
bridges
bridges_2_casing
bridges_2
Instead of having motorway
, primary
, etc.
Yes the case
approach works. A limitation is that MapLibre GL JS currently does not support data-driven line-dash arrays and some other properties like line-caps. Maybe worth talking to @zelonewolf and others from the American map style. They run into the same problem.
Agreed, it's capability gap in the current maplibre-gl-js and we've resorted to very inefficient techniques to resolve it in Americana.
So if we designed around the constraint that there are no variation in linecaps or dashes, we can get away with the total set of ~8 road layers I listed above - it would be cleaner in the number of layers, and have beastly match
/case
expressions - is this really better for performance than having 40 layers, or about the same?
regarding performance cc @msbarry
Currently most of the processing time for each tile is evaluating each filter expression on each feature. I want to make a change that will make that more of a constant time for each feature regardless of how many layers there are. I need to set up new benchmarks in maplibre first though https://github.com/maplibre/maplibre-gl-js/issues/982
Looking at tag info for stats: https://taginfo.openstreetmap.org/keys/layer#values
96.99% of layer
tags are -1
, 0
or 1
.
We can try a hybrid approach of @wipfli 's for the other 3.01% where a casing feature is duplicated in the tileset - this should have minimal bloat
So the complete stack of "normal" road symbology for all kinds is
roads_tunnel_2_minus
roads_tunnel_1_casing
roads_tunnel_1
roads_0_casing
roads_0
roads_bridges_1_casing
roads_bridges_1
roads_bridges_2_plus
For a total of 8 road MapLibre GL layers supporting an arbitrary # of flyover levels and tunnels.
A style can already support an arbitrary # of layers by using data-driven line-color
to visually distinguish each layer
. This looks a bit weird aesthetically, and using casings is better in the majority of cases...
"line-color":["rgb",["-",255,["*",20,["to-number",["get","layer"]]]],255,["-",255,["*",20,["to-number",["get","layer"]]]]],
proof of concept working:
The main problem now is the lack of data-driven line endings, because using butt
will show seams, and using Round will end up like this:
Planet build proof of concept live: 5 road classes, unlimited stacking, 8 MapLibre layers:
Relevant MapLibre issue: https://github.com/maplibre/maplibre-gl-js/issues/2108
In order to make correct casing ordering on complex overpasses, we may need to change Tilezen - Tangram relied on
sort_rank
with casings to overlay an arbitrary number of layers. For MapLibre GL we havesort_key
in the style but that only works per-layer: casings needs to be drawn as separate layers.In my experience the only solution is to have a fixed set of layers each with their own filter e.g. layers -2, -1, 0, 1, 2. @nvkelso