summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2015-07-30 15:34:49 -0700
committerJustin R. Miller <incanus@codesorcery.net>2015-09-07 09:22:52 -0700
commit0a172a21fdc2a87473560fd7d45f4d495d95de91 (patch)
treee4b0ccd7ee2fecdfe63ead975cbb646493ff2bb4 /platform
parent584c36f348d586bd07d27e6a4c9a7f318a98044c (diff)
downloadqtlocation-mapboxgl-0a172a21fdc2a87473560fd7d45f4d495d95de91.tar.gz
CameraOptions
Plumbed camera options all the way through to MGLMapView. Added a method that lets you specify a direction in addition to center point and zoom level. Added Map::jumpTo() for parity with mapbox-gl-js. Replaced usage of Map::setLatLng() and Map::setLatLngZoom() with Map::jumpTo() or Map::easeTo() within MGLMapView. Replaced MGLMapView.pitch with MGLMapCamera for setting all supported degrees of freedom simultaneously. Simultaneously move and rotate with course. Support customizable timing functions on iOS. iosapp now persists an archived MGLMapCamera instead of separate viewpoint properties and also synchronizes user defaults on termination. This change implements persistence entirely in Objective-C, eliminating the use of the Objective-C++ implementation. Fixes #1643, fixes #1834. Ref #1581.
Diffstat (limited to 'platform')
-rw-r--r--platform/ios/MGLMapCamera.mm101
-rw-r--r--platform/ios/MGLMapView.mm287
2 files changed, 334 insertions, 54 deletions
diff --git a/platform/ios/MGLMapCamera.mm b/platform/ios/MGLMapCamera.mm
new file mode 100644
index 0000000000..d04e46fa90
--- /dev/null
+++ b/platform/ios/MGLMapCamera.mm
@@ -0,0 +1,101 @@
+#import "MGLMapCamera.h"
+
+#include <mbgl/util/projection.hpp>
+
+@implementation MGLMapCamera
+
++ (BOOL)supportsSecureCoding
+{
+ return YES;
+}
+
++ (instancetype)camera
+{
+ return [[self alloc] init];
+}
+
++ (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
+ fromEyeCoordinate:(CLLocationCoordinate2D)eyeCoordinate
+ eyeAltitude:(CLLocationDistance)eyeAltitude
+{
+ mbgl::LatLng centerLatLng = mbgl::LatLng(centerCoordinate.latitude, centerCoordinate.longitude);
+ mbgl::LatLng eyeLatLng = mbgl::LatLng(eyeCoordinate.latitude, eyeCoordinate.longitude);
+
+ mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng);
+ mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng);
+ CLLocationDirection heading = std::atan((centerMeters.northing - eyeMeters.northing) /
+ (centerMeters.easting - eyeMeters.easting));
+
+ double groundDistance = std::hypot(centerMeters.northing - eyeMeters.northing,
+ centerMeters.easting - eyeMeters.easting);
+ CGFloat pitch = std::atan(eyeAltitude / groundDistance);
+
+ return [[self alloc] initWithCenterCoordinate:centerCoordinate
+ altitude:eyeAltitude
+ pitch:pitch
+ heading:heading];
+}
+
++ (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
+ fromDistance:(CLLocationDistance)distance
+ pitch:(CGFloat)pitch
+ heading:(CLLocationDirection)heading
+{
+ return [[self alloc] initWithCenterCoordinate:centerCoordinate
+ altitude:distance
+ pitch:(CGFloat)pitch
+ heading:heading];
+}
+
+- (instancetype)initWithCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
+ altitude:(CLLocationDistance)altitude
+ pitch:(CGFloat)pitch
+ heading:(CLLocationDirection)heading
+{
+ if (self = [super init])
+ {
+ _centerCoordinate = centerCoordinate;
+ _altitude = altitude;
+ _pitch = pitch;
+ _heading = heading;
+ }
+ return self;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)coder
+{
+ if (self = [super init])
+ {
+ _centerCoordinate = CLLocationCoordinate2DMake([coder decodeDoubleForKey:@"centerLatitude"],
+ [coder decodeDoubleForKey:@"centerLongitude"]);
+ _altitude = [coder decodeDoubleForKey:@"altitude"];
+ _pitch = [coder decodeDoubleForKey:@"pitch"];
+ _heading = [coder decodeDoubleForKey:@"heading"];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ [coder encodeDouble:_centerCoordinate.latitude forKey:@"centerLatitude"];
+ [coder encodeDouble:_centerCoordinate.longitude forKey:@"centerLongitude"];
+ [coder encodeDouble:_altitude forKey:@"altitude"];
+ [coder encodeDouble:_pitch forKey:@"pitch"];
+ [coder encodeDouble:_heading forKey:@"heading"];
+}
+
+- (id)copyWithZone:(nullable NSZone *)zone
+{
+ return [[[self class] allocWithZone:zone] initWithCenterCoordinate:_centerCoordinate
+ altitude:_altitude
+ pitch:_pitch
+ heading:_heading];
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"<MKMapCamera %p centerCoordinate:%f, %f altitude:%.0fm heading:%.0f° pitch:%.0f°>",
+ self, _centerCoordinate.latitude, _centerCoordinate.longitude, _altitude, _heading, _pitch];
+}
+
+@end
diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm
index 959f294f07..ef6ae52c33 100644
--- a/platform/ios/MGLMapView.mm
+++ b/platform/ios/MGLMapView.mm
@@ -48,6 +48,9 @@ NSUInteger const MGLStyleVersion = 8;
const NSTimeInterval MGLAnimationDuration = 0.3;
const CGSize MGLAnnotationUpdateViewportOutset = {150, 150};
const CGFloat MGLMinimumZoom = 3;
+const CGFloat MGLMinimumPitch = 0;
+const CGFloat MGLMaximumPitch = 60;
+const CLLocationDegrees MGLAngularFieldOfView = M_PI / 6.;
NSString *const MGLAnnotationIDKey = @"MGLAnnotationIDKey";
NSString *const MGLAnnotationSymbolKey = @"MGLAnnotationSymbolKey";
@@ -67,6 +70,18 @@ CLLocationDegrees MGLDegreesFromRadians(CGFloat radians)
return radians * 180 / M_PI;
}
+mbgl::util::UnitBezier MGLUnitBezierForMediaTimingFunction(CAMediaTimingFunction *function)
+{
+ if ( ! function)
+ {
+ function = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
+ }
+ float p1[2], p2[2];
+ [function getControlPointAtIndex:0 values:p1];
+ [function getControlPointAtIndex:1 values:p2];
+ return { p1[0], p1[1], p2[0], p2[1] };
+}
+
#pragma mark - Private -
@interface MGLMapView () <UIGestureRecognizerDelegate, GLKViewDelegate, CLLocationManagerDelegate, UIActionSheetDelegate>
@@ -368,7 +383,10 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
// set initial position
//
- _mbglMap->setLatLngZoom(mbgl::LatLng(0, 0), _mbglMap->getMinZoom());
+ mbgl::CameraOptions options;
+ options.center = mbgl::LatLng(0, 0);
+ options.zoom = _mbglMap->getMinZoom();
+ _mbglMap->jumpTo(options);
_pendingLatitude = NAN;
_pendingLongitude = NAN;
@@ -1347,12 +1365,10 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
else if (twoFingerDrag.state == UIGestureRecognizerStateBegan || twoFingerDrag.state == UIGestureRecognizerStateChanged)
{
CGFloat gestureDistance = CGPoint([twoFingerDrag translationInView:twoFingerDrag.view]).y;
- double currentPitch = _mbglMap->getPitch();
- double minPitch = 0;
- double maxPitch = 60.0;
- double slowdown = 20.0;
+ CGFloat currentPitch = _mbglMap->getPitch();
+ CGFloat slowdown = 20.0;
- double pitchNew = fmax(fmin(currentPitch - (gestureDistance / slowdown), maxPitch), minPitch);
+ CGFloat pitchNew = mbgl::util::clamp(currentPitch - (gestureDistance / slowdown), MGLMinimumPitch, MGLMaximumPitch);
_mbglMap->setPitch(pitchNew);
}
@@ -1530,7 +1546,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingCenterCoordinate
{
- return [NSSet setWithObjects:@"latitude", @"longitude", nil];
+ return [NSSet setWithObjects:@"latitude", @"longitude", @"camera", nil];
}
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated preservingTracking:(BOOL)tracking
@@ -1542,13 +1558,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated
{
- CGFloat duration = (animated ? MGLAnimationDuration : 0);
-
- _mbglMap->setLatLngZoom(MGLLatLngFromLocationCoordinate2D(coordinate),
- fmaxf(_mbglMap->getZoom(), self.currentMinimumZoom),
- secondsAsDuration(duration));
-
- [self notifyMapChange:(animated ? mbgl::MapChangeRegionDidChangeAnimated : mbgl::MapChangeRegionDidChange)];
+ [self setCenterCoordinate:coordinate zoomLevel:self.zoomLevel animated:animated];
}
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
@@ -1563,35 +1573,45 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel animated:(BOOL)animated
{
+ [self setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:self.direction animated:animated];
+}
+
+- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated
+{
self.userTrackingMode = MGLUserTrackingModeNone;
- CGFloat duration = (animated ? MGLAnimationDuration : 0);
+ [self _setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:direction animated:animated];
+}
- _mbglMap->setLatLngZoom(MGLLatLngFromLocationCoordinate2D(centerCoordinate), zoomLevel, secondsAsDuration(duration));
+- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated
+{
+ mbgl::CameraOptions options;
+ options.center = MGLLatLngFromLocationCoordinate2D(centerCoordinate);
+ options.zoom = fmaxf(zoomLevel, self.currentMinimumZoom);
+ if (direction >= 0)
+ {
+ options.angle = MGLRadiansFromDegrees(-direction);
+ }
+ if (animated)
+ {
+ options.duration = secondsAsDuration(MGLAnimationDuration);
+ options.easing = MGLUnitBezierForMediaTimingFunction(nil);
+ }
+ _mbglMap->easeTo(options);
[self unrotateIfNeededAnimated:animated];
[self notifyMapChange:(animated ? mbgl::MapChangeRegionDidChangeAnimated : mbgl::MapChangeRegionDidChange)];
}
-- (double)zoomLevel
++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingZoomLevel
{
- return _mbglMap->getZoom();
+ return [NSSet setWithObject:@"camera"];
}
-- (void)setZoomLevel:(double)zoomLevel animated:(BOOL)animated
+- (double)zoomLevel
{
- self.userTrackingMode = MGLUserTrackingModeNone;
-
- CGFloat duration = (animated ? MGLAnimationDuration : 0);
-
- _mbglMap->setLatLngZoom(_mbglMap->getLatLng(),
- fmaxf(zoomLevel, self.currentMinimumZoom),
- secondsAsDuration(duration));
-
- [self unrotateIfNeededAnimated:animated];
-
- [self notifyMapChange:(animated ? mbgl::MapChangeRegionDidChangeAnimated : mbgl::MapChangeRegionDidChange)];
+ return _mbglMap->getZoom();
}
- (void)setZoomLevel:(double)zoomLevel
@@ -1599,6 +1619,11 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
[self setZoomLevel:zoomLevel animated:NO];
}
+- (void)setZoomLevel:(double)zoomLevel animated:(BOOL)animated
+{
+ [self setCenterCoordinate:self.centerCoordinate zoomLevel:zoomLevel animated:animated];
+}
+
MGLCoordinateBounds MGLCoordinateBoundsFromLatLngBounds(mbgl::LatLngBounds latLngBounds)
{
return MGLCoordinateBoundsMake(MGLLocationCoordinate2DFromLatLng(latLngBounds.sw),
@@ -1639,11 +1664,34 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord
animated:animated];
}
+- (void)setVisibleCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction animated:(BOOL)animated
+{
+ CLLocationCoordinate2D coordinates[] = {
+ {bounds.ne.latitude, bounds.sw.longitude},
+ bounds.sw,
+ {bounds.sw.latitude, bounds.ne.longitude},
+ bounds.ne,
+ };
+ [self setVisibleCoordinates:coordinates
+ count:sizeof(coordinates) / sizeof(coordinates[0])
+ edgePadding:insets
+ direction:direction
+ animated:animated];
+}
+
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated
{
+ [self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:self.direction animated:animated];
+}
+
+- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction animated:(BOOL)animated
+{
+ [self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil];
+}
+
+- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(CAMediaTimingFunction *)function
+{
// NOTE: does not disrupt tracking mode
- CGFloat duration = animated ? MGLAnimationDuration : 0;
-
[self willChangeValueForKey:@"visibleCoordinateBounds"];
mbgl::EdgeInsets mbglInsets = {insets.top, insets.left, insets.bottom, insets.right};
mbgl::AnnotationSegment segment;
@@ -1652,12 +1700,27 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord
{
segment.push_back({coordinates[i].latitude, coordinates[i].longitude});
}
- _mbglMap->fitBounds(segment, mbglInsets, secondsAsDuration(duration));
+ mbgl::CameraOptions options = _mbglMap->cameraForLatLngs(segment, mbglInsets);
+ if (direction >= 0)
+ {
+ options.angle = MGLRadiansFromDegrees(-direction);
+ }
+ if (duration > 0)
+ {
+ options.duration = secondsAsDuration(duration);
+ options.easing = MGLUnitBezierForMediaTimingFunction(function);
+ }
+ _mbglMap->easeTo(options);
[self didChangeValueForKey:@"visibleCoordinateBounds"];
- [self unrotateIfNeededAnimated:animated];
+ [self unrotateIfNeededAnimated:duration > 0];
- [self notifyMapChange:(animated ? mbgl::MapChangeRegionDidChangeAnimated : mbgl::MapChangeRegionDidChange)];
+ [self notifyMapChange:(duration > 0 ? mbgl::MapChangeRegionDidChangeAnimated : mbgl::MapChangeRegionDidChange)];
+}
+
++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingDirection
+{
+ return [NSSet setWithObject:@"camera"];
}
- (CLLocationDirection)direction
@@ -1683,23 +1746,139 @@ mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBounds coord
[self setDirection:direction animated:NO];
}
-- (double)pitch
++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingPitch
{
- return _mbglMap->getPitch();
+ return [NSSet setWithObject:@"camera"];
}
-- (void)setPitch:(double)pitch
++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingCamera
{
- // constrain pitch to between 0º and 60º
- //
- _mbglMap->setPitch(fmax(fmin(pitch, 60), 0));
+ return [NSSet setWithObjects:@"longitude", @"latitude", @"centerCoordinate", @"zoomLevel", @"direction", nil];
+}
+
+- (MGLMapCamera *)camera
+{
+ CGRect frame = self.frame;
+ CGPoint edgePoint;
+ // Constrain by the shorter of the two axes.
+ if (frame.size.width > frame.size.height) // landscape
+ {
+ edgePoint = CGPointMake(0, frame.size.height / 2.);
+ }
+ else // portrait
+ {
+ edgePoint = CGPointMake(frame.size.width / 2., 0);
+ }
+ CLLocationCoordinate2D edgeCoordinate = [self convertPoint:edgePoint toCoordinateFromView:self];
+ mbgl::ProjectedMeters edgeMeters = _mbglMap->projectedMetersForLatLng(MGLLatLngFromLocationCoordinate2D(edgeCoordinate));
+
+ // Because we constrain the zoom level vertically in portrait orientation,
+ // the visible medial span is affected by pitch: the distance from the
+ // center point to the near edge is less than than distance from the center
+ // point to the far edge. Average the two distances.
+ mbgl::ProjectedMeters nearEdgeMeters;
+ if (frame.size.width > frame.size.height)
+ {
+ nearEdgeMeters = edgeMeters;
+ }
+ else
+ {
+ CGPoint nearEdgePoint = CGPointMake(frame.size.width / 2., frame.size.height);
+ CLLocationCoordinate2D nearEdgeCoordinate = [self convertPoint:nearEdgePoint toCoordinateFromView:self];
+ nearEdgeMeters = _mbglMap->projectedMetersForLatLng(MGLLatLngFromLocationCoordinate2D(nearEdgeCoordinate));
+ }
+
+ // The opposite side is the distance between the center and one edge.
+ CLLocationCoordinate2D centerCoordinate = self.centerCoordinate;
+ mbgl::ProjectedMeters centerMeters = _mbglMap->projectedMetersForLatLng(MGLLatLngFromLocationCoordinate2D(centerCoordinate));
+ CLLocationDistance centerToEdge = std::hypot(centerMeters.easting - edgeMeters.easting,
+ centerMeters.northing - edgeMeters.northing);
+ CLLocationDistance centerToNearEdge = std::hypot(centerMeters.easting - nearEdgeMeters.easting,
+ centerMeters.northing - nearEdgeMeters.northing);
+ CLLocationDistance altitude = (centerToEdge + centerToNearEdge) / 2 / std::tan(MGLAngularFieldOfView / 2.);
- //[self notifyMapChange:(mbgl::MapChangeRegionDidChange)];
+ CGFloat pitch = _mbglMap->getPitch();
+
+ return [MGLMapCamera cameraLookingAtCenterCoordinate:centerCoordinate
+ fromDistance:altitude
+ pitch:pitch
+ heading:self.direction];
}
-- (void)resetPitch
+- (void)setCamera:(MGLMapCamera *)camera
{
- [self setPitch:0];
+ [self setCamera:camera animated:NO];
+}
+
+- (void)setCamera:(MGLMapCamera *)camera animated:(BOOL)animated
+{
+ [self setCamera:camera withDuration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil];
+}
+
+- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(CAMediaTimingFunction *)function
+{
+ // The opposite side is the distance between the center and one edge.
+ mbgl::LatLng centerLatLng = MGLLatLngFromLocationCoordinate2D(camera.centerCoordinate);
+ mbgl::ProjectedMeters centerMeters = _mbglMap->projectedMetersForLatLng(centerLatLng);
+ CLLocationDistance centerToEdge = camera.altitude * std::tan(MGLAngularFieldOfView / 2.);
+
+ double angle = -1;
+ if (camera.heading >= 0)
+ {
+ angle = MGLRadiansFromDegrees(mbgl::util::wrap(-camera.heading, 0., 360.));
+ }
+ double pitch = -1;
+ if (camera.pitch >= 0)
+ {
+ pitch = MGLRadiansFromDegrees(mbgl::util::clamp(camera.pitch, MGLMinimumPitch, MGLMaximumPitch));
+ }
+
+ // Make a visible bounds that extends in the constrained direction (the
+ // shorter of the two axes).
+ CGRect frame = self.frame;
+ mbgl::LatLng sw, ne;
+ if (frame.size.width > frame.size.height) // landscape
+ {
+ sw = _mbglMap->latLngForProjectedMeters({
+ centerMeters.northing - centerToEdge * std::sin(angle),
+ centerMeters.easting - centerToEdge * std::cos(angle),
+ });
+ ne = _mbglMap->latLngForProjectedMeters({
+ centerMeters.northing + centerToEdge * std::sin(angle),
+ centerMeters.easting + centerToEdge * std::cos(angle),
+ });
+ }
+ else // portrait
+ {
+ sw = _mbglMap->latLngForProjectedMeters({
+ centerMeters.northing - centerToEdge * std::cos(angle) + centerToEdge * std::cos(angle) * std::sin(pitch) / 2,
+ centerMeters.easting - centerToEdge * std::sin(angle) + centerToEdge * std::sin(angle) * std::sin(pitch) / 2,
+ });
+ ne = _mbglMap->latLngForProjectedMeters({
+ centerMeters.northing + centerToEdge * std::cos(angle) - centerToEdge * std::cos(angle) * std::sin(pitch) / 2,
+ centerMeters.easting + centerToEdge * std::sin(angle) - centerToEdge * std::sin(angle) * std::sin(pitch) / 2,
+ });
+ }
+
+ // Fit the viewport to the bounds. Correct the center in case pitch should
+ // cause the visual center to lie above the screen center.
+ mbgl::CameraOptions options = _mbglMap->cameraForLatLngs({ sw, ne }, {});
+ options.center = centerLatLng;
+
+ if (angle >= 0)
+ {
+ options.angle = angle;
+ }
+ if (pitch >= 0)
+ {
+ options.pitch = pitch;
+ }
+ if (duration > 0)
+ {
+ options.duration = secondsAsDuration(duration);
+ options.easing = MGLUnitBezierForMediaTimingFunction(function);
+ }
+ _mbglMap->easeTo(options);
}
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(nullable UIView *)view
@@ -2482,6 +2661,12 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng)
[self.delegate mapView:self didUpdateUserLocation:self.userLocation];
}
}
+
+ CLLocationDirection course = self.userLocation.location.course;
+ if (course < 0 || self.userTrackingMode != MGLUserTrackingModeFollowWithCourse)
+ {
+ course = -1;
+ }
if (self.userTrackingMode != MGLUserTrackingModeNone)
{
@@ -2496,7 +2681,7 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng)
{
// at sufficient detail, just re-center the map; don't zoom
//
- [self setCenterCoordinate:self.userLocation.location.coordinate animated:YES preservingTracking:YES];
+ [self _setCenterCoordinate:self.userLocation.location.coordinate zoomLevel:self.zoomLevel direction:course animated:YES];
}
else
{
@@ -2526,17 +2711,11 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng)
desiredSouthWest.longitude != actualSouthWest.longitude)
{
// assumes we won't disrupt tracking mode
- [self setVisibleCoordinateBounds:MGLCoordinateBoundsMake(desiredSouthWest, desiredNorthEast) animated:YES];
+ [self setVisibleCoordinateBounds:MGLCoordinateBoundsMake(desiredSouthWest, desiredNorthEast) edgePadding:UIEdgeInsetsZero direction:course animated:YES];
}
}
}
}
-
- CLLocationDirection course = self.userLocation.location.course;
- if (course >= 0 && self.userTrackingMode == MGLUserTrackingModeFollowWithCourse)
- {
- _mbglMap->setBearing(course);
- }
self.userLocationAnnotationView.haloLayer.hidden = ! CLLocationCoordinate2DIsValid(self.userLocation.coordinate) ||
newLocation.horizontalAccuracy > 10;
@@ -3088,7 +3267,7 @@ class MBGLView : public mbgl::View
+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingLatitude
{
- return [NSSet setWithObject:@"centerCoordinate"];
+ return [NSSet setWithObjects:@"centerCoordinate", @"camera", nil];
}
- (double)latitude
@@ -3114,7 +3293,7 @@ class MBGLView : public mbgl::View
+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingLongitude
{
- return [NSSet setWithObject:@"centerCoordinate"];
+ return [NSSet setWithObjects:@"centerCoordinate", @"camera", nil];
}
- (double)longitude