gravitystorm / openstreetmap-carto

A general-purpose OpenStreetMap mapnik style, in CartoCSS
Other
1.51k stars 813 forks source link

water label placement offset #1465

Closed sommerluk closed 6 years ago

sommerluk commented 9 years ago

The label for water features seems to be sometimes placed at wrong positions.

Consider the “Lagune Ébrié” at http://www.openstreetmap.org/relation/1982728#map=10/5.2168/-4.2078 which has a label that is displayed far away from the lagoon itself:

screen3

I’m quite sure that this paricular lagoon had a well-placed label some monthes ago.

pnorman commented 9 years ago

Could that label be coming from a different object? Not only is it not the centroid of that relation, it does not lie within the convex hull or bounding box of it.

sommerluk commented 9 years ago

I’m not sure.

Just a few observations:

→ Some monthes ago this particular lagoon had a well-placed label (within the water area) → This label disappeared some monthes ago. → I’ve seen the label in the ocean only a few days ago. → I’ve searched (www.openstreetmap.org/search?query=Lagune Ébrié) for the text, and there is only one OSM element in the results → I’ve also loaded with JOSM all the area of the ocean around maybe 50 km and didn’t found anything in this sense. → The label in the ocean is only visible from z10 to z13. Starting with z14 it disappears. → I’ve tried to reproduce this locally with TileMill, the current style and a current data extract of Ivory Coast from Geofabrik. There, I see the label in the ocean from z10 to z11. → Within the water area of the lagoon, I didn’t find a label neither at openstreetmap.org nor in my local TileMill rendering.

matthijsmelissen commented 9 years ago

Very strange.

→ I’ve tried to reproduce this locally with TileMill, the current style and a current data extract of Ivory Coast from Geofabrik. There, I see the label in the ocean from z10 to z11.

Especially this is interesting, means it's not an issue with the posgis database at the production server.

sommerluk commented 9 years ago

@pnorman

Could that label be coming from a different object?

No, it doesn’t. I’m now sure. I’ve loaded the hole region (step by step) in JOSM. Then, I’ve selected the lagoon relation and copied it to a new layer. This layer I’ve saved and loaded it in the database. So there was only the lagoon relation and its members in the database; no other elements. Here is the result in TileMill:

screen30

matthijsmelissen commented 9 years ago

Weird. Thank you for in-depth testing. Would you also be able to create a minimal code-example that causes this behaviour?

sommerluk commented 9 years ago

A minimal code example is available at https://github.com/sommerluk/openstreetmap-carto/tree/minimcode01 and contains also example data.

I could reduce the code a lot. However, concerning the example data, I could only remove unnecessary tags. When I start to remove “inner” elements of the polygon or when I start to simplify the outer of the polygon, the label placement gets directly better (but still not always within the water area).

sommerluk commented 9 years ago

By the way: Locally still the same behaviour: Starting from z12 I don’t see the label anymore.

matthijsmelissen commented 9 years ago

Great, thank you. Seems to be a Mapnik issue. We'll leave the issue open here, but in the end it needs to be fixed on the side of Mapnik. Their repository is https://github.com/mapnik/mapnik. Could you report it there, or shall I do that?

sommerluk commented 9 years ago

As I don’t much about how Mapnik works (and how it works together with CartoCSS), I would appreciate if you could make the bug report at Mapnik. I think this will lead to a clearer description. I’ll subscribe the bug report anyway …

sommerluk commented 9 years ago

Upstream bug report at https://github.com/mapnik/mapnik/issues/2762

matthijsmelissen commented 9 years ago

Thanks! Sorry, I did not have time to report the bug myself earlier.

pnorman commented 8 years ago

Labeling seems fine under Mapnik 3.

matthijsmelissen commented 7 years ago

Mapnik 3 now has been rolled out. If there are still problems, I'd be happy to hear about them.

sommerluk commented 7 years ago

This issue is not solved with mapnik3. The label of the lagoon is still not within the lagoon. Instead it is within a nearby lake that has no connection to the lagoon:

screenshot 1

The screenshot is from openstreetmap.org but I’ve tried it out locally (openSUSE/kosmtik/mapnik3) and the result is the same.

Label placement is “interior”, isn’t it? So this should be within the actual water area (and never on land) even on multipolygons with islands, shouldn’t it?

matthijsmelissen commented 7 years ago

Just to be sure, is this a fresh tile?

matthijsmelissen commented 7 years ago

Re-opening for further investigation.

sommerluk commented 7 years ago

screenshot 1

Current rendering. The label “Lagune Ébrié” is displayed over a lake that is not connected at all to the lagoon. The lagoon that should get the label is marked with the red cross.

Skippern commented 7 years ago

Case mentioned in #2613 is not a complex polygon.

pnorman commented 7 years ago

It's worth noting that there's absolutely nothing we plan on doing about this from OpenStreetMap Carto unless we stop using Mapnik to place polygon labels, because there's nothing we can do. It's not a bug in our code.

Skippern commented 7 years ago

I can see that, I was not sure when posting, if it might be an OSM-Carto case, or Mapnik case, but seeing that the ticket have been relayed to mapnik, they should have a look at it, just emphasising that the problem is not limited to complex polygons.

matkoniecz commented 6 years ago

keywords for search: misplaced

kocio-pl commented 6 years ago

I have finally found misplaced Lake Victoria label!

http://bl.ocks.org/math1985/raw/af7a602c222dbf1ff1a2c0d84ed755b7/#9.00/3.5648/29.2504

Until we have new Mapnik released (and deployed in the Kosmtik and on the OSMF servers), which I hope will fix this issue, I still try to spot the label of Great Bear Lake:

http://bl.ocks.org/math1985/raw/af7a602c222dbf1ff1a2c0d84ed755b7/#7.00/65.797/-121.663

kocio-pl commented 6 years ago

There's a work in progress with tuning current label placement algorithm (and adding the new one) in Mapnik, looks very promising:

https://github.com/mapnik/mapnik/pull/3780

kocio-pl commented 6 years ago

Mapnik 3.0.16 is released:

https://github.com/mapnik/mapnik/blob/v3.0.16/CHANGELOG.md#3016

It contains the bug fix and we are not directly depending on this version (one can use the source or live with this upstream bug), but still some additional actions by related projects would be good to see:

pnorman commented 6 years ago

Once we test that 3.0.16 fixes this for us, we can close it - we don't need to wait for any servers to deploy it

kocio-pl commented 6 years ago

Good idea, I meant only waiting to see the changes on the OSMF servers.

kocio-pl commented 6 years ago

I finally managed to test Kosmtik with Mapnik v3.0.16 and it works as expected, so I can safely close this ticket now:

e0zn61o3 lby4u7gs ofotxcs_ ftckm3fs 2uadkzdn

The original problem: hf3uhigd

kocio-pl commented 6 years ago

It looks like Mapnik 3.0.16 introduced another bug (with SVG road shields), which is also present in latest 3.0.17 version:

https://github.com/mapnik/mapnik/issues/3812

verdy-p commented 6 years ago

Why Mapnik does not use the position suggested by "label" members (as described in boundary relations) or another place node for natural features with very irregular shapes (such as lakes, lagunas, or islands) ? The label members don't even need to have "name" attributes, they would only be used for their goegraphic position based on human intelligence.

And this does not prohibit a renderer to slightly change the position (as long as the label covers at least partly the polygon): the label indicates a position inside the poligon from which it can look for a suitable position at a distance minimized from this suggestion).

If a renderer cannot fit the label at that position, it could be allowed to place the label elsewhere where it could fit, by tracing a junction line (or arrow) to the position suggested by the OSM node with "label" role.

With this change, we would have better freedom to place and fit labels and still avoid many collisions. If the renderer cannot fit a label at all with these adjustement, it will eliminate other "less important" labels by managing list of labels, or by sliding again some prepositioned label whithin their tolerance area: basically labels would not be traced immediately in order, they would fill in a list of rectangles, that would be ordered by some "importance ranking note" according to their needed area, and font sizes and styles.

If needed, labels may be further manipulated (by computing common abbreviations, or using alternate "short_name", or inserting line breaks) and their polygonal shape be recomputed (more square than rectangular) to make them fit, before trying to offset them in their tolerance area (trying to maximizing the surface of intersection of the label's rectangular shape with the tolerance shape around the feature; the label restangular shape shoul also include the minimum margins to avoid gluing two labels too near of each other).

The same algorithm would also be used for icons (treated as if they were a one-letter "word" of a label, whose glyph would come from specific font style): icons would be placed also in the same list of labels, and sorted by importance rank. When a low priority label (towards the end of list) can no longer fit it is elminated and the rest of the list is processed. Most labels at end of list would be eliminated, but the first label in the list would be certain to be rendered.

Optionally, when two labels compete each other but have roughly the same rank and none of them can be offsetted in their tolerance area, one of them could be placed outside the tolerance area (where there's still room available not used by other labels at higher or same rank) in order to render them with an arrow link.

Once this is done for the whole list of candidate labels+icons, all labels+icons can be drawn in the order of the list (first the arrow links, then labels and icons on top of it) without collisions, and with the best placement and with their already computed sizes, positions, and adjustments (line breaks, abbreviations).

In all cases, the nodes with "label" role placed by humans will be always smarter (we can just have a quality control to check that these nodes effectively fall inside the (multi)polygons (or boundaries) where they are added, and never in an "inner" hole. This is a very trivial check to do by QA tools and that can be reported as well by renderers ion their own QA analysis (in this check fails in renderers, the label should be ignored completely and another algorithm will attempt to automotically compute an suitable initial position ("initial" because this automatic position is still adjutable when processing the list of labels+icons as indicated above and still has the same rules about their tolerance area, constraints of sizes, ranking, possible modification of texts, possible selective elimination of the text to keep only the icon, and also a tolerance for placing the icon, and the text label not too far from the icon with some intersection of the text area with the icon margin area)

verdy-p commented 6 years ago

Final note: using Mapnik for placing labels has a huge coast on servers. Ideally Mapnik should better be used to provide a cute background bitmap map for surfaces and lines (roads, rivers, borders of physical shapes like buildings).

Labels and icons on the opposite should be rendered as vector MBTiles by the client with additional benefits according to user preferences: support for multiple languages, support for more accessible font sizes, support for more accessible font colors/contrasts.

Servers would have much less to do themselves and our rendered maps would be easier to adapt to other uses (it would be also easier to integrate custom data on custom maps).

Rendering backgrounds with vector tiles however offers generally horrible look or require too much processing on clients, notably for low zoom levels, or will frequently hide too many details. Bitmap backgrounds without labels/icons however are still easily rescalable (using "mipmaps"). If they are computed with high enough resolution (i.e. 2x2 or 3x3 subpixels supersampling) they are easily rotatable at any angle without severe degradation of quality of effective pixels. And intermediate fractional zoom levels can be computed by fusing two "mipmaps" computed at discrete zoom levels. Rotating bitmaps is now easily done even on lowend machines that have hardware display accelerations (used by WebGL or similar 3D rendering engines or SVG renderers)

matkoniecz commented 6 years ago

Proposing using labels (that are blatant case of tagging for renderer) is offtopic in this ticket.

Please find ticket discussing this (may be not present and require creating it), rather than post in a related issue.

HolgerJeromin commented 6 years ago

@verdy-p Just a note: Mapnik is the rendering software. This style is called osm-carto.

kocio-pl commented 6 years ago

Please find ticket discussing this (may be not present and require creating it), rather than post in a related issue.

Just a note: Mapnik is the rendering software. This style is called osm-carto.

:+1:

In all cases, the nodes with "label" role placed by humans will be always smarter

I don't agree - they could only be fine tuned for a given map. You just can't predict which labels/icons/features will be needed on every map and if this placement will not be in conflict with other desired features. Hence automatic collision solving by Mapnik (I mean rendering library) is a way to go - and we just wait for a proper code to be ported upstream.

Labels and icons on the opposite should be rendered as vector MBTiles by the client with additional benefits according to user preferences: support for multiple languages, support for more accessible font sizes, support for more accessible font colors/contrasts.

I agree with you that vector layers are nice and it can be a final solution, but it's a complex technical and testing challenge: different vector formats and servers (MBTiles is just one of them - see http://paulnorman.ca/blog/2016/11/serving-vector-tiles/ ), a machine for testing it before we can start thinking of switching...

In my opinion it's best to start with language versions layer, because osm-carto can not deal with it anyway (there can be hundreds of name:xx labels) and it would be a big usability enhancement. Could you help with it somehow?

Klumbumbus commented 6 years ago

If I didn't misunderstood the problem was fixed with https://github.com/gravitystorm/openstreetmap-carto/issues/1465#issuecomment-346970659. I still have an example of label placement out of the polygon: The label of the forest "Zeisigwald" https://www.openstreetmap.org/relation/229790 is placed at this scrub: https://c.tile.openstreetmap.org/16/35124/21984.png in the east which is not part of the forest multipolygon.

matthijsmelissen commented 6 years ago

Is the new Mapnik already running on the OSMF servers?

verdy-p commented 6 years ago

@kocio-pl the labels are NOT intended to be tagging for rendering, they are suggested optimal placements, and should be the first position to try in renderers, but it does not mean that a renderer can move it around to avoid collisions with other labels. This "optimal" placement is only correct if the label is alone on the map and so there's no collision.

How a renderer will then adjust these positions will be renderer specific. But these labels should be correctly centered in the zone (and not necessarily on the largest subzone if the zone has separate islands, because its optimal placement is sometimes on a small island and not a large dependency): as a renderer CANNOT guess which subarea to label, it MUST be hinted about where to look for a placement. It still has the freedom to move this placement by first looking on other possible nearest places in the same subzone (avoiding if possible to cover inner "holes") then it can allow the label to extend outside the zone (while remaining attached to the initial zone; if the label cannot still be placed, it can place it elsewhere (outside the zone, but not too far away), by drawing a connection line/arrow pointing to the zone.

Labels offer that level of flexibility: they are hints which can be used to improve the placement to be near optimal. Automatic placement from the geometry will frequently be inaccurate because arbitrary choices are made (e.g. using as start position only the central point of a global bounding box, or the central point of the bounding box for the largest subarea, and then it will be randomly be using start positions that could be in a hole or still outside the area.

Hinting the placement with labels avoids most of these arbitrary choices that lead to frequent inaccurate or false placements made by automatic guessers. (Note: labels do not need any tag, they are just used for their geographic coordinates and nothing else, so they don't even need any name, the name to render should always be taken from the relation).

So yes, this talk about "labels" is clearly "on-topic" for this precise subject. it has NEVER been designed to be "tagging for rendering" (not even specific to any one in a specific style like carto-css): your assumption or frequent use of this "tagging for rendering" argument is false here, you clearly don't understand the issue when location of labels are accurate data fully independant of the rendering, and because this location is not specified at all by the outline geometry.

It is a generic instruction/hinting intended for ALL renderers so they can ALL optimize their placement instead of using very fuzzy (and frequently very inaccurate) heuristics based only on the geometry of area outlines. The rule about labels is that its node should be positioned as precisely as possible to the location that gives the name to the whole area, but there's absolutely no need to tag this location, it may be a single node without any tag (only referenced by the relation, possibly several relations, but usually the label should be referenced only once as embedded subareas normally have a name distinguished from the container area; for this reason, labels should not be attached to any other object geometry: not part of any way and not members of other relations).

If you don't want label nodes in the database (or you want to deprecate them), they can be safely replaced by tagging the relation itself with a "label=*" tag specifying coordinates of a node, but this is less easy to edit correctly. In that case there would be no longer any node member with "label" role in relations.

matkoniecz commented 6 years ago

the labels are NOT intended to be tagging for rendering, they are suggested optimal placements

This is contradictory. It is not the worst case of tagging of rendering (deliberately adding wrong data), but adding/changing something solely to change rendering, without adding any new information is also bad and should be avoided.

Further text: tl;dr

verdy-p commented 6 years ago

You've not demonstrated any contradiction. NO. this is not for rendering but for tagging the effective best position of the feature (if it was alone to render, it would be that one). This is really actual data, independant then of how the renderer will finally place it (but still very useful for renderer as it is an important hint against their completely arbitrary and often wrong choice of possible placements)

The label hint also allows a renderer to easily avoid placing dual labels (one for the area, another one for the label node representing it within the area): a frequent anomaly in cartocss renderer: it can eliminate the label drawn for the node and only place the label for the area (at the same suggested position, but possibly slighly moved at minimal distance from that position but still if possible within the area)

Further text: ts;dr (i.e. no argument at all in your comment)

kocio-pl commented 6 years ago

Is the new Mapnik already running on the OSMF servers?

Probably not. Since v3.0.18 has the fix for this problem, but introduces another one (labels can move location when changing zoom level), I would not advise OSMF sysadmins to use this package and wait for v3.0.19 to be released and packaged for Ubuntu, because it would have the fix also for this newer problem.

The good news is that v3.0.19 would also contain grid algorithm for searching best available place for a name label automatically, so we could be smarter than placing "optimal" label points by hand - manual placements can be good just in some cases, but not in general. It's the renderer job to find such place individually in each case. We could try this new algorithm for areas then (I have compilation problems with the pure repo code, so I'm not able to try it before packaging code is ready).

kocio-pl commented 6 years ago

@Klumbumbus The problem is completely external for us, however it's fixed in the Mapnik code and anybody could use this code on their own server, but for the reasons mentioned above it's better to hold on for a moment and not deploy anything less than v3.0.19 on OSMF servers (which are also external from the point of view of osm-carto). This is just unfortunate chain of problems with Mapnik bugs, otherwise it would be solved on OSM.org months ago.

@verdy-p I also think this is mild version of tagging for rendering, but if we could just avoid it, let's not go for half-solutions.

It is a generic instruction/hinting intended for ALL renderers so they can ALL optimize their placement instead of using very fuzzy (and frequently very inaccurate) heuristics based only on the geometry of area outlines.

What do you think might be wrong with this simple algorithm used by grid (see the section "Finding single placement inside a polygon")?

Labels offer that level of flexibility: they are hints which can be used to improve the placement to be near optimal.

Only in some cases, but with a reasonable algorithm they are just not needed, because the optimal placement will be found for any given case. I would also not name a predefined point a flexible solution - it's fixed, but dynamic place searching is flexible.

Automatic placement from the geometry will frequently be inaccurate because arbitrary choices are made (e.g. using as start position only the central point of a global bounding box, or the central point of the bounding box for the largest subarea, and then it will be randomly be using start positions that could be in a hole or still outside the area.

If the grid would use the area outside the polygon or in the hole, I would simply report a bug in the code to be fixed.

Klumbumbus commented 6 years ago

it's better to hold on for a moment and not deploy anything less than v3.0.19 on OSMF servers

OK, thanks.

verdy-p commented 6 years ago

The algorithm by grid is also an heuristic, and even if it is "perfect" geometrically, it is still not the best placement as it will be too far from the designated place, even if it's inside the zone.

You seem to also forget the case of places with exclaves: the largest exclave which is most likely to be found by a "perfect" algorithm (in fact only an heuristic, not a decisive "algorithm") is sometimes not the appropriate one: the smallest exclave is the main place, the largerst one is only a dependency (which has its own local name !

Once again:

Now reread what I said: this is not a position intended for rendering, it is the ideal position where the place should be indicated and the renderer of course can move it elsewhere (possible for text labels, but NOT for placing icons when the area itself cannot be represented because it is too small!).

Label nodes are REAL data. IT does not mean that text labels must be placed there, but that they should not deviate too much away from that ideal position.

matkoniecz commented 6 years ago

To repeat https://github.com/gravitystorm/openstreetmap-carto/issues/1465#issuecomment-355440297

Proposing using label role from relations is offtopic in this closed and already fixed issue.

Please find ticket discussing this (may be not present and creating it may be required), rather than post in a related issue like this one. If it was proposed and already rejected or what you propose was already stated - please do not repeat it or create duplicated issues.

In case of continued offtopic it will be necessary to lock conversation in this issue.

verdy-p commented 6 years ago

Now consider the case of most towns/villages that are municipalities: the ideal position indicated by the "label" node position is generally in the middle of the centre of activity of that municipality but nowhere in the geometric center of the boundaries of the area which is adminsitered: most of these towns/villages have very irregular shapes around for their boundaries. and the label should remain within the central area of where activities in the village/town occurs (this is generally near the location of the townhall, not the building itself but the major crossing or square connecting it to all places in the town village and around which there are most commercial activities and services).

Here again the label position gives the ideal position. Yes it is manually tuned, but this manual tuning should be considered as an important hint by renderers about where they will place the labels and should be even more strongly considered if placing icons, or if the full area cannot be represented with all its details (the text label will then be rendered largely outside the area, but should still cover the ideal location indicated by the label node member, using a best effort heuristic, and if not it should draw a ray to connect the text label to the ideal position).

Note that rays may also be drawn to conenct the same text label with other exclaves (and sometimes it is preferable to rendering the same text label multiple times, because these rays can be partly covered in the middle by other text labels, and because the other terminal position of these rays on exclaves will not need the placement of any additional text label that will collide with other unrelated labels and could fordid them to be rendered separately).

I maintain: label positions are real data, not strict rendering orders, but are important hints for renderers.

Also it is completely ON TOPIC, because for now text labels are far from being ideal and are rendered in wrong positions in frequent cases. With what I indicated, the initial bug shown above (in the initial report as well as all further reports below it) would have NEVER occured !

In addition, these labels allow your renderer to have a measurable quantity to evaluate its placement: any large difference (relative to the current zoom level and the physical area covered by the rendered label) can be reported: it allows your heuristic to be better tuned and improved to better respect the placement hints (sometimes the report will be that the suggested manual label was completely incorrectly placed).

The label finally allows the database to be used by application that only want coordinates of a single point and will zoom on it at a default zoom level where the place should normally be found with its visible label on the rendered map, even if they won't display the full area. Label positions are real data giving the position that people expect to find, independantly of the area they really cover. Such applications include GPS driver's navigators: enter the name of a location and go there: people don't expect to go in the middle of nowhere in the surrounding rural area when the place has an evident "center" (which is not the geometric center), also represented by the ideal "label" node member.

matkoniecz commented 6 years ago

To repeat https://github.com/gravitystorm/openstreetmap-carto/issues/1465#issuecomment-355440297 and https://github.com/gravitystorm/openstreetmap-carto/issues/1465#issuecomment-370268498

Proposing using label role from relations is offtopic in this closed and already fixed issue.

Please find ticket discussing this (may be not present and creating it may be required), rather than post in a related issue like this one. If it was proposed and already rejected or what you propose was already stated - please do not repeat it or create duplicated issues.

In case of continued offtopic it will be necessary to lock conversation in this issue. I am not locking now as it is likely that last comment was posted before warning was visible.

kocio-pl commented 6 years ago

I think a proper place to discuss labels placement might be #1391. It's also about particular issue, but the real problem is general and includes discussing dynamic placement versus manual hints.

dieterdreist commented 6 years ago

2018-03-04 23:07 GMT+01:00 Philippe Verdy notifications@github.com:

Now consider the case of most towns/villages that are municipalities: the ideal position indicated by the "label" node position is generally in the middle of the centre of activity of that municipality but nowhere in the geometric center of the boundaries of the area which is adminsitered

The role name "label" is somehow misleading here. There is actually something like a "centre" in towns or villages (usually), and this is what the node role name should refer to (e.g. "centre", "central_point" or similar). By calling it "label" you suggest it is about rendering a label, not about geographic information describing the place. Btw., no need to mention "municipalities", as this is about administration, when discussing villages and towns we are speaking about settlements here.

kocio-pl commented 6 years ago

Another example of a similar problem - it works with 3.0.15 though and OSMF servers still use 3.0.9, which probably uses the same algorithm, so it might be some other reason (metatiles maybe?):

OSMF server: screenshot-2018-3-21 openstreetmap carto kosmtik

Kosmtik rendering: _taxjvdu

kocio-pl commented 6 years ago

We are waiting now for the deployment of packages on OSMF servers, which is probably the last step - see https://github.com/openstreetmap/chef/issues/155. The package set for Ubuntu Xenial (16.04 LTS) with a fixed Mapnik version is available here:

https://launchpad.net/%7Etalaj/+archive/ubuntu/osm-mapnik/+packages