From bb85d9823884f2c03a06e43016b07d2d4dc0ace6 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Tue, 4 Apr 2017 12:25:20 -0400 Subject: [PATCH 01/15] [ios] MGLMultiPolygon's coordinate property implemented --- platform/darwin/src/MGLPolygon.mm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm index ceafe873bf5..bec29a56d3f 100644 --- a/platform/darwin/src/MGLPolygon.mm +++ b/platform/darwin/src/MGLPolygon.mm @@ -155,6 +155,13 @@ - (NSUInteger)hash { return hash; } +- (CLLocationCoordinate2D)coordinate { + NSAssert(self.polygons.count > 0, @"A multipolygon must have coordinates"); + + MGLPolygon *firstPolygon = [self.polygons firstObject]; + return firstPolygon.coordinate; +} + - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds); } From 0c5ccb58d136dd99c073afd26d6527f607a5369e Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Mon, 10 Apr 2017 09:55:54 -0400 Subject: [PATCH 02/15] [ios,macos] Add polylabalel to project config --- platform/ios/ios.xcodeproj/project.pbxproj | 30 +++++++++++++++++----- scripts/config.xcconfig.in | 1 + 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 27582c1acfb..ef57eac1406 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -2703,7 +2703,10 @@ baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = test/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -2727,7 +2730,10 @@ baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = test/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -2755,7 +2761,10 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = framework/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -2789,7 +2798,10 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = framework/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -2840,7 +2852,10 @@ baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */; buildSettings = { BITCODE_GENERATION_MODE = bitcode; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "$(sqlite_cflags)", @@ -2866,7 +2881,10 @@ baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */; buildSettings = { BITCODE_GENERATION_MODE = bitcode; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "$(sqlite_cflags)", diff --git a/scripts/config.xcconfig.in b/scripts/config.xcconfig.in index eb6bc71b890..b70ff9d6771 100644 --- a/scripts/config.xcconfig.in +++ b/scripts/config.xcconfig.in @@ -3,3 +3,4 @@ // mbgl-core mbgl_core_INCLUDE_DIRECTORIES = "@mbgl_core_INCLUDE_DIRECTORIES@" mbgl_core_LINK_LIBRARIES = "@mbgl_core_LINK_LIBRARIES@" +polylabel_INCLUDE_DIRECTORIES = "@MASON_PACKAGE_polylabel_INCLUDE_DIRS@" From 445ead937302709d14bc7690814d0d3837186bd6 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Tue, 11 Apr 2017 10:28:14 -0400 Subject: [PATCH 03/15] [ios,macos] Change coordinate property for MGLPolyline,MGLPolygon,MGLMultiPolygon --- platform/darwin/src/MGLPolygon.mm | 27 ++++++++++-- platform/darwin/src/MGLPolyline.mm | 32 ++++++++++++++ platform/darwin/test/MGLCodingTests.m | 63 +++++++++++++++++++++++++-- 3 files changed, 116 insertions(+), 6 deletions(-) diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm index bec29a56d3f..1aa6ca239db 100644 --- a/platform/darwin/src/MGLPolygon.mm +++ b/platform/darwin/src/MGLPolygon.mm @@ -6,6 +6,7 @@ #import "MGLPolygon+MGLAdditions.h" #import +#import @implementation MGLPolygon @@ -54,6 +55,17 @@ - (NSUInteger)hash { return [super hash] + [[self geoJSONDictionary] hash]; } +- (CLLocationCoordinate2D)coordinate { + CLLocationCoordinate2D centroid; + + // pole of inaccessibility + auto poi = mapbox::polylabel([self polygon]); + centroid.latitude = poi.y; + centroid.longitude = poi.x; + + return centroid; +} + - (mbgl::LinearRing)ring { NSUInteger count = self.pointCount; CLLocationCoordinate2D *coordinates = self.coordinates; @@ -156,10 +168,19 @@ - (NSUInteger)hash { } - (CLLocationCoordinate2D)coordinate { - NSAssert(self.polygons.count > 0, @"A multipolygon must have coordinates"); + CLLocationCoordinate2D centroid; + + mbgl::Polygon geometry; + for (MGLPolygon *polygon in self.polygons) { + geometry.push_back(polygon.ring); + } + + // pole of inaccessibility + auto poi = mapbox::polylabel(geometry); + centroid.latitude = poi.y; + centroid.longitude = poi.x; - MGLPolygon *firstPolygon = [self.polygons firstObject]; - return firstPolygon.coordinate; + return centroid; } - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index ae4fbe61de3..8e9eceabfef 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -6,6 +6,7 @@ #import "MGLPolyline+MGLAdditions.h" #import +#import @implementation MGLPolyline @@ -52,6 +53,20 @@ - (BOOL)isEqual:(id)other { return self == other || ([other isKindOfClass:[MGLPolyline class]] && [super isEqual:other]); } +- (CLLocationCoordinate2D)coordinate { + CLLocationCoordinate2D centroid; + + mbgl::Polygon multiLineString; + multiLineString.push_back([self lineString]); + + // pole of inaccessibility + auto poi = mapbox::polylabel(multiLineString); + centroid.latitude = poi.y; + centroid.longitude = poi.x; + + return centroid; +} + @end @interface MGLMultiPolyline () @@ -114,6 +129,23 @@ - (NSUInteger)hash { return hash; } +- (CLLocationCoordinate2D)coordinate { + CLLocationCoordinate2D centroid; + + mbgl::Polygon multiLineString; + multiLineString.reserve(self.polylines.count); + for (MGLPolyline *polyline in self.polylines) { + multiLineString.push_back([polyline lineString]); + } + + // pole of inaccessibility + auto poi = mapbox::polylabel(multiLineString); + centroid.latitude = poi.y; + centroid.longitude = poi.x; + + return centroid; +} + - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds); } diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m index ff0d674ad17..4ff7941979a 100644 --- a/platform/darwin/test/MGLCodingTests.m +++ b/platform/darwin/test/MGLCodingTests.m @@ -66,12 +66,27 @@ - (void)testPolyline { [unarchivedPolyline replaceCoordinatesInRange:NSMakeRange(0, 1) withCoordinates:otherCoordinates]; XCTAssertNotEqualObjects(polyline, unarchivedPolyline); + + CLLocationCoordinate2D lineCoordinates[] = { + CLLocationCoordinate2DMake(100.0, 0.0), + CLLocationCoordinate2DMake(101.0, 0.0), + }; + + NSUInteger lnc = sizeof(lineCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolyline *line = [MGLPolyline polylineWithCoordinates:lineCoordinates count:lnc]; + CLLocationCoordinate2D lineCenter = CLLocationCoordinate2DMake(100.0, 0.0); + + XCTAssert([line coordinate].latitude == lineCenter.latitude && + [line coordinate].longitude == lineCenter.longitude); + } - (void)testPolygon { CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0.664482398, 1.8865675), - CLLocationCoordinate2DMake(2.13224687, 3.9984632) + CLLocationCoordinate2DMake(35.090745, -85.300259), + CLLocationCoordinate2DMake(35.092035, -85.298885), + CLLocationCoordinate2DMake(35.090639, -85.297416), + CLLocationCoordinate2DMake(35.089112, -85.298928) }; NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); @@ -84,8 +99,24 @@ - (void)testPolygon { [NSKeyedArchiver archiveRootObject:polygon toFile:filePath]; MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + [unarchivedPolygon coordinate]; XCTAssertEqualObjects(polygon, unarchivedPolygon); + + CLLocationCoordinate2D squareCoordinates[] = { + CLLocationCoordinate2DMake(100.0, 0.0), + CLLocationCoordinate2DMake(101.0, 0.0), + CLLocationCoordinate2DMake(101.0, 1.0), + CLLocationCoordinate2DMake(100.0, 1.0), + }; + + NSUInteger snc = sizeof(squareCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolygon *squarePolygon = [MGLPolygon polygonWithCoordinates:squareCoordinates count:snc]; + CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5); + + XCTAssert([squarePolygon coordinate].latitude == squareCenter.latitude && + [squarePolygon coordinate].longitude == squareCenter.longitude); + } - (void)testPolygonWithInteriorPolygons { @@ -248,6 +279,31 @@ - (void)testMultiPolygon { CLLocationCoordinate2DMake(20, 21), CLLocationCoordinate2DMake(30, 31), }; + + CLLocationCoordinate2D outterSquare[] = { + CLLocationCoordinate2DMake(100.0, 0.0), + CLLocationCoordinate2DMake(101.0, 0.0), + CLLocationCoordinate2DMake(101.0, 1.0), + CLLocationCoordinate2DMake(100.0, 1.0), + }; + + CLLocationCoordinate2D innerSquare[] = { + CLLocationCoordinate2DMake(100.35, 0.35), + CLLocationCoordinate2DMake(100.65, 0.35), + CLLocationCoordinate2DMake(100.65, 0.65), + CLLocationCoordinate2DMake(100.35, 0.65), + }; + + NSUInteger noc = sizeof(outterSquare) / sizeof(CLLocationCoordinate2D); + NSUInteger nic = sizeof(innerSquare) / sizeof(CLLocationCoordinate2D); + + MGLPolygon *outterPolygonSquare = [MGLPolygon polygonWithCoordinates:outterSquare count:noc]; + MGLPolygon *innerPolygonSquare = [MGLPolygon polygonWithCoordinates:innerSquare count:nic]; + MGLMultiPolygon *squares = [MGLMultiPolygon multiPolygonWithPolygons:@[outterPolygonSquare, innerPolygonSquare]]; + CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5); + + XCTAssert([squares coordinate].latitude == squareCenter.latitude && + [squares coordinate].longitude == squareCenter.longitude); NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); @@ -265,9 +321,10 @@ - (void)testMultiPolygon { MGLMultiPolygon *unarchivedMultiPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; MGLMultiPolygon *anotherMultiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]]; - + XCTAssertEqualObjects(multiPolygon, unarchivedMultiPolygon); XCTAssertNotEqualObjects(anotherMultiPolygon, unarchivedMultiPolygon); + } - (void)testShapeCollection { From 36b876dcabcbf5d57935a1509361805c52c776a3 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Tue, 11 Apr 2017 11:04:23 -0400 Subject: [PATCH 04/15] [macos] Change project configuration to support polilabel --- .../macos/macos.xcodeproj/project.pbxproj | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index 11275240981..564d81afb2c 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -1779,7 +1779,10 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = "$(SRCROOT)/sdk/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; @@ -1813,7 +1816,10 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = "$(SRCROOT)/sdk/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; @@ -1837,7 +1843,10 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = test/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; LIBRARY_SEARCH_PATHS = ( @@ -1866,7 +1875,10 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)"; + HEADER_SEARCH_PATHS = ( + "$(mbgl_core_INCLUDE_DIRECTORIES)", + "$(polylabel_INCLUDE_DIRECTORIES)", + ); INFOPLIST_FILE = test/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; OTHER_CFLAGS = "-fvisibility=hidden"; From 8c606639177e9abc7247c0525e2a24147ebeec93 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Thu, 13 Apr 2017 17:14:16 -0400 Subject: [PATCH 05/15] [ios,macos] Add MGLLocationCoordinate2DFromPoint --- platform/darwin/src/MGLGeometry_Private.h | 4 ++ platform/darwin/src/MGLPolygon.mm | 25 +++------- platform/darwin/src/MGLPolyline.mm | 31 ++++-------- platform/darwin/test/MGLCodingTests.m | 61 +++++++++++++++++------ 4 files changed, 67 insertions(+), 54 deletions(-) diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h index 3e029e8ee05..2446ffcfe03 100644 --- a/platform/darwin/src/MGLGeometry_Private.h +++ b/platform/darwin/src/MGLGeometry_Private.h @@ -18,6 +18,10 @@ NS_INLINE mbgl::Point MGLPointFromLocationCoordinate2D(CLLocationCoordin return mbgl::Point(coordinate.longitude, coordinate.latitude); } +NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromPoint(mbgl::Point point) { + return CLLocationCoordinate2DMake(point.y, point.x); +} + NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) { return CLLocationCoordinate2DMake(latLng.latitude(), latLng.longitude()); } diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm index 1aa6ca239db..a61d4d78e0b 100644 --- a/platform/darwin/src/MGLPolygon.mm +++ b/platform/darwin/src/MGLPolygon.mm @@ -56,12 +56,9 @@ - (NSUInteger)hash { } - (CLLocationCoordinate2D)coordinate { - CLLocationCoordinate2D centroid; - // pole of inaccessibility auto poi = mapbox::polylabel([self polygon]); - centroid.latitude = poi.y; - centroid.longitude = poi.x; + CLLocationCoordinate2D centroid = MGLLocationCoordinate2DFromPoint(poi); return centroid; } @@ -168,26 +165,16 @@ - (NSUInteger)hash { } - (CLLocationCoordinate2D)coordinate { - CLLocationCoordinate2D centroid; + MGLPolygon *firstPolygon = self.polygons.firstObject; - mbgl::Polygon geometry; - for (MGLPolygon *polygon in self.polygons) { - geometry.push_back(polygon.ring); - } - - // pole of inaccessibility - auto poi = mapbox::polylabel(geometry); - centroid.latitude = poi.y; - centroid.longitude = poi.x; - - return centroid; + return firstPolygon.coordinate; } - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds); } -- (mbgl::Geometry)geometryObject { +- (mbgl::MultiPolygon)multiPolygon { mbgl::MultiPolygon multiPolygon; multiPolygon.reserve(self.polygons.count); for (MGLPolygon *polygon in self.polygons) { @@ -201,6 +188,10 @@ - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { return multiPolygon; } +- (mbgl::Geometry)geometryObject { + return [self multiPolygon]; +} + - (NSDictionary *)geoJSONDictionary { NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.polygons.count]; for (MGLPolygonFeature *feature in self.polygons) { diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index 8e9eceabfef..df4c83b2f58 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -54,15 +54,12 @@ - (BOOL)isEqual:(id)other { } - (CLLocationCoordinate2D)coordinate { - CLLocationCoordinate2D centroid; - - mbgl::Polygon multiLineString; - multiLineString.push_back([self lineString]); + mbgl::Polygon polyline; + polyline.push_back([self lineString]); // pole of inaccessibility - auto poi = mapbox::polylabel(multiLineString); - centroid.latitude = poi.y; - centroid.longitude = poi.x; + auto poi = mapbox::polylabel(polyline); + CLLocationCoordinate2D centroid = MGLLocationCoordinate2DFromPoint(poi); return centroid; } @@ -130,20 +127,12 @@ - (NSUInteger)hash { } - (CLLocationCoordinate2D)coordinate { - CLLocationCoordinate2D centroid; - - mbgl::Polygon multiLineString; - multiLineString.reserve(self.polylines.count); - for (MGLPolyline *polyline in self.polylines) { - multiLineString.push_back([polyline lineString]); - } - - // pole of inaccessibility - auto poi = mapbox::polylabel(multiLineString); - centroid.latitude = poi.y; - centroid.longitude = poi.x; - - return centroid; + MGLPolyline *polyline = self.polylines.firstObject; + CLLocationCoordinate2D *coordinates = polyline.coordinates; + NSAssert([polyline pointCount] > 0, @"Polyline must have coordinates"); + CLLocationCoordinate2D firstCoordinate = coordinates[0]; + + return firstCoordinate; } - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m index 4ff7941979a..10a0395826c 100644 --- a/platform/darwin/test/MGLCodingTests.m +++ b/platform/darwin/test/MGLCodingTests.m @@ -72,12 +72,12 @@ - (void)testPolyline { CLLocationCoordinate2DMake(101.0, 0.0), }; - NSUInteger lnc = sizeof(lineCoordinates) / sizeof(CLLocationCoordinate2D); - MGLPolyline *line = [MGLPolyline polylineWithCoordinates:lineCoordinates count:lnc]; + NSUInteger lineCoordinatesCount = sizeof(lineCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolyline *line = [MGLPolyline polylineWithCoordinates:lineCoordinates count:lineCoordinatesCount]; CLLocationCoordinate2D lineCenter = CLLocationCoordinate2DMake(100.0, 0.0); - XCTAssert([line coordinate].latitude == lineCenter.latitude && - [line coordinate].longitude == lineCenter.longitude); + XCTAssertEqual([line coordinate].latitude, lineCenter.latitude); + XCTAssertEqual([line coordinate].longitude, lineCenter.longitude); } @@ -110,12 +110,12 @@ - (void)testPolygon { CLLocationCoordinate2DMake(100.0, 1.0), }; - NSUInteger snc = sizeof(squareCoordinates) / sizeof(CLLocationCoordinate2D); - MGLPolygon *squarePolygon = [MGLPolygon polygonWithCoordinates:squareCoordinates count:snc]; + NSUInteger squareCoordinatesCount = sizeof(squareCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolygon *squarePolygon = [MGLPolygon polygonWithCoordinates:squareCoordinates count:squareCoordinatesCount]; CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5); - XCTAssert([squarePolygon coordinate].latitude == squareCenter.latitude && - [squarePolygon coordinate].longitude == squareCenter.longitude); + XCTAssertEqual([squarePolygon coordinate].latitude, squareCenter.latitude); + XCTAssertEqual([squarePolygon coordinate].longitude, squareCenter.longitude); } @@ -200,6 +200,11 @@ - (void)testPointCollection { NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); MGLPointCollection *pointCollection = [MGLPointCollection pointCollectionWithCoordinates:coordinates count:numberOfCoordinates]; + CLLocationCoordinate2D pointsCenter = CLLocationCoordinate2DMake(0, 1); + + XCTAssertEqual([pointCollection coordinate].latitude, pointsCenter.latitude); + XCTAssertEqual([pointCollection coordinate].longitude, pointsCenter.longitude); + NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollection class]]; [NSKeyedArchiver archiveRootObject:pointCollection toFile:filePath]; @@ -249,6 +254,30 @@ - (void)testMultiPolyline { CLLocationCoordinate2DMake(20, 21), CLLocationCoordinate2DMake(30, 31), }; + + CLLocationCoordinate2D line1[] = { + CLLocationCoordinate2DMake(100, 40), + CLLocationCoordinate2DMake(105, 45), + CLLocationCoordinate2DMake(110, 55) + }; + + CLLocationCoordinate2D line2[] = { + CLLocationCoordinate2DMake(105, 40), + CLLocationCoordinate2DMake(110, 45), + CLLocationCoordinate2DMake(115, 55) + }; + + NSUInteger road1CoordinatesCount = sizeof(line1) / sizeof(CLLocationCoordinate2D); + NSUInteger road2CoordinatesCount = sizeof(line2) / sizeof(CLLocationCoordinate2D); + + MGLPolyline *road1Polyline = [MGLPolyline polylineWithCoordinates:line1 count:road1CoordinatesCount]; + MGLPolyline *road2Polyline = [MGLPolyline polylineWithCoordinates:line1 count:road2CoordinatesCount]; + + MGLMultiPolyline *roads = [MGLMultiPolyline multiPolylineWithPolylines:@[road1Polyline, road2Polyline]]; + CLLocationCoordinate2D roadCenter = CLLocationCoordinate2DMake(100, 40); + + XCTAssertEqual([roads coordinate].latitude, roadCenter.latitude); + XCTAssertEqual([roads coordinate].longitude, roadCenter.longitude); NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); @@ -280,7 +309,7 @@ - (void)testMultiPolygon { CLLocationCoordinate2DMake(30, 31), }; - CLLocationCoordinate2D outterSquare[] = { + CLLocationCoordinate2D outerSquare[] = { CLLocationCoordinate2DMake(100.0, 0.0), CLLocationCoordinate2DMake(101.0, 0.0), CLLocationCoordinate2DMake(101.0, 1.0), @@ -294,16 +323,16 @@ - (void)testMultiPolygon { CLLocationCoordinate2DMake(100.35, 0.65), }; - NSUInteger noc = sizeof(outterSquare) / sizeof(CLLocationCoordinate2D); - NSUInteger nic = sizeof(innerSquare) / sizeof(CLLocationCoordinate2D); + NSUInteger outerCoordinatesCount = sizeof(outerSquare) / sizeof(CLLocationCoordinate2D); + NSUInteger innerCoordinatesCount = sizeof(innerSquare) / sizeof(CLLocationCoordinate2D); - MGLPolygon *outterPolygonSquare = [MGLPolygon polygonWithCoordinates:outterSquare count:noc]; - MGLPolygon *innerPolygonSquare = [MGLPolygon polygonWithCoordinates:innerSquare count:nic]; - MGLMultiPolygon *squares = [MGLMultiPolygon multiPolygonWithPolygons:@[outterPolygonSquare, innerPolygonSquare]]; + MGLPolygon *innerPolygonSquare = [MGLPolygon polygonWithCoordinates:innerSquare count:innerCoordinatesCount]; + MGLPolygon *outerPolygonSquare = [MGLPolygon polygonWithCoordinates:outerSquare count:outerCoordinatesCount interiorPolygons:@[innerPolygonSquare]]; + MGLMultiPolygon *squares = [MGLMultiPolygon multiPolygonWithPolygons:@[outerPolygonSquare, innerPolygonSquare]]; CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5); - XCTAssert([squares coordinate].latitude == squareCenter.latitude && - [squares coordinate].longitude == squareCenter.longitude); + XCTAssertEqual([squares coordinate].latitude, squareCenter.latitude); + XCTAssertEqual([squares coordinate].longitude, squareCenter.longitude); NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); From 1966b47af1d5f99b5190e4e669851d0c9d8475e5 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Thu, 13 Apr 2017 19:19:18 -0400 Subject: [PATCH 06/15] [ios, macos] Update changelogs --- platform/darwin/src/MGLPolyline.mm | 12 +++++++++++- platform/ios/CHANGELOG.md | 1 + platform/macos/CHANGELOG.md | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index df4c83b2f58..7de1f523870 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -55,7 +55,17 @@ - (BOOL)isEqual:(id)other { - (CLLocationCoordinate2D)coordinate { mbgl::Polygon polyline; - polyline.push_back([self lineString]); + + NSUInteger count = self.pointCount; + CLLocationCoordinate2D *coordinates = self.coordinates; + + mbgl::LinearRing geometry; + geometry.reserve(self.pointCount); + for (NSUInteger i = 0; i < count; i++) { + geometry.push_back(mbgl::Point(coordinates[i].longitude, coordinates[i].latitude)); + } + + polyline.push_back(geometry); // pole of inaccessibility auto poi = mapbox::polylabel(polyline); diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index ca9d22f2305..15e3c7a081e 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -32,6 +32,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ### Other changes * Xcode 8.0 or higher is now recommended for using this SDK. ([#8775](https://github.com/mapbox/mapbox-gl-native/pull/8775)) +* Fixed a crash when calling `MGLMultiPolygon.coordinate` [#8713](https://github.com/mapbox/mapbox-gl-native/pull/8713) * Updated MGLMapView’s logo view to display [the new Mapbox logo](https://www.mapbox.com/blog/new-mapbox-logo/). ([#8771](https://github.com/mapbox/mapbox-gl-native/pull/8771), [#8773](https://github.com/mapbox/mapbox-gl-native/pull/8773)) * Fixed a crash or console spew when MGLMapView is initialized with a frame smaller than 64 points wide by 64 points tall. ([#8562](https://github.com/mapbox/mapbox-gl-native/pull/8562)) * The error passed into `-[MGLMapViewDelegate mapViewDidFailLoadingMap:withError:]` now includes a more specific description and failure reason. ([#8418](https://github.com/mapbox/mapbox-gl-native/pull/8418)) diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index ba09002d142..a1515e9d7a0 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -17,6 +17,7 @@ ### Other changes * Xcode 8.0 or higher is now recommended for using this SDK. ([#8775](https://github.com/mapbox/mapbox-gl-native/pull/8775)) +* Fixed a crash when calling `MGLMultiPolygon.coordinate` [#8713](https://github.com/mapbox/mapbox-gl-native/pull/8713) * Updated MGLMapView’s logo view to display [the new Mapbox logo](https://www.mapbox.com/blog/new-mapbox-logo/). ([#8771](https://github.com/mapbox/mapbox-gl-native/pull/8771), [#8773](https://github.com/mapbox/mapbox-gl-native/pull/8773)) * Fixed an issue causing attribution button text to appear blue instead of black. ([#8701](https://github.com/mapbox/mapbox-gl-native/pull/8701)) * Fixed a crash or console spew when MGLMapView is initialized with a frame smaller than 64 points wide by 64 points tall. ([#8562](https://github.com/mapbox/mapbox-gl-native/pull/8562)) From e78db29f3454c162f47ecf3396973f3a24153c4c Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Thu, 4 May 2017 20:44:22 -0400 Subject: [PATCH 07/15] [ios, macos] remove unnecesary variables --- platform/darwin/src/MGLPolygon.mm | 3 +-- platform/darwin/src/MGLPolyline.mm | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm index a61d4d78e0b..d966ff13ce4 100644 --- a/platform/darwin/src/MGLPolygon.mm +++ b/platform/darwin/src/MGLPolygon.mm @@ -58,9 +58,8 @@ - (NSUInteger)hash { - (CLLocationCoordinate2D)coordinate { // pole of inaccessibility auto poi = mapbox::polylabel([self polygon]); - CLLocationCoordinate2D centroid = MGLLocationCoordinate2DFromPoint(poi); - return centroid; + return MGLLocationCoordinate2DFromPoint(poi); } - (mbgl::LinearRing)ring { diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index 7de1f523870..059493239ec 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -69,9 +69,8 @@ - (CLLocationCoordinate2D)coordinate { // pole of inaccessibility auto poi = mapbox::polylabel(polyline); - CLLocationCoordinate2D centroid = MGLLocationCoordinate2DFromPoint(poi); - return centroid; + return MGLLocationCoordinate2DFromPoint(poi); } @end From 7d3ee3e67c3563b7c5448eae2ac0984b1dcb9510 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Mon, 8 May 2017 21:05:30 -0400 Subject: [PATCH 08/15] [ios, macos] Add radians conversions --- platform/darwin/src/MGLGeometry.h | 65 ++++++++++++++++++++++++++++++ platform/darwin/src/MGLGeometry.mm | 2 + 2 files changed, 67 insertions(+) diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h index 9fcb9dd37cb..8ff90503482 100644 --- a/platform/darwin/src/MGLGeometry.h +++ b/platform/darwin/src/MGLGeometry.h @@ -6,6 +6,30 @@ NS_ASSUME_NONNULL_BEGIN + +typedef double MGLLocationRadians; +typedef double MGLRadianDistance; +typedef double MGLRadianDirection; + +extern double const MGLMetersPerRadian; + +/** Defines the coordinate by a `MGLRadianCoordinate2D`. */ +typedef struct MGLRadianCoordinate2D { + MGLLocationRadians latitude; + MGLLocationRadians longitude; +} MGLRadianCoordinate2D; + +/** + Creates a new `MGLRadianCoordinate2D` from the given latitudinal and longitudinal. + */ +NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinate2DMake(MGLLocationRadians latitude, MGLLocationRadians longitude) { + MGLRadianCoordinate2D radianCoordinate; + radianCoordinate.latitude = latitude; + radianCoordinate.longitude = longitude; + return radianCoordinate; +} + + /** Defines the area spanned by an `MGLCoordinateBounds`. */ typedef struct MGLCoordinateSpan { /** Latitudes spanned by an `MGLCoordinateBounds`. */ @@ -127,4 +151,45 @@ NS_INLINE CLLocationDegrees MGLDegreesFromRadians(CGFloat radians) { return radians * 180 / M_PI; } +/** Returns MGLRadianCoordinate2D, converted from CLLocationCoordinate2D. */ +NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateFromLocationCoordinate(CLLocationCoordinate2D locationCoordinate) { + return MGLRadianCoordinate2DMake(MGLRadiansFromDegrees(locationCoordinate.latitude), + MGLRadiansFromDegrees(locationCoordinate.longitude)); +} + +/* + Returns the distance in radians given two coordinates. + */ +NS_INLINE MGLRadianDistance MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) +{ + double a = pow(sin((to.latitude - from.latitude) / 2), 2) + + pow(sin((to.longitude - from.longitude) / 2), 2) * cos(from.latitude) * cos(to.latitude); + + return 2 * atan2(sqrt(a), sqrt(1 - a)); +} + +/* + Returns direction in radians given two coordinates. + */ +NS_INLINE MGLRadianDirection MGLRadianCoordinatesDirection(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) { + double a = sin(to.longitude - from.longitude) * cos(to.latitude); + double b = cos(from.latitude) * sin(to.latitude) + - sin(from.latitude) * cos(to.latitude) * cos(to.longitude - from.longitude); + return atan2(a, b); +} + +/* + Returns coordinate at a given distance and direction away from coordinate. + */ +NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGLRadianCoordinate2D coordinate, + MGLRadianDistance distance, + MGLRadianDirection direction) { + double otherLatitude = asin(sin(coordinate.latitude) * cos(distance) + + cos(coordinate.latitude) * sin(distance) * cos(direction)); + double otherLongitude = coordinate.longitude + atan2(sin(direction) * sin(distance) * cos(coordinate.latitude), + cos(distance) - sin(coordinate.latitude) * sin(otherLatitude)); + return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude); +} + + NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm index 1540a3a7419..edd282dfbf2 100644 --- a/platform/darwin/src/MGLGeometry.mm +++ b/platform/darwin/src/MGLGeometry.mm @@ -14,6 +14,8 @@ const MGLCoordinateSpan MGLCoordinateSpanZero = {0, 0}; +const double MGLMetersPerRadian = 6373000.0; + CGRect MGLExtendRect(CGRect rect, CGPoint point) { if (point.x < rect.origin.x) { rect.size.width += rect.origin.x - point.x; From 09f485a05946d3d0ad8a5d4b1ba647a0c80ba7ad Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Tue, 9 May 2017 17:54:10 -0400 Subject: [PATCH 09/15] [ios, macos] Add coordinate calc to MGLPolyline --- platform/darwin/src/MGLPolyline.mm | 59 ++++++++++++++++++++++----- platform/darwin/test/MGLCodingTests.m | 17 ++++---- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index 059493239ec..a6a36044db6 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -54,23 +54,62 @@ - (BOOL)isEqual:(id)other { } - (CLLocationCoordinate2D)coordinate { - mbgl::Polygon polyline; - NSUInteger count = self.pointCount; + NSAssert(count > 0, @"Polyline must have coordinates"); + CLLocationCoordinate2D *coordinates = self.coordinates; + double middle = [self polylineLongitud] / 2.0; + double traveled = 0.0; - mbgl::LinearRing geometry; - geometry.reserve(self.pointCount); - for (NSUInteger i = 0; i < count; i++) { - geometry.push_back(mbgl::Point(coordinates[i].longitude, coordinates[i].latitude)); + if (count > 1 || middle > traveled) { + for (NSUInteger i = 0; i < count; i++) { + + MGLRadianCoordinate2D from = MGLRadianCoordinateFromLocationCoordinate(coordinates[i]); + MGLRadianCoordinate2D to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1]); + + if (traveled >= middle) { + double overshoot = middle - traveled; + if (overshoot == 0) { + return coordinates[i]; + } + to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i - 1]); + MGLRadianDirection direction = [self direction:from to:to] - 180; + MGLRadianCoordinate2D otherCoordinate = MGLRadianCoordinateAtDistanceFacingDirection(from, + overshoot/MGLMetersPerRadian, + MGLRadiansFromDegrees(direction)); + return CLLocationCoordinate2DMake(MGLDegreesFromRadians(otherCoordinate.latitude), + MGLDegreesFromRadians(otherCoordinate.longitude)); + } + + traveled += (MGLDistanceBetweenRadianCoordinates(from, to) * 6373000.0); + + } } + + return coordinates[count - 1]; +} + +- (double)polylineLongitud +{ + double longitude = 0.0; - polyline.push_back(geometry); + NSUInteger count = self.pointCount; + CLLocationCoordinate2D *coordinates = self.coordinates; - // pole of inaccessibility - auto poi = mapbox::polylabel(polyline); + for (NSUInteger i = 0; i < count; i++) { + if (i + 1 >= count) { + return longitude; + } + + longitude += (MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinateFromLocationCoordinate(coordinates[i]), MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1])) * 6373000.0); + } - return MGLLocationCoordinate2DFromPoint(poi); + return longitude; +} + +- (CLLocationDirection)direction:(MGLRadianCoordinate2D)from to:(MGLRadianCoordinate2D)to +{ + return MGLDegreesFromRadians(MGLRadianCoordinatesDirection(from, to)); } @end diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m index 10a0395826c..006d764e772 100644 --- a/platform/darwin/test/MGLCodingTests.m +++ b/platform/darwin/test/MGLCodingTests.m @@ -67,17 +67,18 @@ - (void)testPolyline { XCTAssertNotEqualObjects(polyline, unarchivedPolyline); - CLLocationCoordinate2D lineCoordinates[] = { - CLLocationCoordinate2DMake(100.0, 0.0), - CLLocationCoordinate2DMake(101.0, 0.0), + CLLocationCoordinate2D multiLineCoordinates[] = { + CLLocationCoordinate2DMake(51.000000, 0.000000), + CLLocationCoordinate2DMake(51.000000, 1.000000), + CLLocationCoordinate2DMake(51.000000, 2.000000), }; - NSUInteger lineCoordinatesCount = sizeof(lineCoordinates) / sizeof(CLLocationCoordinate2D); - MGLPolyline *line = [MGLPolyline polylineWithCoordinates:lineCoordinates count:lineCoordinatesCount]; - CLLocationCoordinate2D lineCenter = CLLocationCoordinate2DMake(100.0, 0.0); + NSUInteger multiLineCoordinatesCount = sizeof(multiLineCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolyline *multiLine = [MGLPolyline polylineWithCoordinates:multiLineCoordinates count:multiLineCoordinatesCount]; + CLLocationCoordinate2D multiLineCenter = CLLocationCoordinate2DMake(51.000000, 1.000000); - XCTAssertEqual([line coordinate].latitude, lineCenter.latitude); - XCTAssertEqual([line coordinate].longitude, lineCenter.longitude); + XCTAssertEqual([multiLine coordinate].latitude, multiLineCenter.latitude); + XCTAssertEqual([multiLine coordinate].longitude, multiLineCenter.longitude); } From 79c6d14e0547c26de37fc34d18eef343487f3b6f Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Thu, 11 May 2017 11:40:38 -0400 Subject: [PATCH 10/15] [ios, macos] Move radian fuctions to MGLGeometry_Private.h --- platform/darwin/src/MGLGeometry.h | 65 ----------------------- platform/darwin/src/MGLGeometry_Private.h | 62 +++++++++++++++++++++ 2 files changed, 62 insertions(+), 65 deletions(-) diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h index 8ff90503482..9fcb9dd37cb 100644 --- a/platform/darwin/src/MGLGeometry.h +++ b/platform/darwin/src/MGLGeometry.h @@ -6,30 +6,6 @@ NS_ASSUME_NONNULL_BEGIN - -typedef double MGLLocationRadians; -typedef double MGLRadianDistance; -typedef double MGLRadianDirection; - -extern double const MGLMetersPerRadian; - -/** Defines the coordinate by a `MGLRadianCoordinate2D`. */ -typedef struct MGLRadianCoordinate2D { - MGLLocationRadians latitude; - MGLLocationRadians longitude; -} MGLRadianCoordinate2D; - -/** - Creates a new `MGLRadianCoordinate2D` from the given latitudinal and longitudinal. - */ -NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinate2DMake(MGLLocationRadians latitude, MGLLocationRadians longitude) { - MGLRadianCoordinate2D radianCoordinate; - radianCoordinate.latitude = latitude; - radianCoordinate.longitude = longitude; - return radianCoordinate; -} - - /** Defines the area spanned by an `MGLCoordinateBounds`. */ typedef struct MGLCoordinateSpan { /** Latitudes spanned by an `MGLCoordinateBounds`. */ @@ -151,45 +127,4 @@ NS_INLINE CLLocationDegrees MGLDegreesFromRadians(CGFloat radians) { return radians * 180 / M_PI; } -/** Returns MGLRadianCoordinate2D, converted from CLLocationCoordinate2D. */ -NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateFromLocationCoordinate(CLLocationCoordinate2D locationCoordinate) { - return MGLRadianCoordinate2DMake(MGLRadiansFromDegrees(locationCoordinate.latitude), - MGLRadiansFromDegrees(locationCoordinate.longitude)); -} - -/* - Returns the distance in radians given two coordinates. - */ -NS_INLINE MGLRadianDistance MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) -{ - double a = pow(sin((to.latitude - from.latitude) / 2), 2) - + pow(sin((to.longitude - from.longitude) / 2), 2) * cos(from.latitude) * cos(to.latitude); - - return 2 * atan2(sqrt(a), sqrt(1 - a)); -} - -/* - Returns direction in radians given two coordinates. - */ -NS_INLINE MGLRadianDirection MGLRadianCoordinatesDirection(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) { - double a = sin(to.longitude - from.longitude) * cos(to.latitude); - double b = cos(from.latitude) * sin(to.latitude) - - sin(from.latitude) * cos(to.latitude) * cos(to.longitude - from.longitude); - return atan2(a, b); -} - -/* - Returns coordinate at a given distance and direction away from coordinate. - */ -NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGLRadianCoordinate2D coordinate, - MGLRadianDistance distance, - MGLRadianDirection direction) { - double otherLatitude = asin(sin(coordinate.latitude) * cos(distance) - + cos(coordinate.latitude) * sin(distance) * cos(direction)); - double otherLongitude = coordinate.longitude + atan2(sin(direction) * sin(distance) * cos(coordinate.latitude), - cos(distance) - sin(coordinate.latitude) * sin(otherLatitude)); - return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude); -} - - NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h index 2446ffcfe03..2b7761ea450 100644 --- a/platform/darwin/src/MGLGeometry_Private.h +++ b/platform/darwin/src/MGLGeometry_Private.h @@ -8,6 +8,28 @@ #import #import +typedef double MGLLocationRadians; +typedef double MGLRadianDistance; +typedef double MGLRadianDirection; + +extern double const MGLMetersPerRadian; + +/** Defines the coordinate by a `MGLRadianCoordinate2D`. */ +typedef struct MGLRadianCoordinate2D { + MGLLocationRadians latitude; + MGLLocationRadians longitude; +} MGLRadianCoordinate2D; + +/** + Creates a new `MGLRadianCoordinate2D` from the given latitudinal and longitudinal. + */ +NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinate2DMake(MGLLocationRadians latitude, MGLLocationRadians longitude) { + MGLRadianCoordinate2D radianCoordinate; + radianCoordinate.latitude = latitude; + radianCoordinate.longitude = longitude; + return radianCoordinate; +} + /// Returns the smallest rectangle that contains both the given rectangle and /// the given point. CGRect MGLExtendRect(CGRect rect, CGPoint point); @@ -63,3 +85,43 @@ CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLo @param size The size of the viewport. @return A zero-based zoom level. */ double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLocationDegrees latitude, CGSize size); + +/** Returns MGLRadianCoordinate2D, converted from CLLocationCoordinate2D. */ +NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateFromLocationCoordinate(CLLocationCoordinate2D locationCoordinate) { + return MGLRadianCoordinate2DMake(MGLRadiansFromDegrees(locationCoordinate.latitude), + MGLRadiansFromDegrees(locationCoordinate.longitude)); +} + +/* + Returns the distance in radians given two coordinates. + */ +NS_INLINE MGLRadianDistance MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) +{ + double a = pow(sin((to.latitude - from.latitude) / 2), 2) + + pow(sin((to.longitude - from.longitude) / 2), 2) * cos(from.latitude) * cos(to.latitude); + + return 2 * atan2(sqrt(a), sqrt(1 - a)); +} + +/* + Returns direction in radians given two coordinates. + */ +NS_INLINE MGLRadianDirection MGLRadianCoordinatesDirection(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) { + double a = sin(to.longitude - from.longitude) * cos(to.latitude); + double b = cos(from.latitude) * sin(to.latitude) + - sin(from.latitude) * cos(to.latitude) * cos(to.longitude - from.longitude); + return atan2(a, b); +} + +/* + Returns coordinate at a given distance and direction away from coordinate. + */ +NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGLRadianCoordinate2D coordinate, + MGLRadianDistance distance, + MGLRadianDirection direction) { + double otherLatitude = asin(sin(coordinate.latitude) * cos(distance) + + cos(coordinate.latitude) * sin(distance) * cos(direction)); + double otherLongitude = coordinate.longitude + atan2(sin(direction) * sin(distance) * cos(coordinate.latitude), + cos(distance) - sin(coordinate.latitude) * sin(otherLatitude)); + return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude); +} From 2a297b088d9a270ba17f6a7964dd6cac2bde43b2 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Thu, 11 May 2017 11:42:30 -0400 Subject: [PATCH 11/15] [ios, macos] Fix code style --- platform/darwin/src/MGLGeometry.mm | 2 -- platform/darwin/src/MGLGeometry_Private.h | 2 -- platform/darwin/src/MGLPolyline.mm | 24 ++++++++++------------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm index edd282dfbf2..1540a3a7419 100644 --- a/platform/darwin/src/MGLGeometry.mm +++ b/platform/darwin/src/MGLGeometry.mm @@ -14,8 +14,6 @@ const MGLCoordinateSpan MGLCoordinateSpanZero = {0, 0}; -const double MGLMetersPerRadian = 6373000.0; - CGRect MGLExtendRect(CGRect rect, CGPoint point) { if (point.x < rect.origin.x) { rect.size.width += rect.origin.x - point.x; diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h index 2b7761ea450..220f15f411a 100644 --- a/platform/darwin/src/MGLGeometry_Private.h +++ b/platform/darwin/src/MGLGeometry_Private.h @@ -12,8 +12,6 @@ typedef double MGLLocationRadians; typedef double MGLRadianDistance; typedef double MGLRadianDirection; -extern double const MGLMetersPerRadian; - /** Defines the coordinate by a `MGLRadianCoordinate2D`. */ typedef struct MGLRadianCoordinate2D { MGLLocationRadians latitude; diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index a6a36044db6..8ef26efb392 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -58,8 +58,8 @@ - (CLLocationCoordinate2D)coordinate { NSAssert(count > 0, @"Polyline must have coordinates"); CLLocationCoordinate2D *coordinates = self.coordinates; - double middle = [self polylineLongitud] / 2.0; - double traveled = 0.0; + CLLocationDistance middle = [self length] / 2.0; + CLLocationDistance traveled = 0.0; if (count > 1 || middle > traveled) { for (NSUInteger i = 0; i < count; i++) { @@ -73,15 +73,15 @@ - (CLLocationCoordinate2D)coordinate { return coordinates[i]; } to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i - 1]); - MGLRadianDirection direction = [self direction:from to:to] - 180; + CLLocationDirection direction = [self direction:from to:to] - 180; MGLRadianCoordinate2D otherCoordinate = MGLRadianCoordinateAtDistanceFacingDirection(from, - overshoot/MGLMetersPerRadian, + overshoot/mbgl::util::M2PI * mbgl::util::EARTH_RADIUS_M, MGLRadiansFromDegrees(direction)); return CLLocationCoordinate2DMake(MGLDegreesFromRadians(otherCoordinate.latitude), MGLDegreesFromRadians(otherCoordinate.longitude)); } - traveled += (MGLDistanceBetweenRadianCoordinates(from, to) * 6373000.0); + traveled += (MGLDistanceBetweenRadianCoordinates(from, to) * mbgl::util::EARTH_RADIUS_M); } } @@ -89,22 +89,18 @@ - (CLLocationCoordinate2D)coordinate { return coordinates[count - 1]; } -- (double)polylineLongitud +- (CLLocationDistance)length { - double longitude = 0.0; + CLLocationDistance length = 0.0; NSUInteger count = self.pointCount; CLLocationCoordinate2D *coordinates = self.coordinates; - for (NSUInteger i = 0; i < count; i++) { - if (i + 1 >= count) { - return longitude; - } - - longitude += (MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinateFromLocationCoordinate(coordinates[i]), MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1])) * 6373000.0); + for (NSUInteger i = 0; i < count - 1; i++) { + length += (MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinateFromLocationCoordinate(coordinates[i]), MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1])) * mbgl::util::EARTH_RADIUS_M); } - return longitude; + return length; } - (CLLocationDirection)direction:(MGLRadianCoordinate2D)from to:(MGLRadianCoordinate2D)to From 9b5ee6f317e43747fb1ce13fa3dcfcacca8bca64 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Thu, 11 May 2017 17:06:00 -0400 Subject: [PATCH 12/15] [ios, macos] Fix code indentation --- platform/darwin/src/MGLGeometry_Private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h index 220f15f411a..7ad8314a792 100644 --- a/platform/darwin/src/MGLGeometry_Private.h +++ b/platform/darwin/src/MGLGeometry_Private.h @@ -96,7 +96,7 @@ NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateFromLocationCoordinate(CLLoca NS_INLINE MGLRadianDistance MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) { double a = pow(sin((to.latitude - from.latitude) / 2), 2) - + pow(sin((to.longitude - from.longitude) / 2), 2) * cos(from.latitude) * cos(to.latitude); + + pow(sin((to.longitude - from.longitude) / 2), 2) * cos(from.latitude) * cos(to.latitude); return 2 * atan2(sqrt(a), sqrt(1 - a)); } @@ -107,7 +107,7 @@ NS_INLINE MGLRadianDistance MGLDistanceBetweenRadianCoordinates(MGLRadianCoordin NS_INLINE MGLRadianDirection MGLRadianCoordinatesDirection(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) { double a = sin(to.longitude - from.longitude) * cos(to.latitude); double b = cos(from.latitude) * sin(to.latitude) - - sin(from.latitude) * cos(to.latitude) * cos(to.longitude - from.longitude); + - sin(from.latitude) * cos(to.latitude) * cos(to.longitude - from.longitude); return atan2(a, b); } From 6114170840de8648b65a442c460ff4cf194c31d8 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Thu, 11 May 2017 17:07:04 -0400 Subject: [PATCH 13/15] [ios, macos] Fix radian per meters constant --- platform/darwin/src/MGLPolyline.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index 8ef26efb392..fd75dc27950 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -75,7 +75,7 @@ - (CLLocationCoordinate2D)coordinate { to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i - 1]); CLLocationDirection direction = [self direction:from to:to] - 180; MGLRadianCoordinate2D otherCoordinate = MGLRadianCoordinateAtDistanceFacingDirection(from, - overshoot/mbgl::util::M2PI * mbgl::util::EARTH_RADIUS_M, + overshoot/mbgl::util::EARTH_RADIUS_M, MGLRadiansFromDegrees(direction)); return CLLocationCoordinate2DMake(MGLDegreesFromRadians(otherCoordinate.latitude), MGLDegreesFromRadians(otherCoordinate.longitude)); From 7753572cd4e1ee0f41026fb6eb7544d3d4fa9ec5 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Fri, 12 May 2017 12:54:23 -0400 Subject: [PATCH 14/15] [ios, macos] Add test scenarios to testPolyline --- platform/darwin/test/MGLCodingTests.m | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m index 006d764e772..7c3a67467c9 100644 --- a/platform/darwin/test/MGLCodingTests.m +++ b/platform/darwin/test/MGLCodingTests.m @@ -80,6 +80,32 @@ - (void)testPolyline { XCTAssertEqual([multiLine coordinate].latitude, multiLineCenter.latitude); XCTAssertEqual([multiLine coordinate].longitude, multiLineCenter.longitude); + CLLocationCoordinate2D segmentCoordinates[] = { + CLLocationCoordinate2DMake(35.040390, -85.311477), + CLLocationCoordinate2DMake(35.040390, -85.209510), + }; + + NSUInteger segmentCoordinatesCount = sizeof(segmentCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolyline *segmentLine = [MGLPolyline polylineWithCoordinates:segmentCoordinates count:segmentCoordinatesCount]; + CLLocationCoordinate2D segmentCenter = CLLocationCoordinate2DMake(35.0404006631, -85.2604935); + + XCTAssertEqualWithAccuracy([segmentLine coordinate].latitude, segmentCenter.latitude, 1); + XCTAssertEqualWithAccuracy([segmentLine coordinate].longitude, segmentCenter.longitude, 1); + + CLLocationCoordinate2D sfToBerkeleyCoordinates[] = { + CLLocationCoordinate2DMake(37.782440, -122.397111), + CLLocationCoordinate2DMake(37.818384, -122.352994), + CLLocationCoordinate2DMake(37.831401, -122.274545), + CLLocationCoordinate2DMake(37.862172, -122.262700), + }; + + NSUInteger sfToBerkeleyCoordinatesCount = sizeof(sfToBerkeleyCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolyline *sfToBerkeleyLine = [MGLPolyline polylineWithCoordinates:sfToBerkeleyCoordinates count:sfToBerkeleyCoordinatesCount]; + CLLocationCoordinate2D sfToBerkeleyCenter = CLLocationCoordinate2DMake(37.8230575118,-122.324867587); + + XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].latitude, sfToBerkeleyCenter.latitude, 1); + XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].longitude, sfToBerkeleyCenter.longitude, 1); + } - (void)testPolygon { From cc57a437fc2e19d8b3c101bb8ca2e4211aeb7510 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Mon, 22 May 2017 12:12:28 -0400 Subject: [PATCH 15/15] [ios, macos] Fix test accuracy --- platform/darwin/test/MGLCodingTests.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m index 7c3a67467c9..ac61672b760 100644 --- a/platform/darwin/test/MGLCodingTests.m +++ b/platform/darwin/test/MGLCodingTests.m @@ -89,8 +89,8 @@ - (void)testPolyline { MGLPolyline *segmentLine = [MGLPolyline polylineWithCoordinates:segmentCoordinates count:segmentCoordinatesCount]; CLLocationCoordinate2D segmentCenter = CLLocationCoordinate2DMake(35.0404006631, -85.2604935); - XCTAssertEqualWithAccuracy([segmentLine coordinate].latitude, segmentCenter.latitude, 1); - XCTAssertEqualWithAccuracy([segmentLine coordinate].longitude, segmentCenter.longitude, 1); + XCTAssertEqualWithAccuracy([segmentLine coordinate].latitude, segmentCenter.latitude, 0.0001); + XCTAssertEqualWithAccuracy([segmentLine coordinate].longitude, segmentCenter.longitude, 0.0001); CLLocationCoordinate2D sfToBerkeleyCoordinates[] = { CLLocationCoordinate2DMake(37.782440, -122.397111), @@ -103,8 +103,8 @@ - (void)testPolyline { MGLPolyline *sfToBerkeleyLine = [MGLPolyline polylineWithCoordinates:sfToBerkeleyCoordinates count:sfToBerkeleyCoordinatesCount]; CLLocationCoordinate2D sfToBerkeleyCenter = CLLocationCoordinate2DMake(37.8230575118,-122.324867587); - XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].latitude, sfToBerkeleyCenter.latitude, 1); - XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].longitude, sfToBerkeleyCenter.longitude, 1); + XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].latitude, sfToBerkeleyCenter.latitude, 0.0001); + XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].longitude, sfToBerkeleyCenter.longitude, 0.0001); }