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

[WIP] Polylabel and improved interior algorithm #3780

Closed
wants to merge 4 commits into from

Conversation

talaj
Copy link
Member

@talaj talaj commented Oct 12, 2017

An attempt to improve interior algorithm.

It's based on original interior algorithm, but instead of single horizontal bisector crossing centroid, arbitrary number of bisectors can be used. The number of bisectors controls precision of final placement and can be set as input parameter. Placements also gravitate toward centroid to avoid highly eccentric placements. Please, take a look at the code for details, the algorithm is very simple.

I've also added Polylabel algorithm. Here is a rough performance comparison. Values are milliseconds of overall rendering, when I left only single marker in the style.

Test name Old interior New interior Polylabel
interior-point-8 0.8 0.9 1
interior-point-18 26 27 46
interior-point-13 165 179 254

For visual comparison, please, take a look at visual test results.

I'm going to add more tests and performance benchmarks.

Refs #3550, #3539.

cc @kocio-pl

@artemp
Copy link
Member

artemp commented Oct 12, 2017

@talaj looks great!

@kocio-pl
Copy link

I'm thinking about another improvement - adding some degree of freedom with polygon label placement.

Typical use case is that we have a capital of some administrative area and it's located in the middle of that area, so we have to choose which labels are more important - for example Madrid:

http://www.openstreetmap.org/relation/5326784#map=5/41.935/3.889

It would be good to allow the label of the country to be moved around if possible (within some user defined radius) to show both names.

@yohanboniface
Copy link
Member

It would be good to allow the label of the country to be moved around if possible (within some user defined radius) to show both names.

Isn't this achieved with text-placement-type: simple, text-placements=S,N… plus text-dy/x: xx ?

@kocio-pl
Copy link

These are just part of styling. I mean something like text-label-position-tolerance, which allows to move labels a bit to fit them better if needed, if I understand it correctly.

@talaj
Copy link
Member Author

talaj commented Nov 24, 2017

@yohanboniface is correct, placement-type parameter is for that. Some information about it can be also found in the wiki.

@kocio-pl
Copy link

I don't get the "X" option - could you describe it more clear? And will it work with the polygons?

@talaj
Copy link
Member Author

talaj commented Nov 24, 2017

@kocio-pl The meaning of X is most clear from the code.

will it work with the polygons?

Yes, it will work with any text placement.

@kocio-pl
Copy link

I've been consulting with Polish community and it looks like X just allows to shrink the text, which has nothing to do with moving labels. Madrid label would still be clashing with Spain on z4-z5.

I was also trying to add text-placement-type=simple and text-placements for polygons, but it did not work. Documentation does not make it clear if it should work with polygons, so I don't know if I made some mistake or it's just like that.

text-dx/text-dy is about fixed amount of pixels, so it wouldn't help with avoiding label collisions.

@yohanboniface
Copy link
Member

text-placement-type is about giving Mapnik a bunch of options to try to rearrange labels, so it can render more of them.
By using text-placements you can define where it can move the labels (North, South, and so on) and how much it can play with font size.
The text-dx/dy in this context gives Mapnik the amount of pixels to move the labels north/south/…

@kocio-pl
Copy link

I know these options, but do you know if text-placements works with polygon labels? That is still not what I need (it doesn't work with clashing Madrid/Spain labels), but at least it would help in some cases when the labels are just close to each other.

@talaj
Copy link
Member Author

talaj commented Nov 26, 2017

I've been consulting with Polish community and it looks like X just allows to shrink the text, which has nothing to do with moving labels.

With text-placement-type=simple, the X means that the label will try to move by eXact values of dx and dy, as you set them to the symbolizer. For comparison, the N - North will try to move label by 0 in x direction (no matter what value of dx is set) and by -abs(dy) in y direction, where abs mean absolute value.

it doesn't work with clashing Madrid/Spain labels

Then there is some other aspect. Maybe a bug, but I doubt, this is a widely used, well tested feature. Those labels must not have allow-overlap set to true. Otherwise there would be no collision. Also you have to set dx and dy to say how far to move the label.

@kocio-pl
Copy link

the X means that the label will try to move by eXact values of dx and dy, as you set them to the symbolizer

I'm not sure if it's clear what I mean. Static methods are just not the right tool for my issue. They are needed to make the style look in a certain way, but they are not meant to deal with fitting more labels - and this is a problem I want to solve.

  • Placement options like NSEW etc. are nice, because they allow to try different angles, but they work only with a fixed radius.
  • Changing the size is also clever cheat, but might be not always wanted.
  • The missing tool seems to be trying also different radius, which would add another possibility to a cartographic toolset. This is probably the best when both interesting points are close to each other, so changing the angle and making font a bit smaller are not effective.

What I'd like to have would be:

  • Kind of R (Range) values of dx and dy, so the label could be placed between dx_min-dx_max/dy_min-dy_max to dynamically try to fit labels. This could be easier to code.
  • More complex version of it, like "anywhere inside the area" (starting with default centroid position, of course).

We could check if we're not totally outside the polygon line also in the first case (BR - Bound Range?), but that means additional code and is just an option for R.

@talaj
Copy link
Member Author

talaj commented Nov 26, 2017

Placement options like NSEW etc. are nice, because they allow to try different angles, but they work only with a fixed radius.

Yes, text-placement-type=simple works only with fixed radius. There is text-placement-type=list for more complicated description of possible placements. Unfortunately, there is no real support for it by CartoCSS, see mapbox/carto#238.

There is also an open pull request with combined placement type, which allows to combine simple and list placement type: #2687.

I'm using this combined placement type alongside with angle placement type and grid placement in downstream, but I've never had enough motivation to offer it to the upstream.

Static methods are just not the right tool for my issue.

I don't know what makes you think that X option is somehow static. It is on par with other options like N or S which text symbolizer iterates through.

@kocio-pl
Copy link

But what do you think of flexible radius in general? Do you think it's not needed, that it could be tricky to implement or simply that there is nobody interested in coding it at the moment, for example?

Of course I can try some other ways if I don't have this one, but I prefer to solve the problem this way if possible (SNEW or font size will not help with some typical cases, and a list means manual work, which is better suited for small scale map without big style changes).

@kocio-pl
Copy link

I've just read grid placement documentation. I initially thought it's for repeated labels, but now I feel it can be used also for a single label:

The first point is polygon's interior. Subsequent placements go around interior in a spiral.

These are basic use cases:
Trying various positions around interior.

Sounds to me more or less like what I described as "anywhere inside the area", if I understand it correctly, which would be great to have.

I've never had enough motivation to offer it to the upstream

What could be done to help you raise the motivation then? 😄

@talaj
Copy link
Member Author

talaj commented Nov 27, 2017

But what do you think of flexible radius in general? Do you think it's not needed, that it could be tricky to implement or simply that there is nobody interested in coding it at the moment, for example?

The text-placement-type thing is designed to be modular and each placement type is well isolated code. So there is no problem implementing it.

I'm wondering why do you need this now, after so many years of development of OSM Mapnik styles. There has to be some standard way how to solve such collisions in OSM. It's so basic thing.

What could be done to help you raise the motivation then?

I don't know about any issue here in Mapnik where such feature is requested, except of that still open pull reqeust with combined placement type. So I concluded no one need it.

Also placement type list is still not supported by CartoCSS. Maybe it should be implemented first.

I've just read grid placement documentation. I initially thought it's for repeated labels, but now I feel it can be used also for a single label

Yes, if you set repeat-distance to a large value, the grid placement will put single label on closest place near interior. It also nicely cooperates with offset parameter of text symbolizer: you can shrink a space of possible placements (a polygon) by negative offset value.

@talaj
Copy link
Member Author

talaj commented Nov 27, 2017

Sounds to me more or less like what I described as "anywhere inside the area", if I understand it correctly, which would be great to have.

OK, I will try to offer it to the upstream.

@talaj
Copy link
Member Author

talaj commented Nov 27, 2017

Back to the main topic.

I've made some changes to the algorithm to improve filtering of possible placements.

I've also set precision of polylabel algorithm to 10 instead of default 1. It has a negligible effect to visual output, but performance is now about the same as with the new interior algorithm.

Here are some new tests I've added. I excluded some totally uninteresting cases with symmetric polygons where centroid, interior and polylabel have the same placement.

006, 007, 008, 011, 012, 013, 016, 017, 018, 020, 025, 026, 027, 028, 029, 031, 032, 033, 034, 035, 037, 040, 042, 043, 044, 045, 046, 049, 050, 052, 053, 055, 056, 058, 059, 060, 061, 062, 063, 064, 065, 066, 067, 068, 069, 071, 072, 073, 074, 076, 077, 079, 080, 081, 085, 086, 087, 088, 089, 090, 091, 093, 095, 096, 097, 099, 100

These are new results of old tests:

01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21

@kocio-pl
Copy link

It looks like polylabel is kind of eccentric, at least in this set of tests - it tends to locate the label near the ends of the object. Improved interior works for me much better most of the time.

@talaj
Copy link
Member Author

talaj commented Nov 27, 2017

It looks like polylabel is kind of eccentric

It's because polylabel is "too precise". It's evident on this polygon:

polylabel

The polylabel placement is great as a pole of inaccessibility, but weak as a label placement.

at least in this set of tests

I agree that this test set is not objective. It contains only polygons of buildings. I'm going to make another set with "natural" polygons.

I'm also going to try to modify polylabel in such a way it will prefer positions closer to centroid. Something like mapbox/polylabel#33. I feel some potential there.

@kocio-pl
Copy link

I'm wondering why do you need this now, after so many years of development of OSM Mapnik styles.

It's nothing new and it's not only me, for example gravitystorm/openstreetmap-carto#1069 is already 3 years old. I guess it's a general OSM problem - lack of communication between the projects.

There has to be some standard way how to solve such collisions in OSM. It's so basic thing.

Which OSM project do you mean? In osm-carto we don't have the tools, so we just use suboptimal solutions.

BTW: Are you from Czechia? We plan to hold a regional conference in Poznań, 13-14 April 2018 ( https://wiki.openstreetmap.org/wiki/State_of_the_Map_Poland_2018 ). It would be great if you could come so we could talk about map rendering more (at least one more osm-carto developer plans to attend there - @matkoniecz).

@talaj
Copy link
Member Author

talaj commented Nov 28, 2017

To the main topic: I've managed to modify Polylabel to prefer placements closer to centroid. It now gives almost the same results as the improved Interior.

Take a look on new versions of reference images:

006, 007, 008, 011, 012, 013, 016, 017, 018, 020, 025, 026, 027, 028, 029, 031, 032, 033, 034, 035, 037, 040, 042, 043, 044, 045, 046, 049, 050, 052, 053, 055, 056, 058, 059, 060, 061, 062, 063, 064, 065, 066, 067, 068, 069, 071, 072, 073, 074, 076, 077, 079, 080, 081, 085, 086, 087, 088, 089, 090, 091, 093, 095, 096, 097, 099, 100

01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21

@kocio-pl
Copy link

Now it's a tie - I have spotted 3 cases where polylabel was worse than interior and 3 other where it won (especially 093). Otherwise they are similar and in some hard cases (like 099) they both are equally fooled.

@talaj
Copy link
Member Author

talaj commented Nov 29, 2017

Closed in favor of #3811.

@talaj talaj closed this Nov 29, 2017
@talaj
Copy link
Member Author

talaj commented Dec 1, 2017

BTW: Are you from Czechia? We plan to hold a regional conference in Poznań, 13-14 April 2018

Tak jest. I would really like to come.

@kocio-pl
Copy link

OK, I will try to offer it to the upstream.

Hi, do you still plan to merge grid code? I would really like to have it available in osm-carto.

@talaj
Copy link
Member Author

talaj commented Jan 10, 2018

@kocio-pl - Yes, definitely, I plan to work on it, but there were also some other issues I had to solve.

It may be a quite long process to get these features to OSM. The new interior algorithm is now merged to the master, which will be Mapnik 3.1 once. But when, who knows? Mapnik is being released from 3.0.x branch now. We can try to speed the process up by porting these changes to the 3.0.x branch.

@kocio-pl
Copy link

kocio-pl commented Jan 10, 2018

New interior algorithm is not that important to me - fixing labels outside the polygon was, because this was visible error, so 3.0.18 release is important, because it fixes also nasty SVG bug, but that's all we need for now.

Once the grid is merged, it would be great if it would be released, since OSMF server team sticks to the packages and this is our main deployment, so we will wait for them. Since Mapnik tends to have really long time between X.Y releases, another 3.0.x would make a lot of sense.

@talaj
Copy link
Member Author

talaj commented Jan 10, 2018

OK, good to know. So I will try to focus on the grid placement.

@kocio-pl
Copy link

Thanks! I guess releasing 3.0.18 is in the hands of @artemp?

@artemp
Copy link
Member

artemp commented Jan 10, 2018

@kocio-pl - yes, we have 3.0.18-rc1 already, the plan is to release soon.

@artemp
Copy link
Member

artemp commented Jan 12, 2018

@talaj @kocio-pl - I'm looking at porting new placements to 3.0.x. Just to clarify - new interior (based on modified polylabel) is what we need and we can drop actual polylabel from the backport? I'd rather avoid introducing new deps in 3.0.x

@talaj
Copy link
Member Author

talaj commented Jan 12, 2018

@artemp - Yes, the new interior placement will work without that dependency on upstream polylabel. A bit more laborious can be to port all the visual tests, which basically all depend on polylabel placement.

I can create a pull request with the new interior placement against 3.0.x branch with updated tests, if you want.

@artemp
Copy link
Member

artemp commented Jan 12, 2018

@talaj - yes, please :)

@talaj
Copy link
Member Author

talaj commented Jan 12, 2018

@artemp OK

@artemp
Copy link
Member

artemp commented Jan 23, 2018

@talaj - ping, did you have a chance to work on this ? Would be great to get 3.0.18 released soon, cheers!

@talaj
Copy link
Member Author

talaj commented Jan 23, 2018

@artemp - Yes, I will try to offer it this week. I'm self assigning the issue.

@artemp
Copy link
Member

artemp commented Jan 23, 2018

👍

@kocio-pl
Copy link

Yes, if you set repeat-distance to a large value, the grid placement will put single label on closest place near interior. It also nicely cooperates with offset parameter of text symbolizer: you can shrink a space of possible placements (a polygon) by negative offset value.

Which repeat-distance did you mean? The only one documented in 3.0.20 API is this:

http://mapnik.org/mapnik-reference/#3.0.20/shield-repeat-distance

I'm also not sure about which offset option did you mention.

@talaj
Copy link
Member Author

talaj commented Aug 17, 2018

@kocio-pl There are text-repeat-distance and shield-repeat-distance.
However I forgot to add text-offset and shield-offset to mapnik-reference. I'm sorry, these are new and came alongside with grid placement. I will add them.

@kocio-pl
Copy link

Oh, thanks, great! I don't know why I haven't found text-repeat-distance.

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

Successfully merging this pull request may close these issues.

4 participants