[core, ios, osx] cameraThatFitsCoordinateBounds

Added an API to get a camera that you can pass into -[MGLMapView setCamera:] that fits the given coordinate bounds, by analogy with -[MKMapView regionThatFits:] or -[MKMapView mapRectThatFits:edgePadding:].

Added mbgl::Map::getCameraOptions() for getting the current camera options more conveniently.
This commit is contained in:
Minh Nguyễn
2016-04-21 17:23:09 -07:00
committed by Minh Nguyễn
parent 5939dd5b41
commit 466ed55200
10 changed files with 134 additions and 28 deletions

View File

@@ -69,6 +69,7 @@ public:
bool isPanning() const;
// Camera
CameraOptions getCameraOptions(optional<EdgeInsets>) const;
void jumpTo(const CameraOptions&);
void easeTo(const CameraOptions&, const AnimationOptions&);
void flyTo(const CameraOptions&, const AnimationOptions&);
@@ -90,8 +91,8 @@ public:
double getZoom() const;
void setLatLngZoom(const LatLng&, double zoom, const Duration& = Duration::zero());
void setLatLngZoom(const LatLng&, double zoom, optional<EdgeInsets>, const Duration& = Duration::zero());
CameraOptions cameraForLatLngBounds(const LatLngBounds&, optional<EdgeInsets>);
CameraOptions cameraForLatLngs(const std::vector<LatLng>&, optional<EdgeInsets>);
CameraOptions cameraForLatLngBounds(const LatLngBounds&, optional<EdgeInsets>) const;
CameraOptions cameraForLatLngs(const std::vector<LatLng>&, optional<EdgeInsets>) const;
void resetZoom();
void setMinZoom(const double minZoom);
double getMinZoom() const;

View File

@@ -13,6 +13,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CON
- Rendering now occurs on the main thread, fixing a hang when calling `-[MGLMapView styleURL]` before the map view has fully loaded or while the application is in the background. ([#2909](https://github.com/mapbox/mapbox-gl-native/pull/2909))
- Added category methods on NSValue for converting to and from the structure types defined in MGLGeometry.h. ([#4802](https://github.com/mapbox/mapbox-gl-native/pull/4802))
- Added NSFormatter subclasses for converting geographic coordinates and directions into display strings. ([#4802](https://github.com/mapbox/mapbox-gl-native/pull/4802))
- Added a new method, `-[MGLMapView cameraThatFitsCoordinateBounds:]`, to get a camera that you can pass into `-setCamera:` that fits the given coordinate bounds. ([#4790](https://github.com/mapbox/mapbox-gl-native/pull/4790))
- Added a `-reloadStyle:` action to MGLMapView to force a reload of the current style. ([#4728](https://github.com/mapbox/mapbox-gl-native/pull/4728))
- A more specific user agent string is now sent with style and tile requests. ([#4012](https://github.com/mapbox/mapbox-gl-native/pull/4012))
- Mapbox Telemetry is automatically disabled while the host application is running in the iOS Simulator. ([#4726](https://github.com/mapbox/mapbox-gl-native/pull/4726))

View File

@@ -732,6 +732,31 @@ IB_DESIGNABLE
*/
- (void)flyToCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration peakAltitude:(CLLocationDistance)peakAltitude completionHandler:(nullable void (^)(void))completion;
/**
Returns the camera that best fits the given coordinate bounds.
@param bounds The coordinate bounds to fit to the receiver’s viewport.
@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 *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds;
/**
Returns the camera that best fits the given coordinate bounds, optionally with
some additional padding on each side.
@param bounds The coordinate bounds to fit to the receiver’s viewport.
@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 *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets;
/**
The distance from the edges of the map view’s frame to the edges of the map
view’s logical viewport.

View File

@@ -2023,14 +2023,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
- (MGLMapCamera *)camera
{
CGFloat pitch = _mbglMap->getPitch();
CLLocationDistance altitude = MGLAltitudeForZoomLevel(self.zoomLevel, pitch,
self.centerCoordinate.latitude,
self.frame.size);
return [MGLMapCamera cameraLookingAtCenterCoordinate:self.centerCoordinate
fromDistance:altitude
pitch:pitch
heading:self.direction];
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
return [self cameraForCameraOptions:_mbglMap->getCameraOptions(padding)];
}
- (void)setCamera:(MGLMapCamera *)camera
@@ -2130,6 +2124,29 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
[self didChangeValueForKey:@"camera"];
}
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds
{
return [self cameraThatFitsCoordinateBounds:bounds edgePadding:UIEdgeInsetsZero];
}
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets
{
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), 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;
CLLocationDirection direction = cameraOptions.angle ? *cameraOptions.angle : self.direction;
CGFloat pitch = cameraOptions.pitch ? *cameraOptions.pitch : _mbglMap->getPitch();
CLLocationDistance altitude = MGLAltitudeForZoomLevel(zoomLevel, pitch, centerCoordinate.latitude, self.frame.size);
return [MGLMapCamera cameraLookingAtCenterCoordinate:centerCoordinate fromDistance:altitude pitch:pitch heading:direction];
}
/// Returns a CameraOptions object that specifies parameters for animating to
/// the given camera.
- (mbgl::CameraOptions)cameraOptionsObjectForAnimatingToCamera:(MGLMapCamera *)camera edgePadding:(UIEdgeInsets)insets

View File

@@ -325,6 +325,41 @@ IB_DESIGNABLE
and zooming or `NO` to immediately display the given bounds. */
- (void)setVisibleCoordinateBounds:(MGLCoordinateBounds)bounds animated:(BOOL)animated;
/** Changes the receiver’s viewport to fit the given coordinate bounds and
optionally some additional padding on each side.
@param bounds The bounds that the viewport will show in its entirety.
@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)setVisibleCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets animated:(BOOL)animated;
/** Returns the camera that best fits the given coordinate bounds.
@param bounds The coordinate bounds to fit to the receiver’s viewport.
@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 *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds;
/** Returns the camera that best fits the given coordinate bounds, optionally
with some additional padding on each side.
@param bounds The coordinate bounds to fit to the receiver’s viewport.
@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 *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets;
/** A Boolean value indicating whether the receiver automatically adjusts its
content insets.

View File

@@ -284,7 +284,6 @@
DA839E891CC2E3400062CAFB = {
isa = PBXGroup;
children = (
DAE6C3C31CC31F6900DB3429 /* Configuration */,
DA839E941CC2E3400062CAFB /* Demo App */,
DAE6C3291CC30DB200DB3429 /* SDK */,
DAE6C3371CC30DB200DB3429 /* SDK Tests */,
@@ -461,13 +460,6 @@
name = Kit;
sourceTree = "<group>";
};
DAE6C3C31CC31F6900DB3429 /* Configuration */ = {
isa = PBXGroup;
children = (
);
name = Configuration;
sourceTree = "<group>";
};
DAE6C3C41CC31F7800DB3429 /* Configuration */ = {
isa = PBXGroup;
children = (

View File

@@ -1003,14 +1003,8 @@ public:
}
- (MGLMapCamera *)camera {
CGFloat pitch = _mbglMap->getPitch();
CLLocationDistance altitude = MGLAltitudeForZoomLevel(self.zoomLevel, pitch,
self.centerCoordinate.latitude,
self.frame.size);
return [MGLMapCamera cameraLookingAtCenterCoordinate:self.centerCoordinate
fromDistance:altitude
pitch:pitch
heading:self.direction];
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
return [self cameraForCameraOptions:_mbglMap->getCameraOptions(padding)];
}
- (void)setCamera:(MGLMapCamera *)camera {
@@ -1142,6 +1136,31 @@ public:
_mbglMap->easeTo(cameraOptions, animationOptions);
}
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds {
return [self cameraThatFitsCoordinateBounds:bounds edgePadding:NSEdgeInsetsZero];
}
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(NSEdgeInsets)insets {
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInsets);
mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), 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;
CLLocationDirection direction = cameraOptions.angle ? *cameraOptions.angle : self.direction;
CGFloat pitch = cameraOptions.pitch ? *cameraOptions.pitch : _mbglMap->getPitch();
CLLocationDistance altitude = MGLAltitudeForZoomLevel(zoomLevel, pitch,
centerCoordinate.latitude,
self.frame.size);
return [MGLMapCamera cameraLookingAtCenterCoordinate:centerCoordinate
fromDistance:altitude
pitch:pitch
heading:direction];
}
- (void)setAutomaticallyAdjustsContentInsets:(BOOL)automaticallyAdjustsContentInsets {
_automaticallyAdjustsContentInsets = automaticallyAdjustsContentInsets;
[self adjustContentInsets];

View File

@@ -375,6 +375,10 @@ bool Map::isPanning() const {
}
#pragma mark -
CameraOptions Map::getCameraOptions(optional<EdgeInsets> padding) const {
return impl->transform.getCameraOptions(padding);
}
void Map::jumpTo(const CameraOptions& camera) {
impl->transform.jumpTo(camera);
@@ -466,7 +470,7 @@ void Map::setLatLngZoom(const LatLng& latLng, double zoom, optional<EdgeInsets>
update(Update::RecalculateStyle);
}
CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, optional<EdgeInsets> padding) {
CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, optional<EdgeInsets> padding) const {
AnnotationSegment segment = {
bounds.northwest(),
bounds.southwest(),
@@ -476,7 +480,7 @@ CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, optional<Ed
return cameraForLatLngs(segment, padding);
}
CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, optional<EdgeInsets> padding) {
CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, optional<EdgeInsets> padding) const {
CameraOptions options;
if (latLngs.empty()) {
return options;

View File

@@ -62,6 +62,16 @@ bool Transform::resize(const std::array<uint16_t, 2> size) {
#pragma mark - Camera
CameraOptions Transform::getCameraOptions(optional<EdgeInsets> padding) const {
CameraOptions camera;
camera.center = getLatLng(padding);
camera.padding = padding;
camera.zoom = getZoom();
camera.angle = getAngle();
camera.pitch = getPitch();
return camera;
}
/**
* Change any combination of center, zoom, bearing, and pitch, without
* a transition. The map will retain the current values for any options

View File

@@ -26,6 +26,8 @@ public:
bool resize(std::array<uint16_t, 2> size);
// Camera
/** Returns the current camera options. */
CameraOptions getCameraOptions(optional<EdgeInsets>) const;
/** Instantaneously, synchronously applies the given camera options. */
void jumpTo(const CameraOptions&);