summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsheem Mamoowala <asheem.mamoowala@mapbox.com>2017-10-02 14:46:25 -0700
committerAsheem Mamoowala <asheem.mamoowala@mapbox.com>2017-10-02 15:10:13 -0700
commit9fdb7c04b5ecd52d2444ecf422af44215556d56c (patch)
tree834252b6a0320a2b9f89519707343d58fb20c5d7
parent83367f6537d718954d0d0f7b20d7c06377a2cd29 (diff)
downloadqtlocation-mapboxgl-9fdb7c04b5ecd52d2444ecf422af44215556d56c.tar.gz
[macOS] Implement `[MGLMapView cameraThatFitsShape:heading:padding] and [MGLMapView setVisibleShape:heading:padding:]`
-rw-r--r--platform/macos/src/MGLMapView.h29
-rw-r--r--platform/macos/src/MGLMapView.mm77
2 files changed, 106 insertions, 0 deletions
diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h
index 04c2e77110..bf7484e9f2 100644
--- a/platform/macos/src/MGLMapView.h
+++ b/platform/macos/src/MGLMapView.h
@@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN
@class MGLAnnotationImage;
@class MGLMapCamera;
@class MGLStyle;
+@class MGLShape;
@protocol MGLAnnotation;
@protocol MGLMapViewDelegate;
@@ -403,6 +404,19 @@ MGL_EXPORT IB_DESIGNABLE
- (void)setVisibleCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets animated:(BOOL)animated;
/**
+ Changes the receiver’s viewport to fit the given shape, with the specified heading,
+ and optionally some additional padding on each side.
+
+ @param shape The shape that the viewport will show in its entirety.
+ @param heading The heading of the viewport, measured in degrees clockwise from true north.
+ @param insets The minimum padding (in screen points) that will be visible
+ 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.
+ */
+- (void)setVisibleShape:(MGLShape *)shape heading:(double)heading edgePadding:(NSEdgeInsets)insets animated:(BOOL)animated;
+
+/**
Sets the visible region so that the map displays the specified annotations.
Calling this method updates the value in the `visibleCoordinateBounds` property
@@ -457,6 +471,21 @@ MGL_EXPORT IB_DESIGNABLE
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets;
/**
+ Returns the camera that best fits the given shape, with the specified heading,
+ optionally with some additional padding on each side.
+
+ @param shape The shape to fit to the receiver’s viewport.
+ @param heading The heading of the viewport, measured in degrees clockwise from true north.
+ @param insets The minimum padding (in screen points) that would be visible
+ 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
+ direction and pitch.
+ */
+- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape heading:(double)heading edgePadding:(NSEdgeInsets)insets;
+
+/**
A Boolean value indicating whether the receiver automatically adjusts its
content insets.
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index eb4099f330..00c50cd598 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -14,6 +14,7 @@
#import "MGLMultiPoint_Private.h"
#import "MGLOfflineStorage_Private.h"
#import "MGLStyle_Private.h"
+#import "MGLMultiPoint_Private.h"
#import "MGLAccountManager.h"
#import "MGLMapCamera.h"
@@ -126,6 +127,46 @@ mbgl::util::UnitBezier MGLUnitBezierForMediaTimingFunction(CAMediaTimingFunction
return { p1[0], p1[1], p2[0], p2[1] };
}
+std::vector<mbgl::LatLng> coordinatesForShape(MGLShape *shape) {
+ std::vector<mbgl::LatLng> latLngs;
+ if ([shape isKindOfClass:[MGLMultiPoint class]]) {
+ MGLMultiPoint *multiPoint = (MGLMultiPoint *)shape;
+ latLngs.reserve(multiPoint.pointCount);
+ CLLocationCoordinate2D *coordinates = multiPoint.coordinates;
+ for(int i=0; i < [multiPoint pointCount]; i++) {
+ latLngs.push_back({coordinates[i].latitude, coordinates[i].longitude});
+ }
+ } else if ([shape isKindOfClass:[MGLPointCollection class]]) {
+ MGLPointCollection *pointCollection = (MGLPointCollection *)shape;
+ latLngs.reserve(pointCollection.pointCount);
+ CLLocationCoordinate2D *coordinates = pointCollection.coordinates;
+ for(int i=0; i < [pointCollection pointCount]; i++) {
+ latLngs.push_back({coordinates[i].latitude, coordinates[i].longitude});
+ }
+ } else if ([shape isKindOfClass:[MGLMultiPolygon class]]) {
+ MGLMultiPolygon *shapeCollection = (MGLMultiPolygon *)shape;
+ for(MGLPolygon *s in shapeCollection.polygons) {
+ auto shapeLatLngs = coordinatesForShape(s);
+ latLngs.insert(latLngs.end(), shapeLatLngs.begin(), shapeLatLngs.end());
+ }
+ } else if ([shape isKindOfClass:[MGLMultiPolyline class]]) {
+ MGLMultiPolyline *shapeCollection = (MGLMultiPolyline *)shape;
+ for(MGLPolyline *s in shapeCollection.polylines) {
+ auto shapeLatLngs = coordinatesForShape(s);
+ latLngs.insert(latLngs.end(), shapeLatLngs.begin(), shapeLatLngs.end());
+ }
+ } else if ([shape isKindOfClass:[MGLShapeCollection class]]) {
+ MGLShapeCollection *shapeCollection = (MGLShapeCollection *)shape;
+ for(MGLShape *s in shapeCollection.shapes) {
+ auto shapeLatLngs = coordinatesForShape(s);
+ latLngs.insert(latLngs.end(), shapeLatLngs.begin(), shapeLatLngs.end());
+ }
+ } else {
+ NSLog(@"Shape doesn't have multiple points");
+ }
+ return latLngs;
+}
+
/// Lightweight container for metadata about an annotation, including the annotation itself.
class MGLAnnotationContext {
public:
@@ -1256,6 +1297,32 @@ public:
_mbglMap->easeTo(cameraOptions, animationOptions);
}
+- (void)setVisibleShape:(MGLMultiPoint *)shape heading:(double)heading edgePadding:(NSEdgeInsets)insets animated:(BOOL)animated {
+ _mbglMap->cancelTransitions();
+
+ mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
+ padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
+
+ std::vector<mbgl::LatLng> latLngs = coordinatesForShape(shape);
+ mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngs(latLngs, heading, padding);
+
+ mbgl::AnimationOptions animationOptions;
+ if (animated) {
+ animationOptions.duration = MGLDurationFromTimeInterval(MGLAnimationDuration);
+ }
+
+ MGLMapCamera *camera = [self cameraForCameraOptions:cameraOptions];
+ if ([self.camera isEqualToMapCamera:camera]) {
+ return;
+ }
+
+ [self willChangeValueForKey:@"visibleCoordinateBounds"];
+ animationOptions.transitionFinishFn = ^() {
+ [self didChangeValueForKey:@"visibleCoordinateBounds"];
+ };
+ _mbglMap->easeTo(cameraOptions, animationOptions);
+}
+
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds {
return [self cameraThatFitsCoordinateBounds:bounds edgePadding:NSEdgeInsetsZero];
}
@@ -1267,6 +1334,16 @@ public:
return [self cameraForCameraOptions:cameraOptions];
}
+- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape heading:(double)heading edgePadding:(NSEdgeInsets)insets {
+ mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
+ padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
+
+ std::vector<mbgl::LatLng> latLngs = coordinatesForShape(shape);
+ mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngs(latLngs, heading, padding);
+
+ return [self cameraForCameraOptions:cameraOptions];
+}
+
- (MGLMapCamera *)cameraForCameraOptions:(const mbgl::CameraOptions &)cameraOptions {
CLLocationCoordinate2D centerCoordinate = MGLLocationCoordinate2DFromLatLng(cameraOptions.center ? *cameraOptions.center : _mbglMap->getLatLng());
double zoomLevel = cameraOptions.zoom ? *cameraOptions.zoom : self.zoomLevel;