Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to allow overlapping of labels from different sources #5836

Closed
ttsirkia opened this issue Dec 10, 2017 · 16 comments
Closed

Add option to allow overlapping of labels from different sources #5836

ttsirkia opened this issue Dec 10, 2017 · 16 comments

Comments

@ttsirkia
Copy link

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.

@pathmapper
Copy link
Contributor

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

@ttsirkia
Copy link
Author

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.

@ttsirkia
Copy link
Author

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.

@ttsirkia
Copy link
Author

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.

@ttsirkia
Copy link
Author

ttsirkia commented Jan 5, 2018

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.

@ChrisLoer
Copy link
Contributor

🤔 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.

@ttsirkia
Copy link
Author

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.

@ChrisLoer
Copy link
Contributor

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?

@ansis
Copy link
Contributor

ansis commented Jan 19, 2018

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!

@mb12
Copy link

mb12 commented Jan 19, 2018

@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

@ChrisLoer
Copy link
Contributor

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.

@ttsirkia
Copy link
Author

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?

@ttsirkia
Copy link
Author

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.

@ttsirkia
Copy link
Author

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.

@jfirebaugh
Copy link
Contributor

Let's centralize discussion in #4117.

@ChrisLoer
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants