-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Conversation
7fc0bf8
to
9686bf4
Compare
There was a problem hiding this 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!
There was a problem hiding this 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/data/feature_index.js
Outdated
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); |
There was a problem hiding this comment.
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>
?
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 0b38e35
return this.centerPoint.add(new Point(0, latOffset)); | ||
} | ||
|
||
getCameraQueryGeometry(queryGeometry: Array<Point>): Array<Point> { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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!
const ac = c.sub(a); | ||
const ap = p.sub(a); | ||
|
||
const dotABAB = dot(ab, ab); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documented in 5662072
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
@ChrisLoer thanks for the thorough review! Can you take a look at my changes and do a second review? |
There was a problem hiding this 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?
36db53a
to
a6f34f2
Compare
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.New query tests cover querying and sorting.
Launch Checklist