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

don't reset bearing in fitbounds #1340

Closed
wants to merge 16 commits into from
Closed

don't reset bearing in fitbounds #1340

wants to merge 16 commits into from

Conversation

kelvinabrokwa
Copy link
Contributor

@kelvinabrokwa
Copy link
Contributor Author

@jfirebaugh 👀

@1ec5
Copy link
Contributor

1ec5 commented Jun 26, 2015

This maintains the current zoom but doesn’t account for rotation. For example, this call:

map.fitBounds([[37, -109+2./60+48./(60*60)], [41, -102.05]], {bearing: 60})

shows most of Colorado but not all of it. (#1338 has another example.)

In mapbox/mapbox-gl-native@bcbb56c for mapbox/mapbox-gl-native#1783, I corrected for this issue by fitting to a “visual bounding box” parallel to the viewport that encompasses the passed-in bounds.

@1ec5
Copy link
Contributor

1ec5 commented Jun 26, 2015

Specifically for the box zoom gesture that you’re testing, try this:

  1. Rotate the map such that the District of Columbia’s northeast border is parallel to the top of the page.
  2. Box-zoom the District of Columbia.

There’s a lot of padding on the top and even more on the bottom:

dc at 45

@kelvinabrokwa
Copy link
Contributor Author

@1ec5 woops totally missed that. But doesn't box zoom always have a bunch of padding?

[EDIT]: it doesn't

@1ec5
Copy link
Contributor

1ec5 commented Jun 26, 2015

It appears to have no padding: if you box-zoom on Colorado, for example, it fits perfectly when there’s no rotation but zooms in too far otherwise.

@jfirebaugh
Copy link
Contributor

@kelvinabrokwa Nice! Can you please add some tests for fitBounds to camera.test.js?

@kelvinabrokwa
Copy link
Contributor Author

@jfirebaugh will do. It's not quite ready yet though. I jumped the gun on those googly eyes...

@@ -67,7 +67,7 @@ BoxZoom.prototype = {
this._finish();

this._map
.fitBounds(bounds, {linear: true})
.fitBounds(bounds, {linear: true, bearing: this._map.getBearing()})
Copy link
Contributor

Choose a reason for hiding this comment

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

These bounds are incorrect: if you rotate the map by 45° clockwise and box-zoom the District of Columbia, bounds.ne is the northern corner of D.C. and bounds.sw is the southern corner. But Camera.prototype.fitBounds() is expecting an unrotated bounding box. So the camera ends up trying to fit to a bogus bounding box.

There are two solutions: the simpler solution is to extend bounds by the other two corners of the zoom box. The center point would be correct, but the zoom level would be suboptimal in degenerate cases like D.C. The more complex but more correct solution is to port over the changes in mapbox/mapbox-gl-native#1795, then pass in the four corners of the zoom box rather than a LatLngBounds.

y: Infinity
};

for (var i in segment) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Better to use forEach() or a plain ol’ for loop in this case. In C++, the for…in syntax was cleaner than the alternative, but there isn’t much to be gained here.

Copy link
Member

Choose a reason for hiding this comment

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

Always iterate over arrays with a plain for loop unless there's a strong reason not to.

ne = tr.project(bounds.getNorthEast()),
sw = tr.project(bounds.getSouthWest());

var nePixelInf = {
Copy link
Contributor

Choose a reason for hiding this comment

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

These variables only start out at ±∞; nePixel and swPixel are fine.

scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,
scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y;
ne = tr.project(bounds.getNorthEast()),
sw = tr.project(bounds.getSouthWest());
Copy link
Contributor

Choose a reason for hiding this comment

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

The calls to project() need to take place inside the for loop below. As it is, you’re assuming that the northwest point remains the northwest point after rotation.

@1ec5
Copy link
Contributor

1ec5 commented Jun 30, 2015

Something’s up with Camera.prototype.easeTo(): it works when fitBounds() calls it to set the center point or the zoom level, but not both. Meanwhile, if linear is false, flyTo() appears to work better, albeit with a suboptimal zoom level.

@kelvinabrokwa kelvinabrokwa changed the title Dont reset bearing on box zoom Refactor fitbounds Jun 30, 2015
@kelvinabrokwa kelvinabrokwa changed the title Refactor fitbounds Generalize fitbounds Jun 30, 2015
@kelvinabrokwa kelvinabrokwa changed the title Generalize fitbounds don't reset bearing in fitbounds Jul 1, 2015
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.

4 participants