Mapbox-gl-js: Road name label density badly calculated based on text-size

Created on 6 Apr 2018  ·  9Comments  ·  Source: mapbox/mapbox-gl-js

v0.44.1 @ Chrome 65 @ Windows 10:

Steps to Trigger Behavior

  1. I have created custom map data and style in Casablanca, and as road name labels in Mapbox examples look bad in that area it can most likely be reproduced with your data also.
  2. I have excluded mostly every other layer for this to be more obvious.
  3. I keep everything as a constant, only thing that changes is text-size : stops for label layer.

Expected Behavior

image
with:

                "text-size": {
                    "stops": [ 
                        [ 12, 10 ],
                        [ 19, 10 ],
                        [ 20, 16 ]
                    ]
                }

Actual Behavior

Now i only change this:

                               "text-size": {
                    "stops": [ 
                        [ 12, 10 ],
                        [ 14, 10 ],
                        [ 20, 16 ]
                    ]
                }

And result is this:

image

How is this possible on zoom level 12, especially with stop [ 14, 10 ]?
And even better how does stop [ 19, 10 ], fixes this problem?
This is simplified example but this effect destroys map quality in certain areas of the globe where there are less POIs and other labels.

bug

All 9 comments

Can you please set up a minimal reproducible test case so that we could diagnose the issue? Also, you might want to set map.showCollisionBoxes = true to see what's going on.

Hmm, this looks not related to Mapbox GL — more likely an issue with how Mapbox Streets generalizes road labels on lower zoom levels. cc @ajashton

I am not sure what "generalizes labels means", but I have same behavior without Mapbox Studio, with my own data, tileset and style where all streets have name attribute, but only 1 in entire tile is displayed.
Crazy thing that changing stop which logically should not have impact on rendering on some level changes density. btw thanks for such fast reaction, did not expect this 👍

How is this possible on zoom level 12, especially with stop [ 14, 10 ]?
And even better how does stop [ 19, 10 ], fixes this problem?

@watbywbarif That is indeed confusing behavior! The reason the seemingly-unrelated [ 19, 10 ] fixes the problem is that when we're doing layout is that our getAnchors function does its calculations based on a text-size that's always evaluated at zoom level 18. The evaluation happens here:

https://github.com/mapbox/mapbox-gl-js/blob/866ab7b46635f619347334da6e1baa2cc10e7ecf/src/symbol/symbol_layout.js#L93

The reason we use zoom level 18 regardless of the actual zoom of the tile you're showing is that we want the "anchors" for road labels to show up in similar places as you move between zoom levels, even if the size of the text is changing. There's some discussion of this behavior as "case (4)" at https://github.com/mapbox/mapbox-gl-js/issues/5683#issuecomment-371329406. In short, we think we should remove the behavior or change it, because it doesn't seem to work that well.

I _suspect_ the reason you're seeing labels drop may be that this "max angle" check is failing:

https://github.com/mapbox/mapbox-gl-js/blob/866ab7b46635f619347334da6e1baa2cc10e7ecf/src/symbol/get_anchors.js#L96-L98

The angleWindowSize depends on the text-size at zoom 18, and effectively makes us stricter about how we enforce the text-max-angle style property. The default for that value is "45 degrees" and the docs say it's "the maximum angle change between adjacent characters", but in fact it's an approximation of that based on text-size.

The upshot of all this is that a promising workaround in your case may be to try setting text-max-angle to something higher like "90" to see if that solves the problem!

/cc @nickidlugash @ansis

On the other hand, it's also possible that the labels are getting filtered out because there doesn't appear to be enough space for even a single label in the middle of the line:

https://github.com/mapbox/mapbox-gl-js/blob/866ab7b46635f619347334da6e1baa2cc10e7ecf/src/symbol/get_anchors.js#L87-L92

If that's the case, change text-max-angle won't help.

You could do something really crazy like adjust your zoom stops so the text is small (e.g. 10 point) at _exactly_ zoom 18, but larger at zoom 17.99 and zoom 18.01. Then you could hook the map's zoom events to make it so that the map never actually rendered exactly zoom 18. But hopefully it doesn't come to that, because that's a crazy hack. 🤔

@ChrisLoer Is there some way to force the symbol layout engine to generate anchors for lines where the length of line is slightly smaller than the label (perhaps by using negative text-padding)? It would be useful to create a style similar to what the current waze application uses ('Rexford Way, 'Mansfield Dr', 'Princes Anne Dr' etc in the attached screenshot ).

img-0983

@mb12 unfortunately, no: the relevant code is placeGlyphAlongLine in projection.js -- we use the actual road geometry for placing glyphs, and we hide the whole label if we can't place any one of the glyphs in the label. We'd have to explicitly add support for extrapolating the geometry past the end of the road.

I did play with text-max-angle even before posting this issue, but it was not nice. I even think that some letters overlapped one over another when angle was big enough.

One solution which I was thinking is to use fixed text-size in three to four size groups (small, ..., large). Then to use zoom level dependent filtering and move road classes between size groups from small to large. In that way i expect go get label size dependent on road importance and also to increase with zoom level. But now I guess it will be bad because the same reason you are using only one size to calculate placement. Labels will be "jumpy" :)

Now I can play and hack, but maybe there is some good solution for future versions.
I can suggest one: Try to calculate label placement in 2-3 steps incrementally. First time at text-size at zl 18 like you are doing now. But then if actual zl is 11-14 you do one more calculation using zl 14 text-size, but keep fixed results you have from zl 18. Any maybe once more same story when you get below zl 10.

Was this page helpful?
0 / 5 - 0 ratings