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

fix fill-extrusion querying #7499

Merged
merged 18 commits into from
Jan 9, 2019
Merged

fix fill-extrusion querying #7499

merged 18 commits into from
Jan 9, 2019

Conversation

ansis
Copy link
Contributor

@ansis ansis commented Oct 29, 2018

fixes #3122

This adds building querying by projecting the geometries and querying the projected geometries. Queries are sped up with support for non-rectangular grid index queries.

Results are sorted by distance by depth so that the first result is always the closest no matter the rotation or layer order. In the debug example /debug/extrusion-query.html red is the closest, green is the second closest and blue is the furthest.

screen shot 2018-10-29 at 12 26 53 pm

New query tests cover querying and sorting.

Launch Checklist

  • briefly describe the changes in this PR
  • write tests for all new functionality
  • document any changes to public APIs
  • post benchmark scores
  • manually test the debug page

Copy link
Contributor

@ChrisLoer ChrisLoer left a comment

Choose a reason for hiding this comment

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

I only got as far today as figuring out where the changes were and playing with the demo. Haven't started wrapping my head around the math yet, but it looks like everything would break if it weren't right so it must be fine. 😉

So far it looks awesome!

src/data/feature_index.js Outdated Show resolved Hide resolved
src/data/feature_index.js Show resolved Hide resolved
Copy link
Contributor

@ChrisLoer ChrisLoer left a comment

Choose a reason for hiding this comment

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

OK, I think I finally understand how this works! Most of my comments are naming/comment related.

src/source/source_cache.js Show resolved Hide resolved
src/source/source_cache.js Show resolved Hide resolved
src/geo/transform.js Show resolved Hide resolved
const matching3D = this.grid3D.query(
cameraMinX - queryPadding, cameraMinY - queryPadding, cameraMaxX + queryPadding, cameraMaxY + queryPadding,
(bx1, by1, bx2, by2) => {
return polygonIntersectsBox(args.cameraQueryGeometry[0], bx1 - queryPadding, by1 - queryPadding, bx2 + queryPadding, by2 + queryPadding);
Copy link
Contributor

Choose a reason for hiding this comment

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

This args.cameraQueryGeometry[0] looks like it's not accounting for query geometries with multiple rings, but we don't support that in the first place, do we? Can we just change this code to work with a plain Array<Point>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This switches both queryGeometry and cameraQueryGeometry to 780ad42

@@ -592,6 +592,38 @@ class Transform {
const topPoint = vec4.transformMat4(p, p, this.pixelMatrix);
return topPoint[3] / this.cameraToCenterDistance;
}

getCameraPoint() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I struggled figuring out just from the name and the math, what "camera point" meant. I think we should comment (and maybe rename?). Here's the intuition I worked out for how to think of it:

    // For a given query point, this represents an upper bound on how far
    // away the base of something rendered at that point could be.
    // With pitch=0, this is essentially dividing the screen into quadrants
    // around the center point of the screen, since perspective just pushes
    // the top of extrusions "away" from the center.
    // As pitch increases, the potential base for a building shifts "down"
    // towards the bottom of the screen, and potentially below the bottom of
    // the screen

Although I think that's probably not the most accurate description. Am I right that this calculation is basically just super conservative -- always include half the screen horizontally, and for the y-coordinate shift use Math.tan(pitch) * this.cameraToCenterDistance as a rough approximation of how far down the "tallest building we could render" would go?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 0b38e35

src/geo/transform.js Outdated Show resolved Hide resolved
return this.centerPoint.add(new Point(0, latOffset));
}

getCameraQueryGeometry(queryGeometry: Array<Point>): Array<Point> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Notes I made for myself trying to figure out how this worked:

    // Given a query geometry in screen coordinates, return a geometry that includes
    // all of the original query as well as all possible areas of the screen where the
    // *base* of a visible extrusion could be.
    //  - For point queries, the line from the query point to the "camera point"
    //  - For other geometries, the envelope of the query geometry and the "camera point"

I think this should be commented to explain what it means... I'm still kind of working that out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

improved in 92d59b7, thanks for the wording!

src/source/query_features.js Outdated Show resolved Hide resolved
const ac = c.sub(a);
const ap = p.sub(a);

const dotABAB = dot(ab, ab);
Copy link
Contributor

Choose a reason for hiding this comment

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

This looked like magic to me at first, but I guess it's not actually that complicated:

  • Find the barycentric coordinates of the projected point within the first triangle of the face, using only the xy plane. It doesn't matter if the point is outside the first triangle because all the triangles in the face are in the same plane.
  • Use the barycentric weighting along with the original triangle z coordinates to get the point of intersection.

The "barycentric" comment above was enough to point me in the right direction, but some elaboration along these lines would make it easier to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Documented in 5662072

Choose a reason for hiding this comment

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

Perfect!Is there a IOS & Android version?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@BrightBeacon this will be ported to mapbox-gl-native but there is no ETA

@ansis
Copy link
Contributor Author

ansis commented Jan 8, 2019

@ChrisLoer thanks for the thorough review! Can you take a look at my changes and do a second review?

Copy link
Contributor

@ChrisLoer ChrisLoer left a comment

Choose a reason for hiding this comment

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

Looks good to me!

Although do we want to publish an updated version of GridIndex before we merge this?

@ansis ansis merged commit 2119eaa into master Jan 9, 2019
@ansis ansis deleted the fill-extrusion-query branch January 9, 2019 01:46
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.

Use ray picking to query extrusions in "queryRenderedFeatures"
3 participants