[core][macOS] Compute camera center and zoom for geometry with fixed heading#10107
Conversation
1ec5
left a comment
There was a problem hiding this comment.
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?
| @class MGLAnnotationImage; | ||
| @class MGLMapCamera; | ||
| @class MGLStyle; | ||
| @class MGLShape; |
There was a problem hiding this comment.
Can you make these changes to the iOS implementation of MGLMapView also? Thanks!
| around the given coordinate bounds. | ||
| @param animated Specify `YES` to animate the change by smoothly scrolling and | ||
| zooming or `NO` to immediately display the given bounds. | ||
| */ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| 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.
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.
| } | ||
|
|
||
| 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.
The convention throughout mbgl seems to be to use the term "angle" for what might be called "heading" or "bearing" elsewhere.
| 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.
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.
Given #2259, I didn't want to add pitch just yet.
👍 on direction
| around the returned camera object if it were set as the receiver’s camera. | ||
| @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 |
There was a problem hiding this comment.
This method doesn't use the current direction, and it includes the entire shape, not an entire coordinate bounds.
| 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.
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.
Is MapboxMap::getCameraForGeometry() the right syntax for referring to an instance method in Java? I thought it was MapboxMap.getCameraForGeometry().
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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
| * 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.
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:: cameraForLatLngsvariant that allows specifying a heading and returnsCameraOptionswithzoom,center, andangle.