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

symbol-placement: line-center #6821

Merged
merged 2 commits into from
Jul 3, 2018
Merged

symbol-placement: line-center #6821

merged 2 commits into from
Jul 3, 2018

Conversation

ChrisLoer
Copy link
Contributor

@ChrisLoer ChrisLoer commented Jun 14, 2018

This is a potential implementation of #5061. Currently, it does the simplest thing possible, which is to just place labels in the middle of the line, ignoring text-max-angle limitations. I think we should actually implement some form of text-max-angle support (either hiding labels that don't pass or moving them away from center until they do pass).

I added a simple test case using one of our Berlin test tiles:

screenshot 2018-06-14 14 52 23

I think it highlights one of the potential problems with using "line-center" on data in existing sources: the data is kind of organized by features (I have feature IDs mapped to colors in this example), but those features can be broken down into individual lines in ways that might not make much sense to a style designer. And of course the "center" they have in mind could easily be the center of multiple joined features.

I know @ajashton and @nickidlugash had in mind using this specifically on source layers designed for center labeling (e.g. a center line for a body of water)... to get a better feel for that use case, it would be helpful for us to design an actual vector tile taking advantage of the large buffers to do center-placing across tile boundaries. We can't just use GeoJSON like we do in most tests because that'll automatically get chopped up at tile boundaries (huh, I guess that could be an issue for someone trying to add cross-tile center-placed labels at runtime, too).

  • briefly describe the changes in this PR
  • write tests for all new functionality
  • document any changes to public APIs
  • post benchmark scores
  • manually test the debug page
  • tagged @mapbox/studio and @mapbox/maps-design if this PR includes style spec changes

/cc @ansis

@ChrisLoer
Copy link
Contributor Author

@mourner pointed out that maybe it makes sense to use mergeLines on features with symbol-placement: line-center. I tried it out on the same Berlin tile and ended up with:

screenshot 2018-06-19 11 28 02

Just looking at the image, I don't think there's much of a win in terms of developing an intuition for what the "center" of a line really means. On the other hand, using mergeLines could undermine explicit decisions made in the data layer to support line-center placement... so I think it probably makes sense to skip the merge step?

@ajashton
Copy link
Member

On the other hand, using mergeLines could undermine explicit decisions made in the data layer to support line-center placement... so I think it probably makes sense to skip the merge step?

Agree. I think it's fine that line-center will require special consideration / prep of the underlying data. We already have a similar prep requirement for the much more basic task of labeling a polygon (without repeated labels across tiles).

@nickidlugash
Copy link

to get a better feel for that use case, it would be helpful for us to design an actual vector tile taking advantage of the large buffers to do center-placing across tile boundaries.

@ChrisLoer We have line geometries in the marine_label layer of mapbox-streets-v7 that are formatted for this purpose – will that work for testing? (I pulled this branch and took a look at these on the debug page – looks 👌 !)

@ChrisLoer
Copy link
Contributor Author

@ChrisLoer We have line geometries in the marine_label layer of mapbox-streets-v7 that are formatted for this purpose – will that work for testing?

Yeah, if you could point me to a good tile in streets-v7 to test against (preferably one in which the label will go well past the edge of the tile), I can download that as a fixture and write a test case around it.

For text-max-angle, does the "don't show anything if max angle check doesn't pass" behavior sound right to you?

@nickidlugash
Copy link

if you could point me to a good tile in streets-v7 to test against (preferably one in which the label will go well past the edge of the tile), I can download that as a fixture and write a test case around it.

Tiles 4/4/7 and 4/5/7 are adjacent tiles that have a relevant line crossing the two of them.

For text-max-angle, does the "don't show anything if max angle check doesn't pass" behavior sound right to you?

I think this sounds right. What is the alternative – disabling text-max-angle for symbol-placement: line-center? Although I imagine that anyone using this placement method would be pretty lenient on the max angle (since the label is not repeated), I could still see wanting the option to hide any labels that look really distorted. I think I would just want to double check that the text-max-angle default of 45 is reasonable for center lines. If necessary, we could make the default different depending on the symbol placement (since we do have precedent for dependencies in default values), but hopefully we wouldn't have to add this complexity.

By the way, some food for thought: the symbol-placement property is not data-driven, and my understanding is that we're not likely to make it DDS anytime soon due to the level of complexity (since it has many cascading changes to the rendering of a symbol). If we are interested in making different line placement options data-driven, it may be simpler to add a new style property for line placement behavior (so center line behavior would look something like symbol-placement:line + line-placement:center). I raised this question to others on the cartography team, and we all don't have any strong feelings right now towards needing to make line placement behavior data-driven. So this current implementation of the style spec seems fine (all else equal, adding an additional value to an existing property rather than a new property seems desirable), but I just wanted to raise the issue for others to consider as well.

@ChrisLoer
Copy link
Contributor Author

What is the alternative – disabling text-max-angle for symbol-placement: line-center?

Either disabling it, or relaxing the "center" part and trying to re-sample until we find something close to the center that still fits. I think just hiding sounds right, though, I'm implementing it now.

So this current implementation of the style spec seems fine (all else equal, adding an additional value to an existing property rather than a new property seems desirable), but I just wanted to raise the issue for others to consider as well.

Yeah that is good food for thought, although I don't feel like I could say anything very informed about it. I think implementation-wise it would not be too hard to make something like line-placement: center data-driven since there's not much change to the rendering code. Do we have any use cases in mind where we'd want this to be data-driven?

@ChrisLoer
Copy link
Contributor Author

Here's a render of just 4/5/7:

screenshot 2018-06-21 13 47 33

You can see the line for the marine_label gets clipped at the tile boundary, but the center-placed label itself is allowed to render far off the edge of the tile.

Writing the test made me realize some problems, though... if we allow line-center symbols to be added outside of the drawing area:

  • If collision detection is off, we can get double-draw for the same label present in two adjacent tiles.
  • If collision detection is on, only one of the symbols will draw 👍. But the two symbols from adjacent tiles won't have the same crossTileID (because their tiles don't have a parent/child relationship). So if you rotate the map and thus change which tile gets placed first, the "placed" one can swap states with the "not-placed" one, and that's going to show up as a flickery fade-in/out.

🤔 I don't have an immediate strategy in mind for addressing those issues -- I think it would require something like a CrossTileSymbolIndex that could handle arbitrary tile relationships (any other ideas @ansis?). On the other hand, the problems might not be that bad...

We could also try to avoid including the "same" label in multiple tiles, but then you'd have the downside that you'd depend on one particular tile getting loaded to show the label.

@ChrisLoer
Copy link
Contributor Author

Err, after thinking about this for a second more, it occurs to me that I probably just imagined the "draw symbols anchored outside the tile boundaries" requirement. I think the actual requirement may just be that the labels themselves should be able to draw across tile boundaries -- in which case we'd be able to skip the problems I just brought up.

The only downside would be the same as in the "only include data in a single tile" case... The tile containing the center-point of the label would have to be loaded before a label could show, so for example you might expect a label that looked like "Carr..." clipped against the right edge of the screen, but it wouldn't start displaying until you moved a bit further to the right, you loaded the tile that contained the center of the label, and "Carribe..." started showing clipped against the right edge.

@nickidlugash
Copy link

The tile containing the center-point of the label would have to be loaded before a label could show

@ChrisLoer – @ajashton and I both think this behavior is fine 👍

@ansis
Copy link
Contributor

ansis commented Jun 26, 2018

The tile containing the center-point of the label would have to be loaded before a label could show

Yep, I agree. We already have this behavior for all non-centered labels so if we need to fix it we'll need to find a way that works for all labels.

@ChrisLoer ChrisLoer changed the title WIP: symbol-placement: line-center symbol-placement: line-center Jun 26, 2018
@ChrisLoer ChrisLoer requested a review from ansis June 26, 2018 17:45
@ChrisLoer
Copy link
Contributor Author

OK, I think this is ready to go pending review/edits, then!

@samanpwbb do you or anyone from Studio want to weigh in before we publish this? I think from a Studio UI point of view this should be pretty simple, my only concern would be that using symbol-placement: line-center effectively requires more awareness/coupling with the underlying data than just using symbol-placement: line, so it has a bit of that "advanced feature" smell.

@@ -861,6 +861,9 @@
},
"line": {
"doc": "The label is placed along the line of the geometry. Can only be used on `LineString` and `Polygon` geometries."
},
"line-center": {
"doc": "The label is placed at the center of the line of the geometry. Can only be used on `LineString` and `Polygon` geometries. Note that a single feature in a vector tile may contain multiple line geometries. The center is calculated based on the entirety of the geometry included in the tile buffers, and the label may extend past the edge of the tile."

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@samanpwbb you may want to review this description, since Studio will display this text for the property value tooltip.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is a little on the long side. Is the last sentence necessary?

@ChrisLoer ChrisLoer requested a review from mollymerp July 2, 2018 18:12
Copy link
Contributor

@mollymerp mollymerp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks good to me! it might be a good idea to add some unit tests for this but the render tests are looking good so I'm not toooo concerned
also I think we'll need to add some ignores to gl-native for this one 😅

glyphSize: number,
boxScale: number): number {
return shapedText ?
3 / 5 * glyphSize * boxScale :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a comment explaining the magic 3/5 number might be a good idea 🔢

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ansis or @nickidlugash do you know the origin of this magic number? I guess I just assumed it was something "experimentally reasonable".

@ChrisLoer
Copy link
Contributor Author

Good idea on unit tests for getCenterAnchor, I'll put some in.

@@ -861,6 +861,9 @@
},
"line": {
"doc": "The label is placed along the line of the geometry. Can only be used on `LineString` and `Polygon` geometries."
},
"line-center": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add more specific compatibility info? See

"`auto` value": {
"js": "0.25.0",
"android": "4.2.0",
"ios": "3.4.0",
"macos": "0.3.0"
},
for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea -- this look right?

screenshot 2018-07-03 14 00 05

@@ -861,6 +861,9 @@
},
"line": {
"doc": "The label is placed along the line of the geometry. Can only be used on `LineString` and `Polygon` geometries."
},
"line-center": {
"doc": "The label is placed at the center of the line of the geometry. Can only be used on `LineString` and `Polygon` geometries. Note that a single feature in a vector tile may contain multiple line geometries. The center is calculated based on the entirety of the geometry included in the tile buffers, and the label may extend past the edge of the tile."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is a little on the long side. Is the last sentence necessary?

With this placement option, we will attempt to place a single label in the center of each "line" geometry of a feature. If the label doesn't fit or the 'text-max-angle' check fails, we don't place anything.
Labels using 'line-center' are allowed to extend past the edge of the tile they're centered in, following line geometry included in the tile's buffers.
@andrewharvey
Copy link
Collaborator

hey @ChrisLoer did you need to do yarn run codegen to update src/style/style_layer/symbol_style_layer_properties.js with the new line-center option?

@ChrisLoer
Copy link
Contributor Author

Oops, yeah, thanks for catching that @andrewharvey! #6943

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

Successfully merging this pull request may close these issues.

7 participants