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 inflated map.getBounds due to horizonShift and edge of map #10909

Merged
merged 14 commits into from Aug 27, 2021

Conversation

SnailBones
Copy link
Contributor

@SnailBones SnailBones commented Aug 4, 2021

Launch Checklist

Closes #10261

Also fixed an undocumented issue: with 3d terrain the getBounds function ignores padding.

Updates flow version to support Array.flatMap()

Tests:

  • transform.test.js
    • Poles
    • Padding?
    • Poles/padding with terrain? (transform)
  • map.test.js
    • Poles
  • terrain.test.js
    • Poles + terrain
    • Padding + terrain

@SnailBones SnailBones added bug 🐞 skip changelog Used for PRs that do not need a changelog entry labels Aug 4, 2021
@@ -231,6 +231,66 @@ test('transform', (t) => {
t.end();
});

t.test('getBounds (#10261)', (t) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would be nice to have a test for _getBounds3D with transform isolated, but it requires elevation.visibleDemTiles. Perhaps we could create a mock for that?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that should work by mocking it in such a way that you get a valid minmax value, as it's the only dependency on elevation in this method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm leaning toward pushing these tests to the future given the tests with map seem to cover the function pretty well, and this seems less urgent than the other tasks on my plate. But if you think this is important I'd be happy to look into it.

@SnailBones SnailBones marked this pull request as ready for review August 16, 2021 18:57
Copy link
Contributor

@karimnaaji karimnaaji left a comment

Choose a reason for hiding this comment

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

A first review pass. Nice unit tests!

src/geo/transform.js Outdated Show resolved Hide resolved
src/geo/transform.js Show resolved Hide resolved
src/geo/transform.js Outdated Show resolved Hide resolved
src/geo/transform.js Show resolved Hide resolved
src/geo/transform.js Show resolved Hide resolved
@@ -231,6 +231,66 @@ test('transform', (t) => {
t.end();
});

t.test('getBounds (#10261)', (t) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that should work by mocking it in such a way that you get a valid minmax value, as it's the only dependency on elevation in this method.

Comment on lines 1200 to 1225
const topLeft = new Point(this._edgeInsets.left, this._edgeInsets.top);
const topRight = new Point(this.width - this._edgeInsets.right, this._edgeInsets.top);
const bottomRight = new Point(this.width - this._edgeInsets.right, this.height - this._edgeInsets.bottom);
const bottomLeft = new Point(this._edgeInsets.left, this.height - this._edgeInsets.bottom);

// Consider far points at the maximum possible elevation
// and near points at the minimum to ensure full coverage.
let tl = this.pointCoordinate(topLeft, minmax.min);
let tr = this.pointCoordinate(topRight, minmax.min);
const br = this.pointCoordinate(bottomRight, minmax.max);
const bl = this.pointCoordinate(bottomLeft, minmax.max);

// Snap points if off the edge of the map.
const slope = (p1, p2) => (p2.y - p1.y) / (p2.x - p1.x);

if (tl.y > 1 && tr.y >= 0) tl = new MercatorCoordinate((1 - bl.y) / slope(bl, tl) + bl.x, 1);
else if (tl.y < 0 && tr.y <= 1) tl = new MercatorCoordinate(-bl.y / slope(bl, tl) + bl.x, 0);

if (tr.y > 1 && tl.y >= 0) tr = new MercatorCoordinate((1 - br.y) / slope(br, tr) + br.x, 1);
else if (tr.y < 0 && tl.y <= 1) tr = new MercatorCoordinate(-br.y / slope(br, tr) + br.x, 0);

return new LngLatBounds()
.extend(this.coordinateLocation(tl))
.extend(this.coordinateLocation(tr))
.extend(this.coordinateLocation(bl))
.extend(this.coordinateLocation(br));
Copy link
Contributor

Choose a reason for hiding this comment

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

Any chance part of this code could be shared between _getBounds3D and getBounds? There seem to be some potential for compressing that a bit (The only difference I noticed is on the z value of pointCoordinate).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea!

const minX = Math.min(p0.x, p1.x);
const maxX = Math.max(p0.x, p1.x);
const minY = Math.min(p0.y, p1.y);
const maxY = Math.max(p0.y, p1.y);

const horizon = this.horizonLineFromTop(false);
if (minY < horizon) return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Nice early exit.

test/unit/terrain/terrain.test.js Outdated Show resolved Hide resolved
src/geo/transform.js Show resolved Hide resolved
@karimnaaji
Copy link
Contributor

@SnailBones This looks good and works well from my testing, my last concern before approving would be on the default value added to the pointCoordinate function: z?: number = this._centerAltitude. Otherwise LGTM.

SnailBones and others added 2 commits August 27, 2021 12:35
Co-authored-by: Karim Naaji <karim.naaji@gmail.com>
Copy link
Contributor

@karimnaaji karimnaaji left a comment

Choose a reason for hiding this comment

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

👍

@karimnaaji karimnaaji merged commit 3f88c00 into main Aug 27, 2021
@karimnaaji karimnaaji deleted the aidan/getbounds-horizon branch August 27, 2021 18:59
@karimnaaji karimnaaji removed the skip changelog Used for PRs that do not need a changelog entry label Aug 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

map.getBounds does not account for horizon visibility and low zoom
3 participants