Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Annotating Null Island also annotates its antipode #3563

Merged
merged 5 commits into from
Oct 19, 2016

Conversation

brunoabinader
Copy link
Member

If I add an annotation at the coordinates 0°, 0°, an annotation also appears at the coordinates 0°, 180°, but only at z1.

antipodes

@1ec5 1ec5 added the bug label Jan 15, 2016
@1ec5
Copy link
Contributor Author

1ec5 commented Jan 16, 2016

Actually, more spurious annotations appear at other zoom levels, but on different tiles. Here’s what the same annotation produces at z2:

2/1/1

@friedbunny
Copy link
Contributor

As one would expect, this reproduces on iOS:

simulator screen shot mar 22 2016 5 52 26 pm

@friedbunny
Copy link
Contributor

If you really must draw an annotation at null island, here’s a relatively silly but effective work around:

- (MGLPointAnnotation *)validateCoordinateForAnnotation:(MGLPointAnnotation *)annotation {
    if (annotation.coordinate.latitude == 0 && annotation.coordinate.longitude == 0) {
        annotation.coordinate = CLLocationCoordinate2DMake(0.0000001, 0.0000001);
    }

    return annotation;
}

@brunoabinader
Copy link
Member

This happens because the symbol annotation geographic coordinate intersects with all four surrounding tiles, causing them all to call for SymbolAnnotationImpl::updateLayer, which calculates the projected point based on modulo operations that eventually puts the features into position { 0, 0 } of each respective tile. I've fixed that in #6553 by adding an additional clause to the symbol tree query in AnnotationManager::getTileData that prevents tiles in which the projection calculation would be invalid.

@mention-bot
Copy link

@brunoabinader, thanks for your PR! By analyzing the history of the files in this pull request, we identified @jfirebaugh, @boundsj and @1ec5 to be potential reviewers.

@brunoabinader brunoabinader added the Core The cross-platform C++ core, aka mbgl label Oct 7, 2016
@1ec5
Copy link
Contributor Author

1ec5 commented Oct 7, 2016

Please avoid commandeering an issue opened by someone else by converting it into a PR. The resulting page is confusing for anyone who hasn’t been following the conversation, moreso if for whatever reason the PR gets rejected.

@jfirebaugh
Copy link
Contributor

I'm not sure this is the right fix. Per #5419 and #1673, we actually want the annotation on the border of a tile to appear in all tiles that share that border. So isn't the issue rather that the subsequent projection math places the feature at the wrong tile coordinate for some of the tiles?

@brunoabinader
Copy link
Member

Apologies @1ec5 - this was part of a PR creation batch and I should've paid more attention to this not being a recently created issue of mine.

@brunoabinader
Copy link
Member

You are correct @jfirebaugh - we were actually doing the wrong coordinate system conversions in SymbolAnnotationImpl::updateLayer - so in fact #5419 is just a different manifestation of this issue 🎉 🎉 🎉

Going from Point<double> in SymbolAnnotation to GeometryCoordinate involves:

  1. Convert Point<double> (aka. LonLat) to TileCoordinate via TileCoordinate::fromLatLng
  2. Convert Point<double> from TileCoordinate.p to GeometryCoordinate (aka. TilePoint) via TileCoordinate::toGeometryCoordinate

For 2), we require #6626 - thus I'm rebasing this PR against that. We can either merge #6626 first and rebase this against that or just review and merge this and close #6626, I'm fine with either option.

@brunoabinader
Copy link
Member

Fixes #5419.

@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch from c5b69ae to 156862d Compare October 9, 2016 15:24
@brunoabinader
Copy link
Member

brunoabinader commented Oct 9, 2016

Because geometry tile features are now properly duplicated when they intersect with other tile edges, queryRenderedFeatures would return wrong values. With cbd5a0a we now filter these results by removing features with the same identifier.

@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch from a3c3f78 to cbd5a0a Compare October 9, 2016 17:51
@brunoabinader
Copy link
Member

Filtering out duplicated annotations affects the results of some query render tests e.g. edge-cases/null-island now outputs 1 feature instead of 4. I believe we shouldn't output duplicated features and thus, update the expectations for these.

@brunoabinader
Copy link
Member

Another side-effect: opaque annotations on tile edges are overdrawn:
screen shot 2016-10-09 at 9 20 47 pm

@brunoabinader
Copy link
Member

One solution to the opaque feature overdraw is to always enable symbol bucket clipping:
screen shot 2016-10-10 at 10 20 11 am

This potentially fixes #1673 and #5055.

@brunoabinader
Copy link
Member

This potentially fixes #1673 and #5055.

Not true for #1673. Features that are not exactly on the tile edges, but close enough are still clipped as you can see below (notice the cross pattern):
screen shot 2016-10-10 at 10 48 56 am

@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch from 6d95157 to 197ed67 Compare October 10, 2016 14:30
@brunoabinader
Copy link
Member

brunoabinader commented Oct 10, 2016

i've had an insightful talk with @kkaefer about the possibility to get rid of stencil clipping for symbols. In sum, these are the options we have so far:

Option 1: Get rid of stencil clipping for symbols

  • Filter symbol features in which geometries intersects more than one tile, so only one feature gets inside symbol layer
    • Implies disabling stencil clip for symbols so we don't clip features close to tile edges
  • Pros:
    • Fixes collision tile rendering
    • Fixes overdrawn features on tile edges
  • Cons:
    • Because symbol-avoid-edges depends on the stencil clip, it stops working
    • 5 failing render-tests:
      • symbol-avoid-edges/default
      • symbol-avoid-edges/rotated-false
      • symbol-spacing/line-close
      • symbol-spacing/line-far
      • text-tile-edge-clipping/default

Option 2: Always clip symbol buckets

@brunoabinader
Copy link
Member

Pinging @jfirebaugh for evaluating the options.

@jfirebaugh
Copy link
Contributor

Pretty sure that for now we want to go with Option 2: Always clip symbol buckets. Getting rid of stencil clipping for symbols is a good long-term goal but there are a number of tricky issues that we will need to solve for that to be viable, and we should fix this bug in the meantime.

@brunoabinader
Copy link
Member

One way of fixing the clipped features close to tile edges is increasing the bounds when querying for renderable features within tile bounds - downside is that we'll eventually insert features to render tiles that won't be visible at all due to stencil clipping.

@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch 2 times, most recently from b4c7829 to dc81a13 Compare October 12, 2016 09:00
@brunoabinader
Copy link
Member

Per conversion with @jfirebaugh, I've decided to split the fixes previously contained in this PR in separate ones:

The commit left for review on this PR fixes the immediate cause for the issue initially mentioned on this issue (now PR).

In order to fix rendering of opaque symbols near tile edges, I'm moving this discussion to a new issue: #6670

@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch 2 times, most recently from acf18ce to 36cc9ab Compare October 15, 2016 16:59
@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch from 36cc9ab to 11c67d7 Compare October 17, 2016 17:29
@jfirebaugh
Copy link
Contributor

This introduces a TransformState to a bunch of functions in order to satisfy a composition of functions -- essentially TileCoordinate::toGeometryCoordinate(TileCoordinate::fromLatLng(latLng)) -- in which TransformState should "cancel out" and be irrelevant to the result.

Can we instead write a method such as GeometryCoordinate CanonicalTileID::project(const LatLng&) which does the geographic coordinate ⇢ tile coordinate projection directly? (It doesn't necessarily have to be a member of CanonicalTileID -- a standalone function would also be fine.)

@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch from 11c67d7 to 0cc48e9 Compare October 18, 2016 11:39
@brunoabinader
Copy link
Member

Can we instead write a method such as GeometryCoordinate CanonicalTileID::project(const LatLng&) which does the geographic coordinate ⇢ tile coordinate projection directly?

Totally @jfirebaugh - this actually ended up in moving {un,}project() into Projection class - cleaning up a lot of code in between and moving us one step closer into switchable projection types in the future 😉

@@ -149,11 +149,11 @@ std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) {

const TransformState state;
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused.

@brunoabinader brunoabinader force-pushed the 3563-null-island-annotation-antipodes branch from 0cc48e9 to 6c7b8db Compare October 19, 2016 04:52
@brunoabinader brunoabinader merged commit c50577d into master Oct 19, 2016
@brunoabinader brunoabinader deleted the 3563-null-island-annotation-antipodes branch October 19, 2016 05:11
@1ec5
Copy link
Contributor Author

1ec5 commented Oct 19, 2016

This would be nice to get on the new release-ios-v3.4.0 branch before it diverges.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Core The cross-platform C++ core, aka mbgl
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants