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

Marker ellipse chopped across tile boundary #2577

Open
wibrahim opened this issue Nov 18, 2014 · 10 comments
Open

Marker ellipse chopped across tile boundary #2577

wibrahim opened this issue Nov 18, 2014 · 10 comments

Comments

@wibrahim
Copy link

I have been experimenting with Marker placement for points geometry and it seems that the marker image is always chopped if the point geometry is too close to the tile boundary. I did set the map buffer to half the tile length (512/2). Also in my case when using MetaTile this specific point falls on the boundary of the MetaTile as well (I could make the MetaTile larger but that just mean that other points might get chopped).
Is there any specific way of defining the Marker (I got the same behavior with a ShieldSymbolizer) to not chop the image across tile boundaries ?

My style sheet rule is:

<MarkersSymbolizer width="12" height="14" marker-type="ellipse" fill-opacity="0" stroke="HIGHLIGHTED_COLOR" stroke-width="1.5" placement="point" allow-overlap="false" clip="false" />

and the resulting image:
x31

Any help on this issue will be much appreciated.

@springmeyer
Copy link
Member

Mapnik 3.x now supports avoid-edges="true" option for markers. That is the only sure fire way to avoid a marker being clipped.

@wibrahim
Copy link
Author

Thanks @springmeyer. However, when I added avoid-edges="true" I still got the same previous behavior. To my surprise I was expecting that the marker will not be placed, but actually it was rendered and clipped as before.
I traced down the code to this line inside mapnik::markers_placements::point.hpp:

mapnik::markers_point_placement::get_point(double &x, double &y, double &angle, bool ignore_placement)
{    
    ...
    if (params_.avoid_edges && !detector_.extent().contains(box))
    {
            return false;
    }
    ...
}

my detector_.extent() returns:

minx_ = -256 
miny_ = -256
maxx_ = 768
maxy_ = 768 

which was correctly computed from setting the map buffer size to 256 and a width and height of 512.
while the marker placement box was:

minx_ = 132.99786091154064
miny_ = -23.932891132317863
maxx_ = 176.75213908849346
maxy_ = 23.932891132378785

which is clearly contained inside the detector_.extent(), thus the marker is rendered and clipped.
The marker centroid x, y are (154.87500000001705, 0.00000000003046) which shows that the y coordinate will result in the marker being clipped.
Should not that check detector_.extent().contains(box) be replaced by the Mercator bounding box and the projected marker point coordinate instead ?

@springmeyer
Copy link
Member

Oh no, sounds buggy, thanks for helping test this more. I think the next step should be to reduce a really small testcase so we can both test (and if it is truly a bug then we'll have a regression test once fixed). Have a look at https://github.com/mapnik/mapnik/wiki/A-perfect-testcase to get started.

@talaj
Copy link
Member

talaj commented Nov 19, 2014

mapnik-reference says about buffer-size: "Not intended to be used in combination with avoid-edges." So it looks rather like design decision than a bug.

@springmeyer
Copy link
Member

buffer-size: "Not intended to be used in combination with avoid-edges."

I wrote that and it is not a precise or very good statement. What I meant is that:

  • a bigger buffer can increase the likelyhood that features that occur near a tile edge end up getting rendered on each tile edge (and in the same geographical position) and therefore are less lightly to appear cut off, but even with a massive buffer there are many other factors that can prevent features from getting rendered in the same place along a tile edge (like order, the chaos of other placements, etc)

Now: this raising the question of how buffer-size impacts the collision detector box and whether allow-overlap is computed relative to the actual tile-edge or the edge of the buffered collision detector. I'd need to look at the code to confirm for sure how this works / should work and to make sure it is consistent across symbolizers.

@wibrahim
Copy link
Author

Thanks @springmeyer I will start working on creating a testcase as soon as I have the time to.

@kennykb
Copy link

kennykb commented Jan 4, 2015

For what it's worth, the current behaviour that I'm seeing is that a TextSymbolizer with point placement appears to be working adequately. A TextSymbolizer with line placement, or a ShieldSymbolizer, is now consistently producing clipped labels near tile edges. (I'm using a tile size of 256 with a buffer size of 192). I tried all combinations of clip= and avoid-edges= without effect.

Next step in attempting to work around this will be to try a zero buffer size with huge metatiles (maybe 2048x2048 and avoid-edges. The outermost tiles of a metatile will have to be discarded because they will now lack partial labels with point placement, but this should yield at least adequate results.

@talaj
Copy link
Member

talaj commented Feb 10, 2015

@springmeyer

how buffer-size impacts the collision detector box and whether allow-overlap is computed relative to the actual tile-edge

Did you mean avoid-edges?

What I know buffer-size and avoid-edges are mutually exclusive by now. avoid-edges computes with extent of collision detector which can be extended by buffer-size outside of the actual tile-edge. There is also inconsistency how buffer-size works on map and layer level. buffer-size on layer level does not affect extent of collision detector. Also this condition looks weird to me - label is not placed when single glyph does not intersect collision detector's extent.

@talaj
Copy link
Member

talaj commented May 20, 2015

@wibrahim, I'm responding on your comment from #2687 (comment) here, as the topic suites better to this issue.

I am happy to share the code with you if you want to have a look.

That would be great, I'm really interested and still not fully understanding how adjust-edges="true" is working. The code would help me a lot.

@wibrahim
Copy link
Author

Sorry for my late response.
The code for adjusting the edges is here: edge_placement_adjuster
and a sample usage with the point placement that was only tested with Markers is here point.hpp.patch

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

5 participants