-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Map::queryPointAnnotations() -> Map::queryRenderedFeatures() returns unexpected result as map is moved #6055
Comments
We should determine whether these issues arise from calling |
I went ahead and opened a WIP PR for a visible annotations API in #6061 since that API can help us visualize the problematic behavior. In c2a7ec8 I query for annotations with the map view's bounds as the viewport. I think I can consistently repro now on that PR's branch as follows:
Upper left works fineLower right failsAdditional context
So, despite what I said before, this does not seem like an issue that'll happen only when using |
After reading up on this, I'm all for reverting this for now but at the same time don't see an issue keeping the new api around (internally). In the end we want to migrate to that proposed solution.. thank you for looking into this! These were some interesting finds! |
Been looking into this today. Couple of observations:
That said, I haven't found the root cause yet. |
Thanks @ivovandongen. I noticed that when I updated the ScreenBox points to reflect the device pixelRatio it certainly helped. However, the retina values (2x and 3x on iPhone 6 and 6 Plus) were actually too big -- annotations were coming back in the query result even though they were far offscreen to the right ("far" as a function of zoom level). Digging more, I noticed that we calculate a dynamic scale factor based on the current zoom level and the tile's notion of what zoom level it is intended to represent. I thought that this scale value is key but, since it is a per tile value, there was no way apply it to the ScreenBox at the SDK level. In 16da44f, I propose pushing the ScreenBox down several levels so that the coordinates can be adjusted once we have all the data we need (i.e. the tile). This is less efficient than before but I'm not sure how else we can get the per tile value. Maybe we could take one tile as a representation of all for the current query and move the geometry vector formation up higher again in In any case, with this change querying for point annotations now works for all devices at all zoom levels and all values of pitch. I'm still seeing that querying completely fails after the map is rotated past 45 degrees. I thinkwe should investigate |
This is usually indicative of a problem where we try to compute a coordinate bounding box by converting four screen coordinates, each at the corner of the screen, and we assume that each screen corner corresponds to a particular corner of the bounding box regardless of the rotation. We saw this issue as we implemented fitBounds and camera roundtripping originally. |
What still puzzles me is the way we need to use This seems to be different on ios though, as your example shows that the |
Never mind. I'm not certain that I'm running with the correct core dependency in the Android emulator. |
In 4aa6e6e I added a new test harness for adding two specific annotations (a point and a line) and a query for those annotations. In bae2717 I kept hacking around the core issue by using scaled and non-scaled boxes for the shape vs point queries in FeatureIndex::query(). I think that this should fix the issues noted above with "normal" feature querying. I see that the features are returned as expected as they pass in and out of the query box -- although rotating the map still completely breaks the query's ability to find points: At this point, I'm suspicious of CollisionTile::queryRenderedSymbols() and/or the way we call it in FeatureIndex::query(). |
@boundsj I think you are right in your suspicions of CollisionTile::queryRenderedSymbols(). I've added some debug logging, and it seems that when you rotate the anchor is correct, but the query box is not always projected in the right direction. More concretely. I see the following when querying without rotation:
With rotation (around 180 degrees):
|
@boundsj I made an attempt to transform the querybox with the given rotation (see last commit). This gives surprisingly good results, but it isn't quite there yet. When rotated, the box is not quite in the right place / of the right form. |
The vertical offset in #6055 (comment) may be due to the top edge inset that the SDK automatically applies to accommodate the top bar. |
I started looking into this today but I didn't get to the bottom of it. I'm out for the next two weeks but hopefully this gives you enough background to dig in a bit more without me. While writing this up I realized that the query box used by Narrowing down what is affected
Coordinate systemsUnfortunately the coordinate systems, conversions between them can be hard to follow. Here's a bit of background:
Symbol indexingThe index used for symbol querying is the same one used to do symbol placement (collision prevention). During symbol placement we need to check how much two collision boxes can be scaled before they collide. This calculation is much simpler when all the boxes are axis-aligned (all the edges are either perfectly horizontal or perfectly vertical, never slanted). If you enable the collision debug rendering you'll see all these axis aligned boxes. All the collision boxes are aligned with the screen, not the tile edges. Because of this, the CollisionTile index can't just use regular tile coordinates. It needs to rotate them.
Symbol index updatesWhen the map is rotated, the CollisionTile index is recalculated to update placement and prevent symbol collisions. An updated CollisionTile index should also be created for layers that allow collisions. These updated indexes do not get created instantly! Map rotation triggers a recalculation but it does not wait for the results before rendering. The map is rendered with stale data until the recalculation is finished. Not waiting before rendering reduces the amount of work that needs to be done each frame and let's rendering happen at a higher framerate. Since queryRenderedFeatures uses this index, queries could be slightly incorrect in the split second after the map is rotated. Or it is possible that the recalculation is failing entirely for annotation tiles. |
Fixing the bug reported above (forwarding the query geometry to |
Per GL Core scrum today, we believe that #6627 resolved the main issue reported here with
@brunoabinader Did I summarize that correctly? @boundsj Can you confirm that |
Related ticket: #6630
Precise @jfirebaugh 🎯 thank you for summarizing this. For colliding symbol layers, I'm still perceiving the same issues reported by @boundsj here. I had a talk with @ansis last week about some ideas on how to solve the remaining tasks:
|
@jfirebaugh @brunoabinader Yes! It appears to be behaving as expected when the map is not tilted. I see the expected query result when the map is and is not rotated. In fact, even when the map is tilted (with and without rotation), the query result returns results that are just outside of the viewport (i.e. it over counts) which is a lot better than under counting for the PRs I'm working on. Although #6061 probably needs an accurate count, if possible. |
Possibly related to mapbox/mapbox-gl-js#2647. |
Fixed in #6773. |
I am having the same issue now with |
@PhaelIshall, please open a separate issue about the problem you’re seeing. If possible, please provide some sample code that demonstrates the problem. Lots has changed in this library since this issue was closed, so it’s possible that the root cause is unrelated to #6773. |
In #5165 we added a new method
queryPointAnnotations
that callsqueryRenderedFeatures
with aScreenBox
representing the view port for which you want to query for all point annotations. In the iOS SDK, this is used by:I was planing to use
queryPointAnnotations
in #5987 to help clean up and optimize the implementation in the iOS SDK'supdateAnnotationViews
. However, based on the visual behavior I'm seeing after doing that, I don't know that it'll be possible to rely on the underlyingqueryRenderedFeatures
for this purpose.For example, if I give
queryPointAnnotations\queryRenderedFeatures
a view port of:viewPort == mapView.bounds //(origin = (x = 0, y = 0), size = (width = 375, height = 667))
I see that the annotation view update method stops updating views
almostwhen I would expect it to, at first (the views get stuck near the edge of the view port when their annotations move offscreen). However, when I change the zoom level, the view port / ScreenBox seems to reflect only the upper left section of the view. This is illustrated by native views getting stuck on the map even when the underlying annotation is still technically visible -- at this point,queryPointAnnotations
is returning less annotations than I would expect (and sometimes 0 annotations).Another issue is that the result of
queryPointAnnotations\queryRenderedFeatures
seems to lag behind the map movement. This is particularly noticeable when changing zoom level. Annotation views will maintain theircenter
for the last zoom level and then snap back suddenly.Finally, I see that
queryPointAnnotations\queryRenderedFeatures
returns no annotations where I expect it should as the map is panned. However, once panning is stopped you can still select annotations via[MGLMapView annotationTagAtPoint:persistingResults:]
(which usesqueryPointAnnotations\queryRenderedFeatures
under the hood) by clicking where theyshouldbe (not where the annotation view is floating) and you get the "expected" result (a callout over the actual location of the annotation that really is in the view port):For now, I don't think we should use
queryPointAnnotations\queryRenderedFeatures
as currently implemented for queries when the map is panned, zoom levels are changed, rotation or pitch is changed, etc. I'm not able to reproduce this issue under test intest/api/annotations.cpp
but the test does not simulate queries while the map is moved so it may be fine to keep #5165 for the use cases it was written for (noted above) and just not use it for theupdateAnnotationViews
case.Next steps:
queryPointAnnotations
accessibilityAnnotationCount
,accessibilityElementAtIndex:
,indexOfAccessibilityElement:
work as expected when implemented usingqueryPointAnnotations
queryPointAnnotations
with @jfirebaugh to learn more about how it should / can be usedcc @1ec5 @tobrun @incanus @jfirebaugh @pveugen
The text was updated successfully, but these errors were encountered: