diff options
author | Jason Wray <friedbunny@users.noreply.github.com> | 2019-03-12 14:49:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-12 14:49:49 -0700 |
commit | fb1b6010383f9991c2e95b25bf96e17ff44961d9 (patch) | |
tree | fa1c234c44bcc279d4cd96277da548cb36f5b9fb /platform | |
parent | 103f86c4bca08c34c592edd481f078b7bf77cb3f (diff) | |
download | qtlocation-mapboxgl-fb1b6010383f9991c2e95b25bf96e17ff44961d9.tar.gz |
[darwin] Fix MGLMapView.direction wrapping
Re-adds the 0-to-360° wrapping for MGLMapView.direction. Without this wrapping, we’d get ±180° from core, which results in invalid CLLocationDirection for the negative half of the rotational spectrum.
Diffstat (limited to 'platform')
-rw-r--r-- | platform/darwin/test/MGLMapViewTests.m | 23 | ||||
-rw-r--r-- | platform/ios/ios.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 2 | ||||
-rw-r--r-- | platform/ios/test/MGLMapViewDirectionTests.mm | 95 | ||||
-rw-r--r-- | platform/macos/src/MGLMapView.mm | 2 |
5 files changed, 113 insertions, 13 deletions
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..7f7e0903e3 --- /dev/null +++ b/platform/ios/test/MGLMapViewDirectionTests.mm @@ -0,0 +1,95 @@ +#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)testDirection { + mapView.zoomLevel = 0; + mapView.direction = 30; + XCTAssertEqual(mapView.direction, 0, @"Rotation is not allowed at world-scale zoom levels."); + + mapView.zoomLevel = 15; + + for (NSNumber *degrees in @[@-999, @-359, @-240, @-180, @-90, @-45, @0, @45, @90, @180, @240, @360, @999]) { + double inputDegrees = [degrees doubleValue]; + double wrappedDegrees = mbgl::util::wrap(inputDegrees, 0., 360.); + mapView.direction = inputDegrees; + XCTAssertEqualWithAccuracy(mapView.direction, wrappedDegrees, 0.001); + } + + [mapView resetNorthAnimated:NO]; + XCTAssertEqual(mapView.direction, 0, @"Reset-to-north should set direction to 0°."); +} + +- (void)testRotateGesture { + mapView.zoomLevel = 15; + + UIRotationGestureRecognizer *gesture = [[UIRotationGestureRecognizer alloc] initWithTarget:nil action:nil]; + gesture.state = UIGestureRecognizerStateBegan; + gesture.rotation = 0; + [mapView handleRotateGesture:gesture]; + XCTAssertEqual(mapView.direction, gesture.rotation); + + for (NSNumber *degrees in @[@-999, @-360, @-240, @-180, @-90, @-45, @0, @45, @90, @180, @240, @359, @999]) { + gesture.state = UIGestureRecognizerStateChanged; + gesture.rotation = MGLRadiansFromDegrees([degrees doubleValue]); + [mapView handleRotateGesture:gesture]; + CGFloat wrappedRotation = mbgl::util::wrap(-MGLDegreesFromRadians(gesture.rotation), 0., 360.); + XCTAssertEqualWithAccuracy(mapView.direction, wrappedRotation, 0.001, @"Map direction should match gesture rotation for input of %@°.", degrees); + } +} + +- (void)testCompassRotation { + mapView.zoomLevel = 15; + + for (NSNumber *degrees in @[@-999, @-359, @-240, @-180, @-90, @-45, @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 direction %f° should equal wrapped transform direction %f° (~%.f°).", [self degreesFromAffineTransform:mapView.compassView.transform], [self degreesFromAffineTransform:rotation], wrappedDirection); + } +} + +- (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); +} + +- (CGFloat)degreesFromAffineTransform:(CGAffineTransform)transform { + CGFloat angle = atan2f(transform.b, transform.a); + return MGLDegreesFromRadians(angle); +} + +@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 { |