From dba896ce2ded8df7c8fc4f66aa7bd7dd8f8c4aa0 Mon Sep 17 00:00:00 2001 From: Julian Rex Date: Thu, 22 Nov 2018 00:55:02 -0500 Subject: Compile fixes following rebase --- include/mbgl/style/sources/geojson_source.hpp | 4 +- platform/darwin/src/MGLCluster.m | 131 ------ platform/darwin/src/MGLCluster.mm | 132 ++++++ platform/darwin/src/MGLFoundation_Private.h | 6 + platform/darwin/src/MGLShapeSource.mm | 3 +- platform/darwin/test/MGLCodingTests.m | 624 ------------------------ platform/darwin/test/MGLCodingTests.mm | 625 +++++++++++++++++++++++++ platform/darwin/test/MGLFeatureTests.mm | 1 + platform/ios/ios.xcodeproj/project.pbxproj | 20 +- src/mbgl/style/sources/geojson_source.cpp | 4 +- src/mbgl/style/sources/geojson_source_impl.cpp | 8 +- src/mbgl/style/sources/geojson_source_impl.hpp | 4 +- 12 files changed, 786 insertions(+), 776 deletions(-) delete mode 100644 platform/darwin/src/MGLCluster.m create mode 100644 platform/darwin/src/MGLCluster.mm delete mode 100644 platform/darwin/test/MGLCodingTests.m create mode 100644 platform/darwin/test/MGLCodingTests.mm diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp index 36cc9bb4bb..a2c3c8f7d7 100644 --- a/include/mbgl/style/sources/geojson_source.hpp +++ b/include/mbgl/style/sources/geojson_source.hpp @@ -35,8 +35,8 @@ public: void setGeoJSON(const GeoJSON&); optional getURL() const; - mapbox::geometry::feature_collection getChildren(const std::uint32_t) const; - mapbox::geometry::feature_collection getLeaves(const std::uint32_t, const std::uint32_t, const std::uint32_t) const; + mapbox::feature::feature_collection getChildren(const std::uint32_t) const; + mapbox::feature::feature_collection getLeaves(const std::uint32_t, const std::uint32_t, const std::uint32_t) const; std::uint8_t getClusterExpansionZoom(std::uint32_t) const; class Impl; diff --git a/platform/darwin/src/MGLCluster.m b/platform/darwin/src/MGLCluster.m deleted file mode 100644 index 46c7420cd6..0000000000 --- a/platform/darwin/src/MGLCluster.m +++ /dev/null @@ -1,131 +0,0 @@ -#import "MGLCluster_Private.h" -#import "MGLFeature.h" -#import - -NSString * const MGLClusterBoolKey = @"cluster"; -NSString * const MGLClusterIdentifierKey = @"cluster_id"; -NSString * const MGLClusterCountKey = @"point_count"; -NSString * const MGLClusterCountAbbreviationKey = @"point_count_abbreviated"; - -const NSUInteger MGLClusterIdentifierInvalid = NSUIntegerMax; - -BOOL MGLFeatureHasClusterAttribute(id feature) { - NSNumber *isCluster = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterBoolKey], NSNumber); - return [isCluster boolValue]; -} - -NSString *MGLClusterSubclassNameForFeature(id feature) { - NSString *className = NSStringFromClass([feature class]); - NSString *subclassName = [className stringByAppendingString:@"_Cluster"]; - return subclassName; -} - -static NSUInteger MGLClusterIdentifierIMP(id self, SEL _cmd) { - - id feature = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(self, MGLFeature); - - NSNumber *clusterNumber = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterIdentifierKey], NSNumber); - NSAssert(clusterNumber, @"Clusters should have a cluster_id"); - - if (!clusterNumber) { - return MGLClusterIdentifierInvalid; - } - - NSUInteger identifier = [clusterNumber unsignedIntegerValue]; - NSAssert(identifier <= UINT32_MAX, @"Cluster identifiers are 32bit"); - - return identifier; -} - -static NSUInteger MGLClusterPointCountIMP(id self, SEL _cmd) { - id feature = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(self, MGLFeature); - - NSNumber *count = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterCountKey], NSNumber); - NSAssert(count, @"Clusters should have a point_count"); - - return [count unsignedIntegerValue]; -} - -static NSString *MGLClusterPointCountAbbreviationIMP(id self, SEL _cmd) { - id feature = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(self, MGLFeature); - - NSString *abbreviation = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterCountAbbreviationKey], NSString); - NSAssert(abbreviation, @"Clusters should have a point_count_abbreviated"); - - if (!abbreviation) { - return @"0"; - } - - return abbreviation; -} - -static IMP MGLFeatureClusterIMPFromSelector(SEL selector) { - if (selector == @selector(clusterIdentifier)) { - return (IMP)MGLClusterIdentifierIMP; - } - else if (selector == @selector(clusterPointCount)) { - return (IMP)MGLClusterPointCountIMP; - } - else if (selector == @selector(clusterPointCountAbbreviation)) { - return (IMP)MGLClusterPointCountAbbreviationIMP; - } - assert(0); - return NULL; -} - -id MGLConvertFeatureToClusterSubclass(id feature) { - - Protocol *clusterProtocol = @protocol(MGLCluster); - - if ([feature conformsToProtocol:clusterProtocol]) { - return (id)feature; - } - - if (!MGLFeatureHasClusterAttribute(feature)) { - return nil; - } - - Class currentClass = [feature class]; - - NSString *subclassName = MGLClusterSubclassNameForFeature(feature); - - // Does this new subclass already exist? - Class clusterSubclass = NSClassFromString(subclassName); - - if (!clusterSubclass) { - clusterSubclass = objc_allocateClassPair(currentClass, subclassName.UTF8String, 0); - - // Add protocol to this new subclass - class_addProtocol(clusterSubclass, clusterProtocol); - - // Install protocol methods - unsigned int count = 0; - struct objc_method_description *methodDescriptionList = protocol_copyMethodDescriptionList(clusterProtocol, YES, YES, &count); - - for (unsigned int index = 0; index < count; index++) { - struct objc_method_description desc = methodDescriptionList[index]; - - IMP imp = MGLFeatureClusterIMPFromSelector(desc.name); - - if (imp) { - class_addMethod(clusterSubclass, desc.name, imp, desc.types); - } - } - - free(methodDescriptionList); methodDescriptionList = NULL; - - objc_registerClassPair(clusterSubclass); - } - - // Now change the class of the feature - object_setClass(feature, clusterSubclass); - assert([feature conformsToProtocol:clusterProtocol]); - - id cluster = (id)feature; - - assert([cluster respondsToSelector:@selector(clusterIdentifier)]); - assert([cluster respondsToSelector:@selector(clusterPointCount)]); - assert([cluster respondsToSelector:@selector(clusterPointCountAbbreviation)]); - - return cluster; -} diff --git a/platform/darwin/src/MGLCluster.mm b/platform/darwin/src/MGLCluster.mm new file mode 100644 index 0000000000..5126c56af6 --- /dev/null +++ b/platform/darwin/src/MGLCluster.mm @@ -0,0 +1,132 @@ +#import "MGLFoundation_Private.h" +#import "MGLCluster_Private.h" +#import "MGLFeature.h" +#import + +NSString * const MGLClusterBoolKey = @"cluster"; +NSString * const MGLClusterIdentifierKey = @"cluster_id"; +NSString * const MGLClusterCountKey = @"point_count"; +NSString * const MGLClusterCountAbbreviationKey = @"point_count_abbreviated"; + +const NSUInteger MGLClusterIdentifierInvalid = NSUIntegerMax; + +BOOL MGLFeatureHasClusterAttribute(id feature) { + NSNumber *isCluster = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterBoolKey], NSNumber); + return [isCluster boolValue]; +} + +NSString *MGLClusterSubclassNameForFeature(id feature) { + NSString *className = NSStringFromClass([feature class]); + NSString *subclassName = [className stringByAppendingString:@"_Cluster"]; + return subclassName; +} + +static NSUInteger MGLClusterIdentifierIMP(id self, SEL _cmd) { + + id feature = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(self, MGLFeature); + + NSNumber *clusterNumber = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterIdentifierKey], NSNumber); + NSAssert(clusterNumber, @"Clusters should have a cluster_id"); + + if (!clusterNumber) { + return MGLClusterIdentifierInvalid; + } + + NSUInteger identifier = [clusterNumber unsignedIntegerValue]; + NSAssert(identifier <= UINT32_MAX, @"Cluster identifiers are 32bit"); + + return identifier; +} + +static NSUInteger MGLClusterPointCountIMP(id self, SEL _cmd) { + id feature = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(self, MGLFeature); + + NSNumber *count = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterCountKey], NSNumber); + NSAssert(count, @"Clusters should have a point_count"); + + return [count unsignedIntegerValue]; +} + +static NSString *MGLClusterPointCountAbbreviationIMP(id self, SEL _cmd) { + id feature = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(self, MGLFeature); + + NSString *abbreviation = MGL_OBJC_DYNAMIC_CAST([feature attributeForKey:MGLClusterCountAbbreviationKey], NSString); + NSAssert(abbreviation, @"Clusters should have a point_count_abbreviated"); + + if (!abbreviation) { + return @"0"; + } + + return abbreviation; +} + +static IMP MGLFeatureClusterIMPFromSelector(SEL selector) { + if (selector == @selector(clusterIdentifier)) { + return (IMP)MGLClusterIdentifierIMP; + } + else if (selector == @selector(clusterPointCount)) { + return (IMP)MGLClusterPointCountIMP; + } + else if (selector == @selector(clusterPointCountAbbreviation)) { + return (IMP)MGLClusterPointCountAbbreviationIMP; + } + assert(0); + return NULL; +} + +id MGLConvertFeatureToClusterSubclass(id feature) { + + Protocol *clusterProtocol = @protocol(MGLCluster); + + if ([feature conformsToProtocol:clusterProtocol]) { + return (id)feature; + } + + if (!MGLFeatureHasClusterAttribute(feature)) { + return nil; + } + + Class currentClass = [feature class]; + + NSString *subclassName = MGLClusterSubclassNameForFeature(feature); + + // Does this new subclass already exist? + Class clusterSubclass = NSClassFromString(subclassName); + + if (!clusterSubclass) { + clusterSubclass = objc_allocateClassPair(currentClass, subclassName.UTF8String, 0); + + // Add protocol to this new subclass + class_addProtocol(clusterSubclass, clusterProtocol); + + // Install protocol methods + unsigned int count = 0; + struct objc_method_description *methodDescriptionList = protocol_copyMethodDescriptionList(clusterProtocol, YES, YES, &count); + + for (unsigned int index = 0; index < count; index++) { + struct objc_method_description desc = methodDescriptionList[index]; + + IMP imp = MGLFeatureClusterIMPFromSelector(desc.name); + + if (imp) { + class_addMethod(clusterSubclass, desc.name, imp, desc.types); + } + } + + free(methodDescriptionList); methodDescriptionList = NULL; + + objc_registerClassPair(clusterSubclass); + } + + // Now change the class of the feature + object_setClass(feature, clusterSubclass); + assert([feature conformsToProtocol:clusterProtocol]); + + id cluster = (id)feature; + + assert([cluster respondsToSelector:@selector(clusterIdentifier)]); + assert([cluster respondsToSelector:@selector(clusterPointCount)]); + assert([cluster respondsToSelector:@selector(clusterPointCountAbbreviation)]); + + return cluster; +} diff --git a/platform/darwin/src/MGLFoundation_Private.h b/platform/darwin/src/MGLFoundation_Private.h index 71737c2cf9..db81bde3de 100644 --- a/platform/darwin/src/MGLFoundation_Private.h +++ b/platform/darwin/src/MGLFoundation_Private.h @@ -11,3 +11,9 @@ void MGLInitializeRunLoop(); (type *)([temp##__LINE__ isKindOfClass:[type class]] ? temp##__LINE__ : nil); \ }) +#define MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(object, proto) \ + ({ \ + __typeof__( object ) temp##__LINE__ = (object); \ + (id< proto >)([temp##__LINE__ conformsToProtocol:@protocol( proto )] ? temp##__LINE__ : nil); \ + }) + diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm index c9130d6481..04bd7efde7 100644 --- a/platform/darwin/src/MGLShapeSource.mm +++ b/platform/darwin/src/MGLShapeSource.mm @@ -1,3 +1,4 @@ +#import "MGLFoundation_Private.h" #import "MGLShapeSource_Private.h" #import "MGLStyle_Private.h" @@ -233,7 +234,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary cluster = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(feature, MGLCluster); if (cluster) { diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m deleted file mode 100644 index 46778f51c9..0000000000 --- a/platform/darwin/test/MGLCodingTests.m +++ /dev/null @@ -1,624 +0,0 @@ -#import -#import - -#import "MGLCluster_Private.h" - -#if TARGET_OS_IPHONE -#import "MGLUserLocation_Private.h" -#endif - -@interface MGLCodingTests : XCTestCase -@end - -@implementation MGLCodingTests - -- (NSString *)temporaryFilePathForClass:(Class)clazz { - return [NSTemporaryDirectory() stringByAppendingPathComponent:NSStringFromClass(clazz)]; -} - -- (void)testPointAnnotation { - MGLPointAnnotation *annotation = [[MGLPointAnnotation alloc] init]; - annotation.coordinate = CLLocationCoordinate2DMake(0.5, 0.5); - annotation.title = @"title"; - annotation.subtitle = @"subtitle"; - - NSString *filePath = [self temporaryFilePathForClass:MGLPointAnnotation.class]; - [NSKeyedArchiver archiveRootObject:annotation toFile:filePath]; - MGLPointAnnotation *unarchivedAnnotation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(annotation, unarchivedAnnotation); -} - -- (void)testPointFeature { - MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init]; - pointFeature.title = @"title"; - pointFeature.subtitle = @"subtitle"; - pointFeature.identifier = @(123); - pointFeature.attributes = @{@"bbox": @[@1, @2, @3, @4]}; - - NSString *filePath = [self temporaryFilePathForClass:MGLPointFeature.class]; - [NSKeyedArchiver archiveRootObject:pointFeature toFile:filePath]; - MGLPointFeature *unarchivedPointFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(pointFeature, unarchivedPointFeature); -} - -- (void)testPointFeatureCluster { - MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init]; - pointFeature.title = @"title"; - pointFeature.subtitle = @"subtitle"; - pointFeature.identifier = @(123); - pointFeature.attributes = @{ - @"cluster" : @(YES), - @"cluster_id" : @(456), - @"point_count" : @(2), - @"point_count_abbreviated" : @"2" - }; - - XCTAssert([pointFeature isMemberOfClass:[MGLPointFeature class]], @""); - - NSString *filePath = [self temporaryFilePathForClass:MGLPointFeature.class]; - [NSKeyedArchiver archiveRootObject:pointFeature toFile:filePath]; - MGLPointFeature *unarchivedPointFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(pointFeature, unarchivedPointFeature); - - // Unarchive process should convert to a cluster - NSString *subclassName = MGLClusterSubclassNameForFeature(pointFeature); - XCTAssert([unarchivedPointFeature isMemberOfClass:NSClassFromString(subclassName)]); - - id cluster = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(unarchivedPointFeature, MGLCluster); - - XCTAssert(cluster); - XCTAssert(cluster.clusterIdentifier == 456); - XCTAssert(cluster.clusterPointCount == 2); - XCTAssertEqualObjects(cluster.clusterPointCountAbbreviation, @"2"); - - // Archiving shouldn't affect - [NSKeyedArchiver archiveRootObject:unarchivedPointFeature toFile:filePath]; - MGLPointFeature *unarchivedPointFeature2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssert([unarchivedPointFeature2 isMemberOfClass:NSClassFromString(@"MGLPointFeature_Cluster")]); - XCTAssertEqualObjects(pointFeature, unarchivedPointFeature2); -} - - -- (void)testPolyline { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0.129631234123, 1.7812739312551), - CLLocationCoordinate2DMake(2.532083092342, 3.5216418292392) - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates]; - polyline.title = @"title"; - polyline.subtitle = @"subtitle"; - - NSString *filePath = [self temporaryFilePathForClass:[MGLPolyline class]]; - [NSKeyedArchiver archiveRootObject:polyline toFile:filePath]; - MGLPolyline *unarchivedPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(polyline, unarchivedPolyline); - - CLLocationCoordinate2D otherCoordinates[] = { - CLLocationCoordinate2DMake(-1, -2) - }; - - [unarchivedPolyline replaceCoordinatesInRange:NSMakeRange(0, 1) withCoordinates:otherCoordinates]; - - XCTAssertNotEqualObjects(polyline, unarchivedPolyline); - - CLLocationCoordinate2D multiLineCoordinates[] = { - CLLocationCoordinate2DMake(51.000000, 0.000000), - CLLocationCoordinate2DMake(51.000000, 1.000000), - CLLocationCoordinate2DMake(51.000000, 2.000000), - }; - - NSUInteger multiLineCoordinatesCount = sizeof(multiLineCoordinates) / sizeof(CLLocationCoordinate2D); - MGLPolyline *multiLine = [MGLPolyline polylineWithCoordinates:multiLineCoordinates count:multiLineCoordinatesCount]; - CLLocationCoordinate2D multiLineCenter = CLLocationCoordinate2DMake(51.000000, 1.000000); - - 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, 0.0001); - XCTAssertEqualWithAccuracy([segmentLine coordinate].longitude, segmentCenter.longitude, 0.0001); - - 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, 0.0001); - XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].longitude, sfToBerkeleyCenter.longitude, 0.0001); - -} - -- (void)testPolygon { - CLLocationCoordinate2D coordinates[] = { - 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); - - MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates]; - polygon.title = nil; - polygon.subtitle = @"subtitle"; - - NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]]; - [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 squareCoordinatesCount = sizeof(squareCoordinates) / sizeof(CLLocationCoordinate2D); - MGLPolygon *squarePolygon = [MGLPolygon polygonWithCoordinates:squareCoordinates count:squareCoordinatesCount]; - CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5); - - XCTAssertEqual([squarePolygon coordinate].latitude, squareCenter.latitude); - XCTAssertEqual([squarePolygon coordinate].longitude, squareCenter.longitude); - -} - -- (void)testPolygonWithInteriorPolygons { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0, 1), - CLLocationCoordinate2DMake(10, 20) - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - CLLocationCoordinate2D interiorCoordinates[] = { - CLLocationCoordinate2DMake(4, 4), - CLLocationCoordinate2DMake(6, 6) - }; - - NSUInteger numberOfInteriorCoordinates = sizeof(interiorCoordinates) / sizeof(CLLocationCoordinate2D); - - MGLPolygon *interiorPolygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:numberOfInteriorCoordinates]; - MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates interiorPolygons:@[interiorPolygon]]; - - NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]]; - [NSKeyedArchiver archiveRootObject:polygon toFile:filePath]; - - MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(polygon, unarchivedPolygon); -} - -- (void)testPolylineFeature { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0, 1), - CLLocationCoordinate2DMake(10, 20) - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates]; - polylineFeature.attributes = @{@"bbox": @[@0, @1, @2, @3]}; - polylineFeature.identifier = @"identifier"; - - NSString *filePath = [self temporaryFilePathForClass:[MGLPolylineFeature class]]; - [NSKeyedArchiver archiveRootObject:polylineFeature toFile:filePath]; - - MGLPolylineFeature *unarchivedPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(polylineFeature, unarchivedPolylineFeature); - - unarchivedPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]}; - - XCTAssertNotEqualObjects(polylineFeature, unarchivedPolylineFeature); -} - -- (void)testPolygonFeature { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0, 1), - CLLocationCoordinate2DMake(10, 20) - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates]; - - NSString *filePath = [self temporaryFilePathForClass:[MGLPolygonFeature class]]; - [NSKeyedArchiver archiveRootObject:polygonFeature toFile:filePath]; - - MGLPolygonFeature *unarchivedPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(polygonFeature, unarchivedPolygonFeature); - - unarchivedPolygonFeature.identifier = @"test"; - - XCTAssertNotEqualObjects(polygonFeature, unarchivedPolygonFeature); -} - -- (void)testPointCollection { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0, 1), - CLLocationCoordinate2DMake(10, 11), - CLLocationCoordinate2DMake(20, 21), - CLLocationCoordinate2DMake(30, 31), - }; - - 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]; - - MGLPointCollection *unarchivedPointCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(pointCollection, unarchivedPointCollection); -} - -- (void)testPointCollectionFeature { - NSMutableArray *features = [NSMutableArray array]; - for (NSUInteger i = 0; i < 100; i++) { - MGLPointFeature *feature = [[MGLPointFeature alloc] init]; - feature.coordinate = CLLocationCoordinate2DMake(arc4random() % 90, arc4random() % 180); - [features addObject:feature]; - } - - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0, 1), - CLLocationCoordinate2DMake(10, 11), - CLLocationCoordinate2DMake(20, 21), - CLLocationCoordinate2DMake(30, 31), - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - MGLPointCollectionFeature *collection = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:numberOfCoordinates]; - collection.identifier = @"identifier"; - collection.attributes = @{@"bbox": @[@1, @2, @3, @4]}; - - NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollectionFeature class]]; - [NSKeyedArchiver archiveRootObject:collection toFile:filePath]; - - MGLPointCollectionFeature *unarchivedCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(collection, unarchivedCollection); - - unarchivedCollection.identifier = @"newIdentifier"; - - XCTAssertNotEqualObjects(collection, unarchivedCollection); -} - -- (void)testMultiPolyline { - - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0, 1), - CLLocationCoordinate2DMake(10, 11), - 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); - - NSMutableArray *polylines = [NSMutableArray array]; - - for (NSUInteger i = 0; i < 100; i++) { - MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates]; - [polylines addObject:polyline]; - } - - MGLMultiPolyline *multiPolyline = [MGLMultiPolyline multiPolylineWithPolylines:polylines]; - - NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolyline class]]; - [NSKeyedArchiver archiveRootObject:multiPolyline toFile:filePath]; - - MGLMultiPolyline *unarchivedMultiPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - MGLMultiPolyline *anotherMultipolyline = [MGLMultiPolyline multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]]; - - XCTAssertEqualObjects(multiPolyline, unarchivedMultiPolyline); - XCTAssertNotEqualObjects(unarchivedMultiPolyline, anotherMultipolyline); -} - -- (void)testMultiPolygon { - - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(0, 1), - CLLocationCoordinate2DMake(10, 11), - CLLocationCoordinate2DMake(20, 21), - CLLocationCoordinate2DMake(30, 31), - }; - - CLLocationCoordinate2D outerSquare[] = { - 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 outerCoordinatesCount = sizeof(outerSquare) / sizeof(CLLocationCoordinate2D); - NSUInteger innerCoordinatesCount = sizeof(innerSquare) / sizeof(CLLocationCoordinate2D); - - 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); - - XCTAssertEqual([squares coordinate].latitude, squareCenter.latitude); - XCTAssertEqual([squares coordinate].longitude, squareCenter.longitude); - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - NSMutableArray *polygons = [NSMutableArray array]; - - for (NSUInteger i = 0; i < 100; i++) { - MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates]; - [polygons addObject:polygon]; - } - - MGLMultiPolygon *multiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:polygons]; - - NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolygon class]]; - [NSKeyedArchiver archiveRootObject:multiPolygon toFile:filePath]; - - MGLMultiPolygon *unarchivedMultiPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - MGLMultiPolygon *anotherMultiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]]; - - XCTAssertEqualObjects(multiPolygon, unarchivedMultiPolygon); - XCTAssertNotEqualObjects(anotherMultiPolygon, unarchivedMultiPolygon); - -} - -- (void)testShapeCollection { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(10.12315786, 11.23451186), - CLLocationCoordinate2DMake(20.91836515, 21.93689215), - CLLocationCoordinate2DMake(30.55697246, 31.33988123), - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates]; - MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates]; - - MGLShapeCollection *shapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polyline, polygon]]; - - NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollection class]]; - [NSKeyedArchiver archiveRootObject:shapeCollection toFile:filePath]; - - MGLShapeCollection *unarchivedShapeCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - MGLShapeCollection *anotherShapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polygon]]; - - XCTAssertEqualObjects(shapeCollection, unarchivedShapeCollection); - XCTAssertNotEqualObjects(shapeCollection, anotherShapeCollection); -} - -- (void)testMultiPolylineFeature { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(10.12315786, 11.23451186), - CLLocationCoordinate2DMake(20.91836515, 21.93689215), - CLLocationCoordinate2DMake(30.55697246, 31.33988123), - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - NSMutableArray *polylines = [NSMutableArray array]; - for (NSUInteger i = 0; i < 100; i++) { - MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates]; - polylineFeature.identifier = @(arc4random() % 100).stringValue; - [polylines addObject:polylineFeature]; - } - - MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines]; - multiPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]}; - - NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]]; - [NSKeyedArchiver archiveRootObject:multiPolylineFeature toFile:filePath]; - - MGLMultiPolylineFeature *unarchivedMultiPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - MGLMultiPolylineFeature *anotherMultiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]]; - - XCTAssertEqualObjects(multiPolylineFeature, unarchivedMultiPolylineFeature); - XCTAssertNotEqualObjects(unarchivedMultiPolylineFeature, anotherMultiPolylineFeature); -} - -- (void)testMultiPolygonFeature { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(10.12315786, 11.23451185), - CLLocationCoordinate2DMake(20.88471238, 21.93684215), - CLLocationCoordinate2DMake(30.15697236, 31.32988123), - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - NSMutableArray *polygons = [NSMutableArray array]; - for (NSUInteger i = 0; i < 100; i++ ) { - MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates]; - polygonFeature.identifier = @(arc4random_uniform(100)).stringValue; - [polygons addObject:polygonFeature]; - } - - MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons]; - multiPolygonFeature.attributes = @{@"bbox": @[@(arc4random_uniform(100)), - @(arc4random_uniform(100)), - @(arc4random_uniform(100)), - @(arc4random_uniform(100))]}; - - NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]]; - [NSKeyedArchiver archiveRootObject:multiPolygonFeature toFile:filePath]; - - MGLMultiPolygonFeature *unarchivedMultiPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - MGLMultiPolygonFeature *anotherMultiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]]; - - XCTAssertEqualObjects(multiPolygonFeature, unarchivedMultiPolygonFeature); - XCTAssertNotEqualObjects(anotherMultiPolygonFeature, unarchivedMultiPolygonFeature); -} - -- (void)testShapeCollectionFeature { - CLLocationCoordinate2D coordinates[] = { - CLLocationCoordinate2DMake(10.12315786, 11.23451186), - CLLocationCoordinate2DMake(20.91836515, 21.93689215), - CLLocationCoordinate2DMake(30.55697246, 31.33988123), - }; - - NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); - - MGLPolylineFeature *polyline = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates]; - MGLPolygonFeature *polygon = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates]; - - MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polyline, polygon]]; - shapeCollectionFeature.identifier = @(arc4random_uniform(100)).stringValue; - shapeCollectionFeature.attributes = @{@"bbox":@[@(arc4random_uniform(100)), - @(arc4random_uniform(100)), - @(arc4random_uniform(100)), - @(arc4random_uniform(100))]}; - - NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollectionFeature class]]; - [NSKeyedArchiver archiveRootObject:shapeCollectionFeature toFile:filePath]; - - MGLShapeCollectionFeature *unarchivedShapeCollectionFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(shapeCollectionFeature, unarchivedShapeCollectionFeature); -} - -- (void)testAnnotationImage { -#if TARGET_OS_IPHONE - UIGraphicsBeginImageContext(CGSizeMake(10, 10)); - [[UIColor redColor] setFill]; - UIRectFill(CGRectMake(0, 0, 10, 10)); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); -#else - NSImage *image = [[NSImage alloc] initWithSize:CGSizeMake(10, 10)]; - [image lockFocus]; - [[NSColor redColor] drawSwatchInRect:CGRectMake(0, 0, 10, 10)]; - [image unlockFocus]; -#endif - - MGLAnnotationImage *annotationImage = [MGLAnnotationImage annotationImageWithImage:image reuseIdentifier:@(arc4random_uniform(100)).stringValue]; - - NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationImage class]]; - [NSKeyedArchiver archiveRootObject:annotationImage toFile:filePath]; - - MGLAnnotationImage *unarchivedAnnotationImage = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(annotationImage, unarchivedAnnotationImage); -} - -#if TARGET_OS_IPHONE -- (void)testAnnotationView { - MGLAnnotationView *annotationView = [[MGLAnnotationView alloc] initWithReuseIdentifier:@"id"]; - annotationView.enabled = NO; - annotationView.selected = YES; - annotationView.draggable = YES; - annotationView.centerOffset = CGVectorMake(10, 10); - annotationView.scalesWithViewingDistance = NO; - - NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationView class]]; - [NSKeyedArchiver archiveRootObject:annotationView toFile:filePath]; - - MGLAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled); - XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected); - XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable); - XCTAssertEqualObjects(NSStringFromCGVector(annotationView.centerOffset), NSStringFromCGVector(unarchivedAnnotationView.centerOffset)); - XCTAssertEqual(annotationView.scalesWithViewingDistance, unarchivedAnnotationView.scalesWithViewingDistance); -} -#endif - -#if TARGET_OS_IPHONE -- (void)testUserLocation { - MGLUserLocation *userLocation = [[MGLUserLocation alloc] init]; - userLocation.location = [[CLLocation alloc] initWithLatitude:1 longitude:1]; - - NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocation class]]; - [NSKeyedArchiver archiveRootObject:userLocation toFile:filePath]; - - MGLUserLocation *unarchivedUserLocation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqualObjects(userLocation, unarchivedUserLocation); - unarchivedUserLocation.location = [[CLLocation alloc] initWithLatitude:10 longitude:10]; - XCTAssertNotEqualObjects(userLocation, unarchivedUserLocation); -} -#endif - -#if TARGET_OS_IPHONE -- (void)testUserLocationAnnotationView { - MGLUserLocationAnnotationView *annotationView = [[MGLUserLocationAnnotationView alloc] init]; - annotationView.enabled = NO; - annotationView.selected = YES; - annotationView.draggable = YES; - annotationView.centerOffset = CGVectorMake(10, 10); - annotationView.scalesWithViewingDistance = NO; - - NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocationAnnotationView class]]; - [NSKeyedArchiver archiveRootObject:annotationView toFile:filePath]; - - MGLUserLocationAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled); - XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected); - XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable); - XCTAssertEqualObjects(NSStringFromCGVector(annotationView.centerOffset), NSStringFromCGVector(unarchivedAnnotationView.centerOffset)); - XCTAssertEqual(annotationView.scalesWithViewingDistance, unarchivedAnnotationView.scalesWithViewingDistance); -} -#endif - -@end diff --git a/platform/darwin/test/MGLCodingTests.mm b/platform/darwin/test/MGLCodingTests.mm new file mode 100644 index 0000000000..e8fd0ddf27 --- /dev/null +++ b/platform/darwin/test/MGLCodingTests.mm @@ -0,0 +1,625 @@ +#import +#import + +#import "MGLFoundation_Private.h" +#import "MGLCluster_Private.h" + +#if TARGET_OS_IPHONE +#import "MGLUserLocation_Private.h" +#endif + +@interface MGLCodingTests : XCTestCase +@end + +@implementation MGLCodingTests + +- (NSString *)temporaryFilePathForClass:(Class)clazz { + return [NSTemporaryDirectory() stringByAppendingPathComponent:NSStringFromClass(clazz)]; +} + +- (void)testPointAnnotation { + MGLPointAnnotation *annotation = [[MGLPointAnnotation alloc] init]; + annotation.coordinate = CLLocationCoordinate2DMake(0.5, 0.5); + annotation.title = @"title"; + annotation.subtitle = @"subtitle"; + + NSString *filePath = [self temporaryFilePathForClass:MGLPointAnnotation.class]; + [NSKeyedArchiver archiveRootObject:annotation toFile:filePath]; + MGLPointAnnotation *unarchivedAnnotation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(annotation, unarchivedAnnotation); +} + +- (void)testPointFeature { + MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init]; + pointFeature.title = @"title"; + pointFeature.subtitle = @"subtitle"; + pointFeature.identifier = @(123); + pointFeature.attributes = @{@"bbox": @[@1, @2, @3, @4]}; + + NSString *filePath = [self temporaryFilePathForClass:MGLPointFeature.class]; + [NSKeyedArchiver archiveRootObject:pointFeature toFile:filePath]; + MGLPointFeature *unarchivedPointFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(pointFeature, unarchivedPointFeature); +} + +- (void)testPointFeatureCluster { + MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init]; + pointFeature.title = @"title"; + pointFeature.subtitle = @"subtitle"; + pointFeature.identifier = @(123); + pointFeature.attributes = @{ + @"cluster" : @(YES), + @"cluster_id" : @(456), + @"point_count" : @(2), + @"point_count_abbreviated" : @"2" + }; + + XCTAssert([pointFeature isMemberOfClass:[MGLPointFeature class]], @""); + + NSString *filePath = [self temporaryFilePathForClass:MGLPointFeature.class]; + [NSKeyedArchiver archiveRootObject:pointFeature toFile:filePath]; + MGLPointFeature *unarchivedPointFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(pointFeature, unarchivedPointFeature); + + // Unarchive process should convert to a cluster + NSString *subclassName = MGLClusterSubclassNameForFeature(pointFeature); + XCTAssert([unarchivedPointFeature isMemberOfClass:NSClassFromString(subclassName)]); + + id cluster = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(unarchivedPointFeature, MGLCluster); + + XCTAssert(cluster); + XCTAssert(cluster.clusterIdentifier == 456); + XCTAssert(cluster.clusterPointCount == 2); + XCTAssertEqualObjects(cluster.clusterPointCountAbbreviation, @"2"); + + // Archiving shouldn't affect + [NSKeyedArchiver archiveRootObject:unarchivedPointFeature toFile:filePath]; + MGLPointFeature *unarchivedPointFeature2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssert([unarchivedPointFeature2 isMemberOfClass:NSClassFromString(@"MGLPointFeature_Cluster")]); + XCTAssertEqualObjects(pointFeature, unarchivedPointFeature2); +} + + +- (void)testPolyline { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0.129631234123, 1.7812739312551), + CLLocationCoordinate2DMake(2.532083092342, 3.5216418292392) + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates]; + polyline.title = @"title"; + polyline.subtitle = @"subtitle"; + + NSString *filePath = [self temporaryFilePathForClass:[MGLPolyline class]]; + [NSKeyedArchiver archiveRootObject:polyline toFile:filePath]; + MGLPolyline *unarchivedPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(polyline, unarchivedPolyline); + + CLLocationCoordinate2D otherCoordinates[] = { + CLLocationCoordinate2DMake(-1, -2) + }; + + [unarchivedPolyline replaceCoordinatesInRange:NSMakeRange(0, 1) withCoordinates:otherCoordinates]; + + XCTAssertNotEqualObjects(polyline, unarchivedPolyline); + + CLLocationCoordinate2D multiLineCoordinates[] = { + CLLocationCoordinate2DMake(51.000000, 0.000000), + CLLocationCoordinate2DMake(51.000000, 1.000000), + CLLocationCoordinate2DMake(51.000000, 2.000000), + }; + + NSUInteger multiLineCoordinatesCount = sizeof(multiLineCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolyline *multiLine = [MGLPolyline polylineWithCoordinates:multiLineCoordinates count:multiLineCoordinatesCount]; + CLLocationCoordinate2D multiLineCenter = CLLocationCoordinate2DMake(51.000000, 1.000000); + + 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, 0.0001); + XCTAssertEqualWithAccuracy([segmentLine coordinate].longitude, segmentCenter.longitude, 0.0001); + + 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, 0.0001); + XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].longitude, sfToBerkeleyCenter.longitude, 0.0001); + +} + +- (void)testPolygon { + CLLocationCoordinate2D coordinates[] = { + 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); + + MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates]; + polygon.title = nil; + polygon.subtitle = @"subtitle"; + + NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]]; + [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 squareCoordinatesCount = sizeof(squareCoordinates) / sizeof(CLLocationCoordinate2D); + MGLPolygon *squarePolygon = [MGLPolygon polygonWithCoordinates:squareCoordinates count:squareCoordinatesCount]; + CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5); + + XCTAssertEqual([squarePolygon coordinate].latitude, squareCenter.latitude); + XCTAssertEqual([squarePolygon coordinate].longitude, squareCenter.longitude); + +} + +- (void)testPolygonWithInteriorPolygons { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0, 1), + CLLocationCoordinate2DMake(10, 20) + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + CLLocationCoordinate2D interiorCoordinates[] = { + CLLocationCoordinate2DMake(4, 4), + CLLocationCoordinate2DMake(6, 6) + }; + + NSUInteger numberOfInteriorCoordinates = sizeof(interiorCoordinates) / sizeof(CLLocationCoordinate2D); + + MGLPolygon *interiorPolygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:numberOfInteriorCoordinates]; + MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates interiorPolygons:@[interiorPolygon]]; + + NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]]; + [NSKeyedArchiver archiveRootObject:polygon toFile:filePath]; + + MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(polygon, unarchivedPolygon); +} + +- (void)testPolylineFeature { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0, 1), + CLLocationCoordinate2DMake(10, 20) + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates]; + polylineFeature.attributes = @{@"bbox": @[@0, @1, @2, @3]}; + polylineFeature.identifier = @"identifier"; + + NSString *filePath = [self temporaryFilePathForClass:[MGLPolylineFeature class]]; + [NSKeyedArchiver archiveRootObject:polylineFeature toFile:filePath]; + + MGLPolylineFeature *unarchivedPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(polylineFeature, unarchivedPolylineFeature); + + unarchivedPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]}; + + XCTAssertNotEqualObjects(polylineFeature, unarchivedPolylineFeature); +} + +- (void)testPolygonFeature { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0, 1), + CLLocationCoordinate2DMake(10, 20) + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates]; + + NSString *filePath = [self temporaryFilePathForClass:[MGLPolygonFeature class]]; + [NSKeyedArchiver archiveRootObject:polygonFeature toFile:filePath]; + + MGLPolygonFeature *unarchivedPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(polygonFeature, unarchivedPolygonFeature); + + unarchivedPolygonFeature.identifier = @"test"; + + XCTAssertNotEqualObjects(polygonFeature, unarchivedPolygonFeature); +} + +- (void)testPointCollection { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0, 1), + CLLocationCoordinate2DMake(10, 11), + CLLocationCoordinate2DMake(20, 21), + CLLocationCoordinate2DMake(30, 31), + }; + + 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]; + + MGLPointCollection *unarchivedPointCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(pointCollection, unarchivedPointCollection); +} + +- (void)testPointCollectionFeature { + NSMutableArray *features = [NSMutableArray array]; + for (NSUInteger i = 0; i < 100; i++) { + MGLPointFeature *feature = [[MGLPointFeature alloc] init]; + feature.coordinate = CLLocationCoordinate2DMake(arc4random() % 90, arc4random() % 180); + [features addObject:feature]; + } + + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0, 1), + CLLocationCoordinate2DMake(10, 11), + CLLocationCoordinate2DMake(20, 21), + CLLocationCoordinate2DMake(30, 31), + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + MGLPointCollectionFeature *collection = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:numberOfCoordinates]; + collection.identifier = @"identifier"; + collection.attributes = @{@"bbox": @[@1, @2, @3, @4]}; + + NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollectionFeature class]]; + [NSKeyedArchiver archiveRootObject:collection toFile:filePath]; + + MGLPointCollectionFeature *unarchivedCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(collection, unarchivedCollection); + + unarchivedCollection.identifier = @"newIdentifier"; + + XCTAssertNotEqualObjects(collection, unarchivedCollection); +} + +- (void)testMultiPolyline { + + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0, 1), + CLLocationCoordinate2DMake(10, 11), + 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); + + NSMutableArray *polylines = [NSMutableArray array]; + + for (NSUInteger i = 0; i < 100; i++) { + MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates]; + [polylines addObject:polyline]; + } + + MGLMultiPolyline *multiPolyline = [MGLMultiPolyline multiPolylineWithPolylines:polylines]; + + NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolyline class]]; + [NSKeyedArchiver archiveRootObject:multiPolyline toFile:filePath]; + + MGLMultiPolyline *unarchivedMultiPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + MGLMultiPolyline *anotherMultipolyline = [MGLMultiPolyline multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]]; + + XCTAssertEqualObjects(multiPolyline, unarchivedMultiPolyline); + XCTAssertNotEqualObjects(unarchivedMultiPolyline, anotherMultipolyline); +} + +- (void)testMultiPolygon { + + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(0, 1), + CLLocationCoordinate2DMake(10, 11), + CLLocationCoordinate2DMake(20, 21), + CLLocationCoordinate2DMake(30, 31), + }; + + CLLocationCoordinate2D outerSquare[] = { + 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 outerCoordinatesCount = sizeof(outerSquare) / sizeof(CLLocationCoordinate2D); + NSUInteger innerCoordinatesCount = sizeof(innerSquare) / sizeof(CLLocationCoordinate2D); + + 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); + + XCTAssertEqual([squares coordinate].latitude, squareCenter.latitude); + XCTAssertEqual([squares coordinate].longitude, squareCenter.longitude); + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + NSMutableArray *polygons = [NSMutableArray array]; + + for (NSUInteger i = 0; i < 100; i++) { + MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates]; + [polygons addObject:polygon]; + } + + MGLMultiPolygon *multiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:polygons]; + + NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolygon class]]; + [NSKeyedArchiver archiveRootObject:multiPolygon toFile:filePath]; + + MGLMultiPolygon *unarchivedMultiPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + MGLMultiPolygon *anotherMultiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]]; + + XCTAssertEqualObjects(multiPolygon, unarchivedMultiPolygon); + XCTAssertNotEqualObjects(anotherMultiPolygon, unarchivedMultiPolygon); + +} + +- (void)testShapeCollection { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(10.12315786, 11.23451186), + CLLocationCoordinate2DMake(20.91836515, 21.93689215), + CLLocationCoordinate2DMake(30.55697246, 31.33988123), + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates]; + MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates]; + + MGLShapeCollection *shapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polyline, polygon]]; + + NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollection class]]; + [NSKeyedArchiver archiveRootObject:shapeCollection toFile:filePath]; + + MGLShapeCollection *unarchivedShapeCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + MGLShapeCollection *anotherShapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polygon]]; + + XCTAssertEqualObjects(shapeCollection, unarchivedShapeCollection); + XCTAssertNotEqualObjects(shapeCollection, anotherShapeCollection); +} + +- (void)testMultiPolylineFeature { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(10.12315786, 11.23451186), + CLLocationCoordinate2DMake(20.91836515, 21.93689215), + CLLocationCoordinate2DMake(30.55697246, 31.33988123), + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + NSMutableArray *polylines = [NSMutableArray array]; + for (NSUInteger i = 0; i < 100; i++) { + MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates]; + polylineFeature.identifier = @(arc4random() % 100).stringValue; + [polylines addObject:polylineFeature]; + } + + MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines]; + multiPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]}; + + NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]]; + [NSKeyedArchiver archiveRootObject:multiPolylineFeature toFile:filePath]; + + MGLMultiPolylineFeature *unarchivedMultiPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + MGLMultiPolylineFeature *anotherMultiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]]; + + XCTAssertEqualObjects(multiPolylineFeature, unarchivedMultiPolylineFeature); + XCTAssertNotEqualObjects(unarchivedMultiPolylineFeature, anotherMultiPolylineFeature); +} + +- (void)testMultiPolygonFeature { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(10.12315786, 11.23451185), + CLLocationCoordinate2DMake(20.88471238, 21.93684215), + CLLocationCoordinate2DMake(30.15697236, 31.32988123), + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + NSMutableArray *polygons = [NSMutableArray array]; + for (NSUInteger i = 0; i < 100; i++ ) { + MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates]; + polygonFeature.identifier = @(arc4random_uniform(100)).stringValue; + [polygons addObject:polygonFeature]; + } + + MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons]; + multiPolygonFeature.attributes = @{@"bbox": @[@(arc4random_uniform(100)), + @(arc4random_uniform(100)), + @(arc4random_uniform(100)), + @(arc4random_uniform(100))]}; + + NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]]; + [NSKeyedArchiver archiveRootObject:multiPolygonFeature toFile:filePath]; + + MGLMultiPolygonFeature *unarchivedMultiPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + MGLMultiPolygonFeature *anotherMultiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]]; + + XCTAssertEqualObjects(multiPolygonFeature, unarchivedMultiPolygonFeature); + XCTAssertNotEqualObjects(anotherMultiPolygonFeature, unarchivedMultiPolygonFeature); +} + +- (void)testShapeCollectionFeature { + CLLocationCoordinate2D coordinates[] = { + CLLocationCoordinate2DMake(10.12315786, 11.23451186), + CLLocationCoordinate2DMake(20.91836515, 21.93689215), + CLLocationCoordinate2DMake(30.55697246, 31.33988123), + }; + + NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D); + + MGLPolylineFeature *polyline = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates]; + MGLPolygonFeature *polygon = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates]; + + MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polyline, polygon]]; + shapeCollectionFeature.identifier = @(arc4random_uniform(100)).stringValue; + shapeCollectionFeature.attributes = @{@"bbox":@[@(arc4random_uniform(100)), + @(arc4random_uniform(100)), + @(arc4random_uniform(100)), + @(arc4random_uniform(100))]}; + + NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollectionFeature class]]; + [NSKeyedArchiver archiveRootObject:shapeCollectionFeature toFile:filePath]; + + MGLShapeCollectionFeature *unarchivedShapeCollectionFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(shapeCollectionFeature, unarchivedShapeCollectionFeature); +} + +- (void)testAnnotationImage { +#if TARGET_OS_IPHONE + UIGraphicsBeginImageContext(CGSizeMake(10, 10)); + [[UIColor redColor] setFill]; + UIRectFill(CGRectMake(0, 0, 10, 10)); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); +#else + NSImage *image = [[NSImage alloc] initWithSize:CGSizeMake(10, 10)]; + [image lockFocus]; + [[NSColor redColor] drawSwatchInRect:CGRectMake(0, 0, 10, 10)]; + [image unlockFocus]; +#endif + + MGLAnnotationImage *annotationImage = [MGLAnnotationImage annotationImageWithImage:image reuseIdentifier:@(arc4random_uniform(100)).stringValue]; + + NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationImage class]]; + [NSKeyedArchiver archiveRootObject:annotationImage toFile:filePath]; + + MGLAnnotationImage *unarchivedAnnotationImage = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(annotationImage, unarchivedAnnotationImage); +} + +#if TARGET_OS_IPHONE +- (void)testAnnotationView { + MGLAnnotationView *annotationView = [[MGLAnnotationView alloc] initWithReuseIdentifier:@"id"]; + annotationView.enabled = NO; + annotationView.selected = YES; + annotationView.draggable = YES; + annotationView.centerOffset = CGVectorMake(10, 10); + annotationView.scalesWithViewingDistance = NO; + + NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationView class]]; + [NSKeyedArchiver archiveRootObject:annotationView toFile:filePath]; + + MGLAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled); + XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected); + XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable); + XCTAssertEqualObjects(NSStringFromCGVector(annotationView.centerOffset), NSStringFromCGVector(unarchivedAnnotationView.centerOffset)); + XCTAssertEqual(annotationView.scalesWithViewingDistance, unarchivedAnnotationView.scalesWithViewingDistance); +} +#endif + +#if TARGET_OS_IPHONE +- (void)testUserLocation { + MGLUserLocation *userLocation = [[MGLUserLocation alloc] init]; + userLocation.location = [[CLLocation alloc] initWithLatitude:1 longitude:1]; + + NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocation class]]; + [NSKeyedArchiver archiveRootObject:userLocation toFile:filePath]; + + MGLUserLocation *unarchivedUserLocation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqualObjects(userLocation, unarchivedUserLocation); + unarchivedUserLocation.location = [[CLLocation alloc] initWithLatitude:10 longitude:10]; + XCTAssertNotEqualObjects(userLocation, unarchivedUserLocation); +} +#endif + +#if TARGET_OS_IPHONE +- (void)testUserLocationAnnotationView { + MGLUserLocationAnnotationView *annotationView = [[MGLUserLocationAnnotationView alloc] init]; + annotationView.enabled = NO; + annotationView.selected = YES; + annotationView.draggable = YES; + annotationView.centerOffset = CGVectorMake(10, 10); + annotationView.scalesWithViewingDistance = NO; + + NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocationAnnotationView class]]; + [NSKeyedArchiver archiveRootObject:annotationView toFile:filePath]; + + MGLUserLocationAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled); + XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected); + XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable); + XCTAssertEqualObjects(NSStringFromCGVector(annotationView.centerOffset), NSStringFromCGVector(unarchivedAnnotationView.centerOffset)); + XCTAssertEqual(annotationView.scalesWithViewingDistance, unarchivedAnnotationView.scalesWithViewingDistance); +} +#endif + +@end diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm index 31150cb565..0d6f4af29d 100644 --- a/platform/darwin/test/MGLFeatureTests.mm +++ b/platform/darwin/test/MGLFeatureTests.mm @@ -2,6 +2,7 @@ #import #import +#import "MGLFoundation_Private.h" #import "../../darwin/src/MGLFeature_Private.h" @interface MGLFeatureTests : XCTestCase diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 94f14ab907..ed803fe107 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -170,7 +170,7 @@ 35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */; }; 35D3A1E61E9BE7EB002B38EE /* MGLScaleBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 355ADFFB1E9281DA00F3939D /* MGLScaleBar.h */; }; 35D3A1E71E9BE7EC002B38EE /* MGLScaleBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 355ADFFB1E9281DA00F3939D /* MGLScaleBar.h */; }; - 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */; }; + 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.mm */; }; 35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; }; 35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; }; 35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */; }; @@ -485,8 +485,8 @@ CAA69DA4206DCD0E007279CD /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4A26961CB6E795000B7809 /* Mapbox.framework */; }; CAA69DA5206DCD0E007279CD /* Mapbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DA4A26961CB6E795000B7809 /* Mapbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; CABE5DAD2072FAB40003AF3C /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; }; - CAE21180216552AE00429B6F /* MGLCluster.m in Sources */ = {isa = PBXBuildFile; fileRef = CAE2117F216552AE00429B6F /* MGLCluster.m */; }; - CAE21181216552AE00429B6F /* MGLCluster.m in Sources */ = {isa = PBXBuildFile; fileRef = CAE2117F216552AE00429B6F /* MGLCluster.m */; }; + CAE21180216552AE00429B6F /* MGLCluster.mm in Sources */ = {isa = PBXBuildFile; fileRef = CAE2117F216552AE00429B6F /* MGLCluster.mm */; }; + CAE21181216552AE00429B6F /* MGLCluster.mm in Sources */ = {isa = PBXBuildFile; fileRef = CAE2117F216552AE00429B6F /* MGLCluster.mm */; }; CAE211832165BD0300429B6F /* MGLCluster_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE211822165BD0300429B6F /* MGLCluster_Private.h */; }; CAE211842165BD0300429B6F /* MGLCluster_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE211822165BD0300429B6F /* MGLCluster_Private.h */; }; CAE7AD5520F46EF5003B6782 /* MGLMapSnapshotterSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAE7AD5420F46EF5003B6782 /* MGLMapSnapshotterSwiftTests.swift */; }; @@ -941,7 +941,7 @@ 35D13AB61D3D15E300AFB4E0 /* MGLStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleLayer.mm; sourceTree = ""; }; 35D13AC11D3D19DD00AFB4E0 /* MGLFillStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFillStyleLayer.h; sourceTree = ""; }; 35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFillStyleLayer.mm; sourceTree = ""; }; - 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCodingTests.m; path = ../../darwin/test/MGLCodingTests.m; sourceTree = ""; }; + 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLCodingTests.mm; path = ../../darwin/test/MGLCodingTests.mm; sourceTree = ""; }; 35DE35531EB7CBA8004917C5 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sv; path = sv.lproj/Localizable.stringsdict; sourceTree = ""; }; 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyle_Private.h; sourceTree = ""; }; 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = ""; }; @@ -1153,7 +1153,7 @@ CA6914B420E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLAnnotationViewIntegrationTests.m; path = "Annotation Tests/MGLAnnotationViewIntegrationTests.m"; sourceTree = ""; }; CA88DC2F21C85D900059ED5A /* MGLStyleURLIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLStyleURLIntegrationTest.m; sourceTree = ""; }; CA8FBC0821A47BB100D1203C /* MGLRendererConfigurationTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLRendererConfigurationTests.mm; path = ../../darwin/test/MGLRendererConfigurationTests.mm; sourceTree = ""; }; - CAE2117F216552AE00429B6F /* MGLCluster.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCluster.m; sourceTree = ""; wrapsLines = 0; }; + CAE2117F216552AE00429B6F /* MGLCluster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLCluster.mm; sourceTree = ""; wrapsLines = 0; }; CAE211822165BD0300429B6F /* MGLCluster_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCluster_Private.h; sourceTree = ""; }; CAE7AD5320F46EF5003B6782 /* integration-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "integration-Bridging-Header.h"; sourceTree = ""; }; CAE7AD5420F46EF5003B6782 /* MGLMapSnapshotterSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MGLMapSnapshotterSwiftTests.swift; sourceTree = ""; }; @@ -1991,7 +1991,7 @@ 353D23951D0B0DFE002BE09D /* MGLAnnotationViewTests.m */, DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */, DA35A2C31CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m */, - 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */, + 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.mm */, DA35A2C41CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m */, DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */, 3598544C1E1D38AA00B29F84 /* MGLDistanceFormatterTests.m */, @@ -2219,7 +2219,7 @@ DA8847E01CBAFA5100AB86E3 /* MGLAnnotation.h */, CAE211822165BD0300429B6F /* MGLCluster_Private.h */, CA42323A2159242400BB7C18 /* MGLCluster.h */, - CAE2117F216552AE00429B6F /* MGLCluster.m */, + CAE2117F216552AE00429B6F /* MGLCluster.mm */, DAD1656A1CF41981001FF4B9 /* MGLFeature_Private.h */, DAD165691CF41981001FF4B9 /* MGLFeature.h */, DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */, @@ -3097,7 +3097,7 @@ 170C437D2029D97900863DF0 /* MGLHeatmapStyleLayerTests.mm in Sources */, 170C437C2029D96F00863DF0 /* MGLHeatmapColorTests.mm in Sources */, 357579801D501E09000B822E /* MGLFillStyleLayerTests.mm in Sources */, - 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */, + 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.mm in Sources */, DA1F8F3D1EBD287B00367E42 /* MGLDocumentationGuideTests.swift in Sources */, 076171C32139C70900668A35 /* MGLMapViewTests.m in Sources */, 3598544D1E1D38AA00B29F84 /* MGLDistanceFormatterTests.m in Sources */, @@ -3212,7 +3212,7 @@ DA8848501CBAFB9800AB86E3 /* MGLAnnotationImage.m in Sources */, 40834BF01FE05E1800C1BD0D /* MMELocationManager.m in Sources */, DA8848281CBAFA6200AB86E3 /* MGLShape.mm in Sources */, - CAE21180216552AE00429B6F /* MGLCluster.m in Sources */, + CAE21180216552AE00429B6F /* MGLCluster.mm in Sources */, DA35A2B31CCA141D00E826B2 /* MGLCompassDirectionFormatter.m in Sources */, DD0902A91DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */, 35D13AB91D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */, @@ -3348,7 +3348,7 @@ 40834C041FE05E1800C1BD0D /* MMELocationManager.m in Sources */, DA35A2B41CCA141D00E826B2 /* MGLCompassDirectionFormatter.m in Sources */, 35D13ABA1D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */, - CAE21181216552AE00429B6F /* MGLCluster.m in Sources */, + CAE21181216552AE00429B6F /* MGLCluster.mm in Sources */, 071BBAFF1EE7613E001FB02A /* MGLImageSource.mm in Sources */, DA35A2CC1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */, 40834C591FE05F7600C1BD0D /* TSKTrustKitConfig.m in Sources */, diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp index 665cc9c0dc..0df72f1ed5 100644 --- a/src/mbgl/style/sources/geojson_source.cpp +++ b/src/mbgl/style/sources/geojson_source.cpp @@ -40,11 +40,11 @@ optional GeoJSONSource::getURL() const { return url; } -mapbox::geometry::feature_collection GeoJSONSource::getChildren(const std::uint32_t cluster_id) const { +mapbox::feature::feature_collection GeoJSONSource::getChildren(const std::uint32_t cluster_id) const { return impl().getData()->getChildren(cluster_id); } -mapbox::geometry::feature_collection GeoJSONSource::getLeaves(const std::uint32_t cluster_id, +mapbox::feature::feature_collection GeoJSONSource::getLeaves(const std::uint32_t cluster_id, const std::uint32_t limit = 10, const std::uint32_t offset = 0) const{ return impl().getData()->getLeaves(cluster_id, limit, offset); diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp index 7e83588c5d..2e29317258 100644 --- a/src/mbgl/style/sources/geojson_source_impl.cpp +++ b/src/mbgl/style/sources/geojson_source_impl.cpp @@ -21,11 +21,11 @@ public: return impl.getTile(tileID.z, tileID.x, tileID.y).features; } - mapbox::geometry::feature_collection getChildren(const std::uint32_t) final { + mapbox::feature::feature_collection getChildren(const std::uint32_t) final { return {}; } - mapbox::geometry::feature_collection getLeaves(const std::uint32_t, + mapbox::feature::feature_collection getLeaves(const std::uint32_t, const std::uint32_t, const std::uint32_t) final { return {}; @@ -49,11 +49,11 @@ public: return impl.getTile(tileID.z, tileID.x, tileID.y); } - mapbox::geometry::feature_collection getChildren(const std::uint32_t cluster_id) final { + mapbox::feature::feature_collection getChildren(const std::uint32_t cluster_id) final { return impl.getChildren(cluster_id); } - mapbox::geometry::feature_collection getLeaves(const std::uint32_t cluster_id, + mapbox::feature::feature_collection getLeaves(const std::uint32_t cluster_id, const std::uint32_t limit = 10, const std::uint32_t offset = 0) final { return impl.getLeaves(cluster_id, limit, offset); diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp index 4ab529b54b..120e7c2256 100644 --- a/src/mbgl/style/sources/geojson_source_impl.hpp +++ b/src/mbgl/style/sources/geojson_source_impl.hpp @@ -17,8 +17,8 @@ public: virtual mapbox::feature::feature_collection getTile(const CanonicalTileID&) = 0; // SuperclusterData - virtual mapbox::geometry::feature_collection getChildren(const std::uint32_t) = 0; - virtual mapbox::geometry::feature_collection getLeaves(const std::uint32_t, const std::uint32_t, + virtual mapbox::feature::feature_collection getChildren(const std::uint32_t) = 0; + virtual mapbox::feature::feature_collection getLeaves(const std::uint32_t, const std::uint32_t, const std::uint32_t) = 0; virtual std::uint8_t getClusterExpansionZoom(std::uint32_t) = 0; }; -- cgit v1.2.1