-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core][macOS] Compute camera center and zoom for geometry with fixed heading #10107
Conversation
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.
👍 core changes
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 running with this feature. In addition to the comments below, would you do the honors and add a blurb to the iOS and macOS changelogs?
@@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN | |||
@class MGLAnnotationImage; | |||
@class MGLMapCamera; | |||
@class MGLStyle; | |||
@class MGLShape; |
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 make these changes to the iOS implementation of MGLMapView also? Thanks!
platform/macos/src/MGLMapView.h
Outdated
@param animated Specify `YES` to animate the change by smoothly scrolling and | ||
zooming or `NO` to immediately display the given bounds. | ||
*/ | ||
- (void)setVisibleShape:(MGLShape *)shape heading:(double)heading edgePadding:(NSEdgeInsets)insets animated:(BOOL)animated; |
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 method is reminiscent of -showAnnotation:
, which also adds the passed-in annotation (which may be a shape) if it isn't already on the map. It might be nice to generalize that method with these additional parameters, but I'm not sure it's necessary to have one that only changes the camera, since the developer can readily compose -cameraThatFitsShape:heading:edgePadding:
with -setCamera:animated:
. The reason -setVisibleCoordinateBounds:edgePadding:animated:
exists is that there's already a visibleCoordinateBounds
property. But there isn't inherently a "visible shape" the way there's a visible coordinate bounds.
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.
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.
We try to keep the iOS and macOS SDKs as close as possible. In fact, there’s an entire project tracking macOS SDK parity with the iOS SDK, but it’s generally assumed that the iOS SDK would get new features first because it’s a bigger priority for Mapbox.
Ideally we would find a way to make -cameraThatFitsShape:heading:edgePadding:
compatible with one of the -setCamera:…
methods, perhaps -setCamera:withDuration:animationTimingFunction:edgePadding:completionHandler:
, such that we could add the same method to both SDKs publicly.
src/mbgl/map/map.cpp
Outdated
Transform transform(impl->transform.getState()); | ||
transform.setAngle(angle); | ||
CameraOptions options = mbgl::cameraForLatLngs(latLngs, transform, padding); | ||
options.angle = angle; |
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.
The return value inherits the current pitch, but the developer may want to animate to an arbitrary pitch for the same reason that they'd want to animate to an arbitrary angle.
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.
src/mbgl/map/map.cpp
Outdated
} | ||
|
||
CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, double heading, const EdgeInsets& padding) const { | ||
double angle = -heading * util::DEG2RAD; |
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.
The convention throughout mbgl seems to be to use the term "angle" for what might be called "heading" or "bearing" elsewhere.
platform/macos/src/MGLMapView.h
Outdated
including the entire coordinate bounds. The camera object uses the current | ||
direction and pitch. | ||
*/ | ||
- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape heading:(double)heading edgePadding:(NSEdgeInsets)insets; |
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.
MGLMapView uses the term "direction" instead of "heading", because "heading" is part of a 3D camera system that's encapsulated in MGLMapCamera. If we allow the heading to be configured but not the pitch, we should use "direction" here for consistency with -setDirection:
. On the other hand, if we make the pitch configurable, as suggested below, then this method might take a camera (as matchingCamera:
) instead of separate heading
and pitch
parameters.
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.
Given #2259, I didn't want to add pitch
just yet.
👍 on direction
platform/macos/src/MGLMapView.h
Outdated
@return A camera object centered on the same location as the coordinate bounds | ||
with zoom level as high (close to the ground) as possible while still | ||
including the entire coordinate bounds. The camera object uses the current | ||
direction and 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 method doesn't use the current direction, and it includes the entire shape, not an entire coordinate bounds.
platform/macos/src/MGLMapView.mm
Outdated
MGLShapeCollection *shapeCollection = (MGLShapeCollection *)shape; | ||
for(MGLShape *s in shapeCollection.shapes) { | ||
auto shapeLatLngs = coordinatesForShape(s); | ||
latLngs.insert(latLngs.end(), shapeLatLngs.begin(), shapeLatLngs.end()); |
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.
Consider having the mbgl::Map method take a Geometry; each MGLShape subclass already has an internal method for converting to a Geometry.
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.
Added some final comments regarding the iOS and macOS changes. I’ll leave it to @tobrun to look at the Android side in detail.
platform/android/CHANGELOG.md
Outdated
@@ -6,7 +6,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to | |||
|
|||
* Add support for ImageSource [#9110](https://github.com/mapbox/mapbox-gl-native/pull/9110) | |||
* Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)) | |||
* TBA | |||
* Added `MapboxMap::getCameraForGeometry()` to get a camera with zoom and center computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)) |
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.
Is MapboxMap::getCameraForGeometry()
the right syntax for referring to an instance method in Java? I thought it was MapboxMap.getCameraForGeometry()
.
platform/ios/CHANGELOG.md
Outdated
@@ -29,6 +29,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT | |||
* Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)) | |||
* Added an `overlays` property to `MGLMapView`. ([#8617](https://github.com/mapbox/mapbox-gl-native/pull/8617)) | |||
* Selecting an annotation no longer sets the user tracking mode to `MGLUserTrackingModeNone`. ([#10094](https://github.com/mapbox/mapbox-gl-native/pull/10094)) | |||
* Added `-[MGLMapView cameraThatFitsShape:direction:padding:]` to get a camera with zoom and center computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)) |
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.
We just branched for iOS SDK v3.7.0 and macOS SDK v0.6.0 (in release-agua
). Would you mind retitling the “master” section and adding a new “master” section above it?
platform/macos/CHANGELOG.md
Outdated
@@ -26,6 +26,7 @@ | |||
* Fixed several bugs and performance issues related to the use of annotations backed by `MGLAnnotationImage`s. The limits on the number and size of images and glyphs has been effectively eliminated and should now depend on hardware constraints. These fixes also apply to images used to represent icons in `MGLSymbolStyleLayer`s. ([#9213](https://github.com/mapbox/mapbox-gl-native/pull/9213)) | |||
* Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)) | |||
* Added an `overlays` property to `MGLMapView`. ([#8617](https://github.com/mapbox/mapbox-gl-native/pull/8617)) | |||
* Added `-[MGLMapView cameraThatFitsShape:direction:padding:]` to get a camera with zoom and center computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)) |
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.
The iOS and macOS SDKs always say “zoom level” and “center coordinate”, to differentiate from the act of zooming and the view’s center (point).
platform/macos/src/MGLMapView.h
Outdated
@param animated Specify `YES` to animate the change by smoothly scrolling and | ||
zooming or `NO` to immediately display the given bounds. | ||
*/ | ||
- (void)setVisibleShape:(MGLShape *)shape direction:(double)direction edgePadding:(NSEdgeInsets)insets animated:(BOOL)animated; |
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 continue to think this would be a poor API to expose publicly, per #10107 (comment). For one thing, it isn’t possible to customize the duration or timing function or provide a completion handler, all options that come with -setCamera:withDuration:animationTimingFunction:edgePadding:completionHandler:
on iOS.
If it’s really necessary to achieve a padding-less camera fitting a shape, can we remove this method, replace it with -setCamera:withDuration:animationTimingFunction:edgePadding:completionHandler:
from iOS, and use the following code to achieve the same effect for the time being?
MGLMapCamera *camera = [mapView cameraThatFitsShape:shape direction:direction edgePadding:edgePadding];
NSEdgeInsets edgePadding = contentInsets;
edgePadding.left *= -1; edgePadding.right *= -1; edgePadding.top *= -1; edgePadding.bottom *= -1;
[mapView setCamera:camera withDuration:5 animationTimingFunction:nil edgePadding:edgePadding completionHandler:nil];
a7b7f9a
to
71f6649
Compare
platform/ios/CHANGELOG.md
Outdated
@@ -29,6 +29,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT | |||
* Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)) | |||
* Added an `overlays` property to `MGLMapView`. ([#8617](https://github.com/mapbox/mapbox-gl-native/pull/8617)) | |||
* Selecting an annotation no longer sets the user tracking mode to `MGLUserTrackingModeNone`. ([#10094](https://github.com/mapbox/mapbox-gl-native/pull/10094)) | |||
* Added `-[MGLMapView cameraThatFitsShape:direction:padding:]` to get a camera with zoom level and center coordinate computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)) |
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 should say edgePadding:
, not padding:
.
This is working great @asheemmamoowala 👍 I might revisit the public api with overloaded methods (so bearing and padding are optional) |
…. On macOS, also added -[MGLMapView setCamera: withDuration: animationTimingFunction: edgePadding: completionHandler:] for parity with iOS
71f6649
to
900faca
Compare
Closes #9809
Implement a
Map:: cameraForLatLngs
variant that allows specifying a heading and returnsCameraOptions
withzoom
,center
, andangle
.