-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Rework Camera#easeTo and Transform#pointLocation #4320
Conversation
Continues on changes in mapbox#3130 pull request
Continues on changes in mapbox#3130 pull request
…7/mapbox-gl-js into fix-easeTo-direction
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.
Thanks for the PR and sorry for the long hold time for a review. We've been very busy the last few weeks here @ Mapbox!
src/geo/transform.js
Outdated
if ('center' in v) this.center = v.center; | ||
if ('zoom' in v) this.zoom = v.zoom; | ||
if ('bearing' in v) this.bearing = v.bearing; | ||
if ('pitch' in v) this.pitch = v.pitch; |
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 is a step in the right direction. I'm still uncomfortable with this stateful & implicit setting & resetting of parameters on Transform
. Passing arguments this way is surprising and creates potential for bugs & unintended side effects. coordinateLocation
and coordinatePoint
worked with this viewport object directly rather than reading from Transform
.
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 get what you mean by that, I looked into it. I could add an extra argument to the coordinateLocation
and pointCoordinate
methods but the reason why I used this implicit setting of parameters is to make sure that the pixelMatrix is calculated for the viewport. What do you suggest that I should do concerning the _calcMatrices
function, should I rewrite it to allow a viewport parameter? _calcMatrices
uses the following fields:
this.x
this.y
this._fov
this._pitch
this.width
this.height
this.worldSize
If I'm going to do it with a viewport parameter I'm also a bit afraid to introduce a lot of duplicate code because every parameter has a seperate check and a lot of other Transform
fields are dependent on the ones used in the viewport such as this.worldSize
which is dependent on this.scale
which is dependent on this.zoom
.
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.
Ideally, we would work together to find a way to add a viewport parameter to _calcMatrices
, reduce the amount of input needed by _calcMatricies
where possible, and refactor to eliminate any duplicate code. Does that sound doable based on your experience in this part of the codebase?
src/ui/camera.js
Outdated
tr.setLocationAtPoint(toLngLat, fromPoint.add(toPoint.sub(fromPoint)._mult(k))); | ||
var lng = interpolate(startCenter.lng, toLocation.lng, k2); | ||
var lat = interpolate(startCenter.lat, toLocation.lat, k2); | ||
tr.center = LngLat.convert([lng, lat]); |
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 created a regression test for the I have added a
The functionality should be the same as it was in commit aaede, do the fields in |
@lucaswoj I got the tests working now. I want to start refactoring now but I still have some questions. The first two things that should happen is that:
Do you have any suggestion how I should merge these functions? For most of the functions in the edit: I refactored and merged the two functions. |
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.
Thank you so much for following through on the requested architectural changes. 🎉 😄
I have a few points of in-the-weeds feedback.
@jfirebaugh @mourner would you care to take a look at the algorithm changes?
src/geo/transform.js
Outdated
this.xLng(zoomedCoord.column * this.tileSize), | ||
this.yLat(zoomedCoord.row * this.tileSize)); | ||
x, | ||
y); |
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.
Minor nit: can we make this all one line?
src/geo/transform.js
Outdated
@@ -283,8 +314,10 @@ class Transform { | |||
const coord0 = [p.x, p.y, 0, 1]; | |||
const coord1 = [p.x, p.y, 1, 1]; | |||
|
|||
vec4.transformMat4(coord0, coord0, this.pixelMatrixInverse); | |||
vec4.transformMat4(coord1, coord1, this.pixelMatrixInverse); | |||
const pixelMatrixInverse = this._calcMatrices(viewport); |
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 operation is expensive enough that we will need to cache pixelMatrixInverse
for at least the global viewport.
sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; | ||
minX = (180 + this.lngRange[0]) * worldSize / 360; | ||
maxX = (180 + this.lngRange[1]) * worldSize / 360; | ||
sx = maxX - minX < this.size.x ? this.size.x / (maxX - minX) : 0; |
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.
Can you explain what changed & why in this algorithm?
Happy to see a PR that fixes the issues, but surprised that it requires so many complicated changes, many of them introducing new expensive calculations. I'll need to spend some time on the problem to see if there's possibly a more elegant approach we're not yet seeing. |
@mourner Should we delay merging this PR until you've had a chance to prototype a more elegant implementation? |
@lucaswoj yes, let's delay for a few days! We'll have a hard time maintaining the code merged as is. |
I'm moving with an alternative PR, submitting soon. Basically the root problem here is not |
The changes in this pull request fix #4178 and #3112.
Previously when using the Camera#easeTo function the following can happen where the camera only eases to the north. The path of the camera is illustrated in the left image where the camera moves across both poles when easing between two coordinates A and B, this is unwanted behavior. The easeTo should ease in the direction of the shortest path to the endpoint, The correct behaviour is illustrated in the right image. The incorrect behaviour can be observed in the following gist: https://bl.ocks.org/joswinter/f2e9bc8413ed00875ac06eca35d7b83d
These bugs were already fixed by @yeldarby in pull request #3130 which hasn't been merged. I continued working on the code in that pull request and reworked the structure of Camera#easeTo and Transform#pointLocation as commented by @lucaswoj. The Transform#pointLocation now has an optional viewport argument which is used to calculate the pointLocation for the given point. I also changed the Camera#easeTo implementation so that all tests in camera.test.js pass.