Mapbox-gl-js: Add option to allow overlapping of labels from different sources

Created on 10 Dec 2017  路  16Comments  路  Source: mapbox/mapbox-gl-js

I have a static background for my map and dynamic circles with labels. It seems that in the newest versions, labels collide even if they are from different sources.

This causes some problems. For example, if I have a big label for the town (static) and then a dynamic circle with a label, the town name will become invisible if the label for the circle overlaps with the other label. I would like to see the town name in the background and the label for the circle on top of it. Usually, it may overlap only partially.

There should be an option to allow overlapping of labels if they are from different sources.

feature

Most helpful comment

There's significant overlap between this and #4117, but the proposal there is for a breaking change, and I'd like to explore doing something compatible with the existing style spec. Although I said grouping layers was a can of worms, as I work through possible solutions I'm starting to think it's no wormier than special collision behavior for a single layer, and if we come up with a solution that allows grouping of layers it would allow us to completely replicate what used to be (unintentionally) possible by separating layers into different sources.

I'm imagining a property text/icon-collision-group. If specified, features would only collide against features in the same group. Features without *-collision-group specified would all be in the "default" group. *-ignore-placement would mean "test against my collision group, but when you insert me in the collision index, don't mark me as a member of any group". *-allow-overlap would mean "always insert me, but still mark me as a member of my collision group".

Under the hood, we'd get rid of the notion of an "ignored grid" -- we'd just have one grid, but for every feature we'd track which (if any) collision group it was part of.

I think this would provide a pretty straightforward way to re-implement the previous per-source behavior, and it adds some expressivity. It wouldn't allow us to express something like "allow overlap within the group, but enforce collisions outside the group", but If that turned out to be valuable the underlying plumbing would be in place -- we'd just need to add style properties that allowed for more complicated "collides-with" predicates than the 1:1 mapping proposed here.

@mapbox/gl-core thoughts?

All 16 comments

Assuming you are using text-field for your labels. Did you try text-allow-overlap or text-ignore-placement?

https://www.mapbox.com/mapbox-gl-js/style-spec#layout-symbol-text-allow-overlap
https://www.mapbox.com/mapbox-gl-js/style-spec/#layout-symbol-text-ignore-placement

Yes, but I want that the labels for the circles may not overlap. If I set text-allow-overlap, it also allows overlapping for the label circles which causes the map to be quite unreadable in some cases.

The mapbox-gl-js library 0.39.1 worked perfectly so that the overlapping labels for circles are not drawn, but if a town name and the circle label overlap, they are both drawn.

v 0.42.2: https://jsfiddle.net/7d6rfstf/
v 0.39.1: https://jsfiddle.net/wvbqkz49/

Zoom out until the town label disappears in 0.42.2.

The situation I'd like to achieve is that town labels cannot overlap, circle labels cannot overlap, but town and circle labels can overlap.

Is there any approximation how big change this would be to implement? This is one of the main reasons why I'm using an older version. When having a map showing real-time positions, I don't want that the labels of the static background map constantly disappear and become visible depending on the real-time elements.

馃 Now that we've moved to global collision detection, we probably won't move back to emulating the old behavior in which collision detection didn't work between sources. What might make sense instead is some way to group layers for collision detection purposes... but that might be a bit of a can of worms. In your case, it sounds like maybe it would be sufficient to have a per-layer style option, something like text-allow-overlap-within-layer? So you would allow overlap with other layers, but not within each layer...

To implement that, we'd need to store layer information in the CollisionIndex, so that when did a collision detection lookup we could filter by layer.

That would exactly be the case. Labels in data source which constantly updates (airplanes, trains, etc.) should not overlap (they form the dynamic layer) but they should overlap with all other labels which are considered as the static background. Then moving objects and their labels can change but the background map never changes in any way.

There's significant overlap between this and #4117, but the proposal there is for a breaking change, and I'd like to explore doing something compatible with the existing style spec. Although I said grouping layers was a can of worms, as I work through possible solutions I'm starting to think it's no wormier than special collision behavior for a single layer, and if we come up with a solution that allows grouping of layers it would allow us to completely replicate what used to be (unintentionally) possible by separating layers into different sources.

I'm imagining a property text/icon-collision-group. If specified, features would only collide against features in the same group. Features without *-collision-group specified would all be in the "default" group. *-ignore-placement would mean "test against my collision group, but when you insert me in the collision index, don't mark me as a member of any group". *-allow-overlap would mean "always insert me, but still mark me as a member of my collision group".

Under the hood, we'd get rid of the notion of an "ignored grid" -- we'd just have one grid, but for every feature we'd track which (if any) collision group it was part of.

I think this would provide a pretty straightforward way to re-implement the previous per-source behavior, and it adds some expressivity. It wouldn't allow us to express something like "allow overlap within the group, but enforce collisions outside the group", but If that turned out to be valuable the underlying plumbing would be in place -- we'd just need to add style properties that allowed for more complicated "collides-with" predicates than the 1:1 mapping proposed here.

@mapbox/gl-core thoughts?

I'm imagining a property text/icon-collision-group. If specified, features would only collide against features in the same group.

Sounds good to me!

@ansis and @ChrisLoer Is it possible to add Mapnik's equivalent of clear-label-cache for use cases like this?

https://github.com/mapnik/mapnik/wiki/XMLConfigReference

Is it possible to add Mapnik's equivalent of clear-label-cache for use cases like this?

馃 Interesting, I hadn't thought of that approach... so a set of layers like:

A, B, C (clear-cache), D, E (clear-cache), F

Would be equivalent to:

A, B, C (group 2), D (group 2), E (group 3), F (group 3)

Right? Unless I'm missing something, you could implement the same thing either way (uh, after figuring out how to account for the interaction with ignore-placement and allow-overlap).

I see how it could be attractive to be a little less verbose with the "clear-cache" approach, but against that benefit you introduce a somewhat hard-to-see order-based dependency between layers, which seems like a pretty big downside to me.

If I purely think the JSON file, it would be much easier to define the group name. With the clear-cache approach you should be able to somehow define the correct order between the layers. Or is the order always based on the draw order?

Reading the documentation gives impression that clear-cache approach uses the drawing order. If you can define the group name, it gives more freedom to control the z-order and text overlapping.

This is actually a nice example: https://www.mapbox.com/mapbox-gl-js/example/animate-point-along-route/ See the map while the plane is moving.

Let's centralize discussion in #4117.

We didn't end up making the larger changes discussed in #4117, but PR #6566 (just merged) pretty closely targets this original request.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PBrockmann picture PBrockmann  路  3Comments

aderaaij picture aderaaij  路  3Comments

samanpwbb picture samanpwbb  路  3Comments

bgentry picture bgentry  路  3Comments

stevage picture stevage  路  3Comments