diff options
author | Asheem Mamoowala <asheem.mamoowala@mapbox.com> | 2017-10-02 14:46:25 -0700 |
---|---|---|
committer | Asheem Mamoowala <asheem.mamoowala@mapbox.com> | 2017-10-02 15:10:13 -0700 |
commit | 9fdb7c04b5ecd52d2444ecf422af44215556d56c (patch) | |
tree | 834252b6a0320a2b9f89519707343d58fb20c5d7 | |
parent | 83367f6537d718954d0d0f7b20d7c06377a2cd29 (diff) | |
download | qtlocation-mapboxgl-9fdb7c04b5ecd52d2444ecf422af44215556d56c.tar.gz |
[macOS] Implement `[MGLMapView cameraThatFitsShape:heading:padding] and [MGLMapView setVisibleShape:heading:padding:]`
-rw-r--r-- | platform/macos/src/MGLMapView.h | 29 | ||||
-rw-r--r-- | platform/macos/src/MGLMapView.mm | 77 |
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; |