summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Wray <jason@mapbox.com>2019-03-11 19:15:57 -0700
committerJason Wray <jason@mapbox.com>2019-03-11 19:22:51 -0700
commit0c0790d5f276947853c674f0dbe54811bc7abf12 (patch)
tree14c764baa4e85458bf9232d9e410888fb02cffa0
parent60ceac5efc3d77199f773f08400fe1d53d5a1b90 (diff)
downloadqtlocation-mapboxgl-upstream/friedbunny-fixes-ios-direction-wrapping.tar.gz
-rw-r--r--include/mbgl/map/camera.hpp2
-rw-r--r--platform/darwin/test/MGLMapViewTests.m23
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj4
-rw-r--r--platform/ios/src/MGLMapView.mm2
-rw-r--r--platform/ios/test/MGLMapViewDirectionTests.mm85
-rw-r--r--platform/macos/src/MGLMapView.mm2
6 files changed, 104 insertions, 14 deletions
diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp
index e3d6677c0a..ff08334ade 100644
--- a/include/mbgl/map/camera.hpp
+++ b/include/mbgl/map/camera.hpp
@@ -37,7 +37,7 @@ struct CameraOptions {
levels. */
optional<double> zoom;
- /** Bearing, measured in degrees from true north. Wrapped to [0, 360). */
+ /** Bearing, measured in degrees from true north. Wrapped to [0, 360]. */
optional<double> bearing;
/** Pitch toward the horizon measured in degrees , with 0 deg resulting in a
diff --git a/platform/darwin/test/MGLMapViewTests.m b/platform/darwin/test/MGLMapViewTests.m
index eb40ff724a..9a8e7bdb64 100644
--- a/platform/darwin/test/MGLMapViewTests.m
+++ b/platform/darwin/test/MGLMapViewTests.m
@@ -4,20 +4,27 @@
static MGLMapView *mapView;
@interface MGLMapViewTests : XCTestCase
-
@end
@implementation MGLMapViewTests
-+ (void)setUp {
+- (void)setUp {
[super setUp];
[MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
- mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 64, 64) styleURL:MGLStyle.streetsStyleURL];
- [mapView setCenterCoordinate:CLLocationCoordinate2DMake(33, 179)];
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 64, 64) styleURL:styleURL];
+}
+
+- (void)tearDown {
+ mapView = nil;
+ [MGLAccountManager setAccessToken:nil];
+ [super tearDown];
}
- (void)testCoordinateBoundsConversion {
+ [mapView setCenterCoordinate:CLLocationCoordinate2DMake(33, 179)];
+
MGLCoordinateBounds leftAntimeridianBounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(-75, 175), CLLocationCoordinate2DMake(75, 180));
CGRect leftAntimeridianBoundsRect = [mapView convertCoordinateBounds:leftAntimeridianBounds toRectToView:mapView];
@@ -30,14 +37,8 @@ static MGLMapView *mapView;
// If the resulting CGRect from -convertCoordinateBounds:toRectToView:
// intersects the set of bounds to the left and right of the
// antimeridian, then we know that the CGRect spans across the antimeridian
- XCTAssertTrue(CGRectIntersectsRect(spanningBoundsRect, leftAntimeridianBoundsRect), @"Resulting ");
+ XCTAssertTrue(CGRectIntersectsRect(spanningBoundsRect, leftAntimeridianBoundsRect), @"Resulting");
XCTAssertTrue(CGRectIntersectsRect(spanningBoundsRect, rightAntimeridianBoundsRect), @"Something");
}
-+ (void)tearDown {
- mapView = nil;
- [MGLAccountManager setAccessToken:nil];
- [super tearDown];
-}
-
@end
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 9d75424afd..cec8476fcc 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -458,6 +458,7 @@
96E516FC20005A4400A02306 /* MGLUserLocationHeadingIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */; };
96E516FF20005A4F00A02306 /* MGLMapboxEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */; };
96E5170420005A6B00A02306 /* SMCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848891CBB037E00AB86E3 /* SMCalloutView.h */; };
+ 96ED34DE22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96ED34DD22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm */; };
96F3F73C1F57124B003E2D2C /* MGLUserLocationHeadingIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */; };
AC1B0916221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = AC1B0914221CA14500DB56C8 /* CLLocationManager+MMEMobileEvents.h */; };
AC1B0917221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = AC1B0914221CA14500DB56C8 /* CLLocationManager+MMEMobileEvents.h */; };
@@ -1141,6 +1142,7 @@
96E0272C1E57C7E5004B8E66 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
96E0272D1E57C7E6004B8E66 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
96E0272E1E57C7E7004B8E66 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ 96ED34DD22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLMapViewDirectionTests.mm; sourceTree = "<group>"; };
96F017292118FBAE00892778 /* MGLMapView_Experimental.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Experimental.h; sourceTree = "<group>"; };
96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = "<group>"; };
AC1B0914221CA14500DB56C8 /* CLLocationManager+MMEMobileEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CLLocationManager+MMEMobileEvents.h"; path = "../vendor/mapbox-events-ios/MapboxMobileEvents/CLLocationManager+MMEMobileEvents.h"; sourceTree = "<group>"; };
@@ -2025,6 +2027,7 @@
DA5DB1291FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m */,
DA695425215B1E75002041A4 /* MGLMapCameraTests.m */,
076171C22139C70900668A35 /* MGLMapViewTests.m */,
+ 96ED34DD22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm */,
16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */,
9658C154204761FC00D8A674 /* MGLMapViewScaleBarTests.m */,
35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */,
@@ -3152,6 +3155,7 @@
07D8C6FF1F67562C00381808 /* MGLComputedShapeSourceTests.m in Sources */,
920A3E5D1E6F995200C16EFC /* MGLSourceQueryTests.m in Sources */,
DA5DB12A1FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m in Sources */,
+ 96ED34DE22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm in Sources */,
FAE1CDCB1E9D79CB00C40B5B /* MGLFillExtrusionStyleLayerTests.mm in Sources */,
DA35A2AA1CCA058D00E826B2 /* MGLCoordinateFormatterTests.m in Sources */,
357579831D502AE6000B822E /* MGLRasterStyleLayerTests.mm in Sources */,
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index f19f1c8661..c45f436c33 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -3431,7 +3431,7 @@ public:
- (CLLocationDirection)direction
{
- return *self.mbglMap.getCameraOptions().bearing;
+ return mbgl::util::wrap(*self.mbglMap.getCameraOptions().bearing, 0., 360.);
}
- (void)setDirection:(CLLocationDirection)direction animated:(BOOL)animated
diff --git a/platform/ios/test/MGLMapViewDirectionTests.mm b/platform/ios/test/MGLMapViewDirectionTests.mm
new file mode 100644
index 0000000000..839e2741d4
--- /dev/null
+++ b/platform/ios/test/MGLMapViewDirectionTests.mm
@@ -0,0 +1,85 @@
+#import <Mapbox/Mapbox.h>
+#import <XCTest/XCTest.h>
+
+#import <mbgl/math/wrap.hpp>
+
+static MGLMapView *mapView;
+
+@interface MGLMapView (MGLMapViewDirectionTests)
+- (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate;
+- (void)resetNorthAnimated:(BOOL)animated;
+@end
+
+@interface UIRotationGestureRecognizer (MGLMapViewDirectionTests)
+@property (nonatomic, readwrite) UIGestureRecognizerState state;
+@end
+
+@interface MGLMapViewDirectionTests : XCTestCase
+@end
+
+@implementation MGLMapViewDirectionTests
+
+- (void)setUp {
+ [super setUp];
+
+ [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 64, 64) styleURL:styleURL];
+}
+
+- (void)tearDown {
+ mapView = nil;
+ [MGLAccountManager setAccessToken:nil];
+ [super tearDown];
+}
+
+- (void)testDirectionAndRotation {
+ mapView.zoomLevel = 0;
+ mapView.direction = 30;
+ XCTAssertEqual(mapView.direction, 0, @"Rotation is not allowed at world-scale zoom levels.");
+
+ mapView.zoomLevel = 15;
+
+ mapView.direction = 5;
+ XCTAssertEqual(mapView.direction, 5);
+
+ mapView.direction = -180;
+ XCTAssertEqual(mapView.direction, 180, @"Negative (invalid) direction should be wrapped.");
+
+ mapView.direction = 366;
+ XCTAssertEqualWithAccuracy(mapView.direction, 6, 0.001, @">360° direction should be wrapped.");
+
+ [mapView resetNorthAnimated:NO];
+ XCTAssertEqual(mapView.direction, 0, @"Reset-to-north should set direction to 0°.");
+
+ UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc] initWithTarget:nil action:nil];
+ rotate.state = UIGestureRecognizerStateBegan;
+ rotate.rotation = 0;
+ [mapView handleRotateGesture:rotate];
+ XCTAssertEqual(mapView.direction, rotate.rotation);
+
+ rotate.state = UIGestureRecognizerStateChanged;
+ rotate.rotation = 0.4;
+ [mapView handleRotateGesture:rotate];
+ XCTAssertEqual(mapView.direction, mbgl::util::wrap(-MGLDegreesFromRadians(rotate.rotation), 0., 360.), @"Map direction should match gesture rotation.");
+}
+
+- (void)testCompassRotation {
+ mapView.zoomLevel = 15;
+
+ for (NSNumber *degrees in @[@-1, @0, @45, @90, @180, @240, @360, @999]) {
+ mapView.direction = [degrees doubleValue];
+ CGFloat wrappedDirection = mbgl::util::wrap(-mapView.direction, 0., 360.);
+ CGAffineTransform rotation = CGAffineTransformMakeRotation(MGLRadiansFromDegrees(wrappedDirection));
+ XCTAssertTrue(CGAffineTransformEqualToTransform(mapView.compassView.transform, rotation),
+ @"Compass transform %@ should equal wrapped transform %@.", NSStringFromCGAffineTransform(mapView.compassView.transform), NSStringFromCGAffineTransform(rotation));
+ }
+}
+
+- (void)testResetPosition {
+ [mapView resetPosition];
+ MGLMapCamera *defaultCamera = [MGLMapCamera cameraLookingAtCenterCoordinate:CLLocationCoordinate2DMake(0, 0) altitude:mapView.camera.altitude pitch:0 heading:0];
+ XCTAssertTrue([mapView.camera isEqualToMapCamera:defaultCamera], @"Map camera %@ should be equal to default camera %@.", mapView.camera, defaultCamera);
+}
+
+@end
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 045a0c9f98..fa207ec187 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -1132,7 +1132,7 @@ public:
}
- (CLLocationDirection)direction {
- return *_mbglMap->getCameraOptions().bearing;
+ return mbgl::util::wrap(*_mbglMap->getCameraOptions().bearing, 0., 360.);
}
- (void)setDirection:(CLLocationDirection)direction {