-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
the future of labelling #4704
Comments
@ansis Thank you very much for publicly sharing such a detailed logical and high level description. Can you please kindly answer the following?
"Project the line into the plane you want to put the text on (map plane, 3.) In pitched mode lines also show sawtoothed edges/aliasing artifacts.
|
Yep, I was referring to the distortion on labels placed along lines.
Yep, projecting them from tile coordinates to screen pixels if you want labels rendered on the viewport plane.
I'm not sure. I think last time I looked at this lines were pretty ok, except when they are drawn on top of a casing. The way two really thin lines drawn on top of each look isn't great.
I think it might be faster for me to start with JS. and I think we're also more concerned about performance in Javascript and large viewports than on mobile devices. Also, we're now using this repository for general high level issues that span -js and -native. |
😄
Would api-gl continue to use a placement system similar to what we have currently?
Probably would be helpful to talk to support/customer success about customers that use both to see exactly how they use them. I think that most use cases of api-gl don't require the static map to look exactly like the dynamic map. One of the possible concerns might be that users design maps in Studio with a dynamic map preview, so if they are creating that style for use with api-gl they might see unexpected results. Similarly, we're developing a map design tool for showing lots of views of your map style at one time, which currently uses static maps as it's not performant to load so many gl maps on the same page. This workflow might create similar discrepancies.
I think this depends on how they behave. Labels flickering in and out seems like a necessary evil if we want to optimize display for our increasingly versatile camera and styling abilities. Personally I don't think it is in itself a bad thing, but I do find two things very jarring:
It sounds like this new approach would improve at last parts of both of these points. @ansis can you speak more to either of these?
My gut reaction is that this doesn't matter much for dynamic maps, but that's an interesting question 🤔 |
Most of the customers I've seen either use api-gl because:
In some of these cases labelling is quite important (a label not showing up is a big deal so will spend a bit of time tweaking the label position manually and symbol properties to get it right in Studio) and discrepancies between Studio and api-gl would be an issue in some cases. Mostly it's only important for default pitch and bearing. Although there are already discrepancies between GL JS and api-gl labelling with labels being cut off tile borders which is an issue. |
@andrewharvey ohh, thanks for these insights 👍 Just throwing out another issue with our current system:
|
@ansis @ChrisLoer will we be able to improve labels along a line that have a text offset? E.g. if we have access to the full line geometry when calculating placement, can we offset the line first (and analyze |
@nickidlugash yes! We should be able to improve:
The main challenge is doing this fast enough and finding a tradeoff between speed and quality if we need to. |
Based on the work already happening in the viewport label placement branch, here's some potential further areas for label placement improvement that are high priority for the cartography team. Can we discuss/evaluate for feasibility? Some items have already been separated ticketed, and others I can ticket out later if they seem like things we want to pursue: Variable text placement for point labelsThis is the ability for the renderer to assign different placements for a label in order to improve the likelihood that the label will be visible. Add placement logic for a single centered line labelWhile not directly affected by switching to viewport placement, I think this would be useful to consider now while we're refactoring label placement in general. Labeling offset linesImproving the appearance of offset lines has come up many times. We don't currently use any offset line label in our own Mapbox styles due to the rendering issues for curved/angled lines, but we would like to. As we discussed earlier in this ticket, more accurate rendering should be possible with the viewport placement refactor. @ansis @ChrisLoer any further thoughts on this now that the refactor is underway? Cross fading for symbol layout property changesI think cross fading symbols at zoom levels where there are symbol layout changes would greatly improve the appearance of symbols that have either large value differences, or multiple changes simultaneously. City labels in Mapbox Streets at zoom level 8 is a great example, where This was discussed briefly during the viewport placement refactor sprint. My understanding from that conversation was that since we are already implementing fading for symbols in general for all situations when they get shown/hidden, adding this capability should be fairly straight-forward. Symbol spacing along lines that accounts for pitchRight now, symbol spacing does not account for pitch (since anchor placement along a line only gets calculated once when a tile loads), so symbols along a line in the background are closer together (i.e. seem denser) than in the foreground. Ideally the spacing should appear about equal (you could argue that it should actually be less dense in the background, but I think we can separate that issue out from this, since the need to reduce density in the background in general also affects point placement labels). For our Mapbox styles, symbol spacing for pitched labels is most noticeably an issue for highway shields. Based on previous conversations, it seems like the simplest way to reduce the density of symbols in the background is selectively hiding certain anchors based on pitch. This probably will also create more stable label placement than other options. I have concerns that this won't look seamless (the labels will look too dense, and at a certain pitch will switch to looking to sparse), but I think this is hard to evaluate without seeing it. The only other options I can think of right now require either anchor placement or other functions in addFeature to be recalculated every pitch change. @ansis @ChrisLoer can you explain in more detail about the feasibility of doing this? Would you suggest just trying the simpler approach first and seeing if the results are acceptable? Collision boxes for geometriesNot high priority right now. Sometimes it's not desirable to have symbols overlap specific geometries (e.g. admin boundaries). This was briefly discussed during the viewport placement refactor sprint, and seems technically feasible, but we should first see if we can gather enough compelling use cases for this. /cc @ansis @ChrisLoer @mollymerp @mapbox/cartography-cats |
@nickidlugash For handling symbol-spacing and pitch, maybe it would make sense to cut density based on "distance from the camera" instead of the overall pitch of the viewport? So for instance, highway shields in the near field would remain densely placed, but after reaching a certain distance the density would be cut in half (and maybe cut in half again in the far distance). It would be nice to keep the underlying anchor placement calculation in the background if we can get away with it, both to keep the overall placement more stable and to save expensive calculation in the foreground. |
@ChrisLoer Yep, sorry – this is what I had in mind based on our previous conversations, but didn't describe it well above. I'm not sure if the transitions at those certain distances will be jarring, but if this is straightforward to implement then I think it makes sense to try this approach first. Do you think it makes sense to incorporate this into the main viewport placement refactor branch, or to separate it out? |
@nickidlugash I think that should be relatively straightforward, and I suspect it won't be that jarring in most real-world cases. I'll give it a try and if it's easy I'll roll it into the bigger changes. |
Here's the status quo in a pitched view: And here's after removing every other anchor if the anchors have a "perspective ratio" > 1.1 (i.e. they're at least somewhat in the distance). This doesn't help at all for point-placed labels, which we use in Mapbox Streets below zoom level 11. We'd have to come up with some other solution to handle those in pitched views. |
Moving the discussion about symbol spacing/density reduction for pitched labels to it's own ticket: #5086 /cc @ChrisLoer |
@ansis and @ChrisLoer Is it possible to also add support for following kind of symbols as part of the re-write? It will be useful for feature parity with Google Maps and Apple Mapkit. @friedbunny also mentioned this the first time pitched support was added to native. In the current implementation, in pitched mode, the size of the icons depends on its position in the viewport. It would be nice to have an icon-{property} that keeps the size of the icon same at all positions in the viewport irrespective of the map state. |
Hi @mb12, that sounds like adding the properties Although we don't plan to include an |
@ChrisLoer The most conspicuous use cases I have noticed so far are the following:
Is it possible to expose text/pitch scaling value of 1 (perhaps at the style level) if not at the layer level? Another common usecase is the pin dropped on long touch.
|
Viewport collision detection landed! 🎉 Please open separate issues for any followup work that's not already tracked. |
@ChrisLoer, @kkaefer and I talked about making large changes to text rendering and label placement.
Problems
current problems:
text-pitch-scaling
future problems:
Labelling has two subproblems:
Rendering
Up until now
We're still using the sliding-glyph-for-each-segment-that-gets-toggled-on-and-off approach (original devlog). This approach really only works if labels are always rendered on the map plane.
text-pitch-alignment
was added to make labels more legible in pitched views. @ChrisLoer's recent work improves on this. Both of thesetext-pitch-alignment
implementations are workarounds that work fairly well but have some problems because of the limitations of the original implementation.Using a different approach
I think we all agreed that this approach is getting hard to adapt to our needs and is getting harder to understand. We should try something completely different. If we have access to the full line geometry when doing the vertex transform it gets a lot easier and more accurate. The rough algorithm:
We need to figure out a way to do this fast enough that we can do it on every frame.
CPU version
On every every, perform the above algorithm in javascript to transform each symbol vertex into gl coords. Create a new vertex buffer, upload the changes.
Potential concerns:
If performance is good enough this approach is probably ideal.
GPU version
If we can't make the CPU version fast enough here's something we can try:
Encode a fixed size representation of the line in a vertex attribute. Perform the entire algorithm in the vertex shader.
Potential concerns:
Placement and collision prevention
Up until now
We've been doing label placement with a tiled approach where the placement is calculated completely separately for each tile. This approach lets us do cross-tile labels in api gl (where each tile is rendered separately) while having exactly the same labelling as client-side gl maps.
The current approach calculates placement for an entire zoom level at once to reduce flickering. We do this by creating a bunch of boxes that cover the label and collision checking them in 3 dimensions. It was adapted to mostly work in pitched views but this gets harder to do with
text-pitch-alignment
. It will get worse if we support tilting the map further or support z offsets for labels.A different approach
I think we're going to have to do global placement instead of tiled placement in order to:
text-pitch-alignment
properlyThe general idea would be to collect all label data from all tiles/workers and move it to a single thread where we can operate on them all at once.
open questions:
Next steps
I'm going start working on rendering using the CPU vertex transformation approach. @ChrisLoer is looking at his current PRs and seeing what can be merged without waiting for this future work.
The text was updated successfully, but these errors were encountered: