summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorituaijagbone <i.ijagbone@gmail.com>2016-09-29 16:44:10 -0700
committerJesse Bounds <jesse@rebounds.net>2016-10-14 14:59:28 -0700
commitf558f6bc4a12fc621589c0b0f50d42c18e00453c (patch)
treec43e9b4722d72b8220e936719cbe14a8f9fa5958
parent242c7f8fe62eb863cf300855aee2f04022311288 (diff)
downloadqtlocation-mapboxgl-f558f6bc4a12fc621589c0b0f50d42c18e00453c.tar.gz
[ios, macos] Add feature initializer
This adds a features initializer to MGLGeoJSONSource. The initializer takes shapes and converts them to JSON representation before passing to core. This also adds methods to the MGLShape concrete subclasses so that they can represent themselves in NSDictionary form suitable for transforming to JSON (GeoJSON).
-rw-r--r--platform/darwin/src/MGLFeature.h9
-rw-r--r--platform/darwin/src/MGLFeature.mm115
-rw-r--r--platform/darwin/src/MGLGeoJSONSource.h31
-rw-r--r--platform/darwin/src/MGLGeoJSONSource.mm29
-rw-r--r--platform/darwin/src/MGLPolygon+MGLAdditions.h15
-rw-r--r--platform/darwin/src/MGLPolygon+MGLAdditions.m35
-rw-r--r--platform/darwin/src/MGLPolyline+MGLAdditions.h15
-rw-r--r--platform/darwin/src/MGLPolyline+MGLAdditions.m25
-rw-r--r--platform/ios/app/MBXViewController.m26
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj24
-rw-r--r--platform/ios/test/MGLGeoJSONSourceTests.mm214
11 files changed, 527 insertions, 11 deletions
diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
index aec4223b12..d187e9cf06 100644
--- a/platform/darwin/src/MGLFeature.h
+++ b/platform/darwin/src/MGLFeature.h
@@ -83,6 +83,10 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy, readonly) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary;
+
/**
Returns the feature attribute for the given attribute name.
@@ -140,6 +144,11 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
*/
@interface MGLShapeCollectionFeature : MGLShapeCollection <MGLFeature>
+
+@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLShape<MGLFeature> *) *shapes;
+
++ (instancetype)shapeCollectionWithShapes:(NS_ARRAY_OF(MGLShape<MGLFeature> *) *)shapes;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
index 6d4f76a71d..142a5e7ae6 100644
--- a/platform/darwin/src/MGLFeature.mm
+++ b/platform/darwin/src/MGLFeature.mm
@@ -6,7 +6,8 @@
#import "MGLValueEvaluator.h"
#import "MGLMultiPoint_Private.h"
-
+#import "MGLPolyline+MGLAdditions.h"
+#import "MGLPolygon+MGLAdditions.h"
#import <mbgl/util/geometry.hpp>
@protocol MGLFeaturePrivate <MGLFeature>
@@ -28,6 +29,17 @@
return self.attributes[key];
}
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary {
+
+ return @{@"type":@"Feature",
+ @"properties":(self.attributes) ? self.attributes : @{},
+ @"geometry":@{
+ @"type":@"Point",
+ @"coordinates":@[@(self.coordinate.longitude), @(self.coordinate.latitude)]
+ }
+ };
+}
+
@end
@interface MGLPolylineFeature () <MGLFeaturePrivate>
@@ -37,11 +49,22 @@
@synthesize identifier;
@synthesize attributes;
+//
- (id)attributeForKey:(NSString *)key {
return self.attributes[key];
}
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary {
+ return @{@"type":@"Feature",
+ @"properties":(self.attributes) ? self.attributes : @{},
+ @"geometry":@{
+ @"type":@"LineString",
+ @"coordinates":self.mgl_coordinates
+ }
+ };;
+}
+
@end
@interface MGLPolygonFeature () <MGLFeaturePrivate>
@@ -56,6 +79,16 @@
return self.attributes[key];
}
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary {
+ return @{@"type":@"Feature",
+ @"properties":(self.attributes) ? self.attributes : @{},
+ @"geometry":@{
+ @"type":@"Polygon",
+ @"coordinates":self.mgl_coordinates
+ }
+ };
+}
+
@end
@interface MGLMultiPointFeature () <MGLFeaturePrivate>
@@ -70,6 +103,23 @@
return self.attributes[key];
}
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary {
+ NSMutableArray *coordinates = [NSMutableArray array];
+
+ for (NSUInteger index = 0; index < self.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = self.coordinates[index];
+ [coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+
+ return @{@"type":@"Feature",
+ @"properties":(self.attributes) ? self.attributes : @{},
+ @"geometry":@{
+ @"type":@"Multipoint",
+ @"coordinates":coordinates
+ }
+ };
+}
+
@end
@interface MGLMultiPolylineFeature () <MGLFeaturePrivate>
@@ -84,6 +134,21 @@
return self.attributes[key];
}
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary {
+ NSMutableArray *coordinates = [NSMutableArray array];
+ for (MGLPolylineFeature *feature in self.polylines) {
+ [coordinates addObject:feature.mgl_coordinates];
+ }
+
+ return @{@"type":@"Feature",
+ @"properties":(self.attributes) ? self.attributes : @{},
+ @"geometry":@{
+ @"type":@"MultiLineString",
+ @"coordinates":coordinates
+ }
+ };
+}
+
@end
@interface MGLMultiPolygonFeature () <MGLFeaturePrivate>
@@ -98,6 +163,21 @@
return self.attributes[key];
}
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary {
+ NSMutableArray *coordinates = [NSMutableArray array];
+ for (MGLPolygonFeature *feature in self.polygons) {
+ [coordinates addObject:feature.mgl_coordinates];
+ }
+
+ return @{@"type":@"Feature",
+ @"properties":(self.attributes) ? self.attributes : @{},
+ @"geometry":@{
+ @"type":@"MultiPolygon",
+ @"coordinates":coordinates
+ }
+ };
+}
+
@end
@interface MGLShapeCollectionFeature () <MGLFeaturePrivate>
@@ -108,10 +188,43 @@
@synthesize identifier;
@synthesize attributes;
+@dynamic shapes;
+
++ (instancetype)shapeCollectionWithShapes:(NS_ARRAY_OF(MGLShape<MGLFeature> *) *)shapes {
+ return [super shapeCollectionWithShapes:shapes];
+}
+
- (id)attributeForKey:(NSString *)key {
return self.attributes[key];
}
+- (NS_DICTIONARY_OF(NSString *, id) *)featureDictionary {
+
+ return @{@"type":@"Feature",
+ @"properties":(self.attributes) ? self.attributes : @{},
+ @"geometry":@{
+ @"type":@"GeometryCollection",
+ @"geometries":[self geometryCollection:self.shapes]
+ }
+ };
+}
+
+- (NS_MUTABLE_ARRAY_OF(NS_DICTIONARY_OF(NSString *, id) *) *)geometryCollection:(NS_ARRAY_OF(MGLShape<MGLFeature> *) *)shapes {
+ NSMutableArray *geometries = [NSMutableArray array];
+
+ for (MGLShape<MGLFeature> *shape in shapes) {
+ if ([shape isKindOfClass:[MGLShapeCollectionFeature class]]) {
+ [geometries addObject:@{@"type":@"GeometryCollection",
+ @"geometries":[self geometryCollection:((MGLShapeCollectionFeature *)shape).shapes]}];
+ } else {
+ NSDictionary *geometry = shape.featureDictionary[@"geometry"];
+ [geometries addObject:@{@"type":geometry[@"type"],
+ @"coordinates":geometry[@"coordinates"] }];
+ }
+ }
+
+ return geometries;
+}
@end
diff --git a/platform/darwin/src/MGLGeoJSONSource.h b/platform/darwin/src/MGLGeoJSONSource.h
index 0b25f1a9d4..9eeb1e1188 100644
--- a/platform/darwin/src/MGLGeoJSONSource.h
+++ b/platform/darwin/src/MGLGeoJSONSource.h
@@ -87,12 +87,25 @@ extern NSString * const MGLGeoJSONToleranceOption;
*/
- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(nullable NS_DICTIONARY_OF(NSString *, id) *)options NS_DESIGNATED_INITIALIZER;
+/**
+ Returns a GeoJSON source with an identifier, features dictionary, and dictionary
+ of options for the source according to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson">style
+ specification</a>.
+
+ @param identifier A string that uniquely identifies the source.
+ @param features An array of features that conform to the `MGLFeature` protocol.
+ @param options An `NSDictionary` of options for this source.
+ @return An initialized GeoJSON source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier features:(NSArray<id<MGLFeature>> *)features options:(nullable NS_DICTIONARY_OF(NSString *,id) *)options NS_DESIGNATED_INITIALIZER;
+
#pragma mark Accessing a Source’s Content
/**
The contents of the source.
-
- If the receiver was initialized using `-initWithIdentifier:URL:`, this property
+
+ If the receiver was initialized using `-initWithIdentifier:URL:options:`, this property
is set to `nil`. This property is unavailable until the receiver is passed into
`-[MGLStyle addSource]`.
*/
@@ -104,21 +117,23 @@ extern NSString * const MGLGeoJSONToleranceOption;
Use the `features` property instead to get an object representation of the
contents. Alternatively, use NSJSONSerialization with the value of this
property to transform it into Foundation types.
-
- If the receiver was initialized using `-initWithIdentifier:URL:`, this property
- is set to `nil`. This property is unavailable until the receiver is passed into
- `-[MGLStyle addSource]`.
+
+ If the receiver was initialized using `-initWithIdentifier:URL:options` or
+ `-initWithIdentifier:features:options`, this property is set to `nil`.
+ This property is unavailable until the receiver is passed
+ into `-[MGLStyle addSource]`.
*/
@property (nonatomic, readonly, nullable, copy) NSData *geoJSONData;
/**
The URL to the GeoJSON document that specifies the contents of the source.
-
- If the receiver was initialized using `-initWithIdentifier:geoJSONData:`, this
+
+ If the receiver was initialized using `-initWithIdentifier:geoJSONData:options`, this
property is set to `nil`.
*/
@property (nonatomic, readonly, nullable) NSURL *URL;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLGeoJSONSource.mm b/platform/darwin/src/MGLGeoJSONSource.mm
index 458f062ad3..4417788851 100644
--- a/platform/darwin/src/MGLGeoJSONSource.mm
+++ b/platform/darwin/src/MGLGeoJSONSource.mm
@@ -42,6 +42,15 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance
return self;
}
+- (instancetype)initWithIdentifier:(NSString *)identifier features:(NSArray<id<MGLFeature>> *)features options:(NS_DICTIONARY_OF(NSString *,id) *)options {
+ if (self = [super initWithIdentifier:identifier]) {
+ _features = features;
+ _options = options;
+ }
+
+ return self;
+}
+
- (mbgl::style::GeoJSONOptions)geoJSONOptions
{
auto mbglOptions = mbgl::style::GeoJSONOptions();
@@ -100,11 +109,29 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance
if (self.URL) {
NSURL *url = self.URL.mgl_URLByStandardizingScheme;
source->setURL(url.absoluteString.UTF8String);
- } else {
+ } else if (self.geoJSONData) {
NSString *string = [[NSString alloc] initWithData:self.geoJSONData encoding:NSUTF8StringEncoding];
const auto geojson = mapbox::geojson::parse(string.UTF8String).get<mapbox::geojson::feature_collection>();
source->setGeoJSON(geojson);
_features = MGLFeaturesFromMBGLFeatures(geojson);
+ } else {
+
+ NSMutableArray *featuresArray = [NSMutableArray array];
+ for (id<MGLFeature> feature in self.features) {
+ [featuresArray addObject:[feature featureDictionary]];
+ }
+
+ NSDictionary *featureCollection = @{
+ @"type":@"FeatureCollection",
+ @"features":featuresArray};
+
+ NSError *error;
+ NSData *featuresJSONData = [NSJSONSerialization dataWithJSONObject:featureCollection options:0 error:&error];
+
+ NSString *string = [[NSString alloc] initWithData:featuresJSONData encoding:NSUTF8StringEncoding];
+ const auto geojson = mapbox::geojson::parse(string.UTF8String).get<mapbox::geojson::feature_collection>();
+ source->setGeoJSON(geojson);
+ _features = MGLFeaturesFromMBGLFeatures(geojson);
}
return std::move(source);
diff --git a/platform/darwin/src/MGLPolygon+MGLAdditions.h b/platform/darwin/src/MGLPolygon+MGLAdditions.h
new file mode 100644
index 0000000000..c9ef95b6bc
--- /dev/null
+++ b/platform/darwin/src/MGLPolygon+MGLAdditions.h
@@ -0,0 +1,15 @@
+//
+// MGLPolygonFeature+MGLAdditions.h
+// ios
+//
+// Created by Mapbox on 9/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <Mapbox/Mapbox.h>
+
+@interface MGLPolygon (MGLAdditions)
+
+- (NS_ARRAY_OF(id) *)mgl_coordinates;
+
+@end
diff --git a/platform/darwin/src/MGLPolygon+MGLAdditions.m b/platform/darwin/src/MGLPolygon+MGLAdditions.m
new file mode 100644
index 0000000000..74fb5668d1
--- /dev/null
+++ b/platform/darwin/src/MGLPolygon+MGLAdditions.m
@@ -0,0 +1,35 @@
+//
+// MGLPolygonFeature+MGLAdditions.m
+// ios
+//
+// Created by Mapbox on 9/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import "MGLPolygon+MGLAdditions.h"
+
+@implementation MGLPolygon (MGLAdditions)
+
+- (NS_ARRAY_OF(id) *)mgl_coordinates {
+ NS_MUTABLE_ARRAY_OF(NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *) *coordinates = [NSMutableArray array];
+
+ NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *exteriorRing = [NSMutableArray array];
+ for (NSUInteger index = 0; index < self.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = self.coordinates[index];
+ [exteriorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+ [coordinates addObject:exteriorRing];
+
+ for (MGLPolygon *interiorPolygon in self.interiorPolygons) {
+ NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *interiorRing = [NSMutableArray array];
+ for (int index = 0; index < interiorPolygon.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = interiorPolygon.coordinates[index];
+ [interiorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+ [coordinates addObject:interiorRing];
+ }
+
+ return coordinates;
+}
+
+@end
diff --git a/platform/darwin/src/MGLPolyline+MGLAdditions.h b/platform/darwin/src/MGLPolyline+MGLAdditions.h
new file mode 100644
index 0000000000..e1e24a8ebc
--- /dev/null
+++ b/platform/darwin/src/MGLPolyline+MGLAdditions.h
@@ -0,0 +1,15 @@
+//
+// MGLPolyline+MGLPolyline_MGLAdditions.h
+// ios
+//
+// Created by Mapbox on 9/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import <Mapbox/Mapbox.h>
+
+@interface MGLPolyline (MGLAdditions)
+
+- (NS_ARRAY_OF(id) *)mgl_coordinates;
+
+@end
diff --git a/platform/darwin/src/MGLPolyline+MGLAdditions.m b/platform/darwin/src/MGLPolyline+MGLAdditions.m
new file mode 100644
index 0000000000..e91e4fc192
--- /dev/null
+++ b/platform/darwin/src/MGLPolyline+MGLAdditions.m
@@ -0,0 +1,25 @@
+//
+// MGLPolyline+MGLPolyline_MGLAdditions.m
+// ios
+//
+// Created by Mapbox on 9/30/16.
+// Copyright © 2016 Mapbox. All rights reserved.
+//
+
+#import "MGLPolyline+MGLAdditions.h"
+
+@implementation MGLPolyline (MGLAdditions)
+
+- (NS_ARRAY_OF(id) *)mgl_coordinates {
+
+ NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *coordinates = [NSMutableArray array];
+
+ for (NSUInteger index = 0; index < self.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = self.coordinates[index];
+ [coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+
+ return coordinates;
+}
+
+@end
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 5a3c56af69..3ee405fd04 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -61,6 +61,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
MBXSettingsRuntimeStylingFilteredFill,
MBXSettingsRuntimeStylingFilteredLines,
MBXSettingsRuntimeStylingNumericFilteredFill,
+ MBXSettingsRuntimeStylingStyleQuery,
};
typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@@ -304,6 +305,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@"Style Fill With Filter",
@"Style Lines With Filter",
@"Style Fill With Numeric Filter",
+ @"Style Query For GeoJSON",
]];
break;
case MBXSettingsMiscellaneous:
@@ -429,6 +431,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
case MBXSettingsRuntimeStylingNumericFilteredFill:
[self styleNumericFilteredFills];
break;
+ case MBXSettingsRuntimeStylingStyleQuery:
+ [self styleQuery];
+ break;
default:
NSAssert(NO, @"All runtime styling setting rows should be implemented");
break;
@@ -785,6 +790,27 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
});
}
+
+- (void)styleQuery
+{
+ CGRect queryRect = CGRectInset(self.mapView.bounds, 100, 200);
+ NSArray *features = [self.mapView visibleFeaturesInRect:queryRect];
+
+// NSMutableArray *polygonFeatures = [NSMutableArray array];
+// for (id<MGLFeature> feature in features) {
+// if ([feature isMemberOfClass:[MGLPolygonFeature class]]) {
+// [polygonFeatures addObject:feature];
+// }
+// }
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"query-id" features:features options:nil];
+ [self.mapView.style addSource:source];
+
+ MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"query-layer-id" source:source];
+ fillLayer.fillColor = [UIColor blueColor];
+ [self.mapView.style addLayer:fillLayer];
+}
+
- (IBAction)startWorldTour
{
_isTouringWorld = YES;
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index ee772a9cd2..9b5a405f34 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -179,6 +179,14 @@
40FDA76B1CCAAA6800442548 /* MBXAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */; };
554180421D2E97DE00012372 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 554180411D2E97DE00012372 /* OpenGLES.framework */; };
55D8C9961D0F18CE00F42F10 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D8C9951D0F18CE00F42F10 /* libsqlite3.tbd */; };
+ 7E016D7E1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */; };
+ 7E016D7F1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */; };
+ 7E016D801D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */; };
+ 7E016D811D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */; };
+ 7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */; };
+ 7E016D851D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */; };
+ 7E016D861D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
+ 7E016D871D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */; };
DA17BE301CC4BAC300402C41 /* MGLMapView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */; };
DA17BE311CC4BDAA00402C41 /* MGLMapView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */; };
@@ -601,6 +609,10 @@
554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
55D8C9941D0F133500F42F10 /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/ios/config.xcconfig; sourceTree = "<group>"; };
55D8C9951D0F18CE00F42F10 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
+ 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolyline+MGLAdditions.h"; sourceTree = "<group>"; };
+ 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolyline+MGLAdditions.m"; sourceTree = "<group>"; };
+ 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = "<group>"; };
+ 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolygon+MGLAdditions.m"; sourceTree = "<group>"; };
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; };
DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Private.h; sourceTree = "<group>"; };
DA1DC94A1CB6C1C2006E619F /* Mapbox GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1355,6 +1367,10 @@
3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */,
3510FFF71D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h */,
3510FFF81D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm */,
+ 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */,
+ 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */,
+ 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */,
+ 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */,
);
name = Categories;
sourceTree = "<group>";
@@ -1419,6 +1435,7 @@
4018B1C91CDC288A00F666AF /* MGLAnnotationView_Private.h in Headers */,
35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */,
DA88482C1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h in Headers */,
+ 7E016D7E1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */,
35D13AB71D3D15E300AFB4E0 /* MGLStyleLayer.h in Headers */,
354D42DC1D4919F900F400A1 /* NSValue+MGLStyleAttributeAdditions_Private.h in Headers */,
DA88488E1CBB047F00AB86E3 /* reachability.h in Headers */,
@@ -1440,6 +1457,7 @@
DA8847FC1CBAFA5100AB86E3 /* MGLStyle.h in Headers */,
354B83961D2E873E005D9406 /* MGLUserLocationAnnotationView.h in Headers */,
DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */,
+ 7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */,
DA88483E1CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */,
4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */,
350098C61D48288B004B2AF0 /* NSNumber+MGLStyleAttributeAdditions_Private.h in Headers */,
@@ -1552,6 +1570,7 @@
350098CB1D482D9C004B2AF0 /* NSArray+MGLStyleAttributeAdditions.h in Headers */,
3510FFEB1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h in Headers */,
35E1A4D91D74336F007AA97F /* MGLValueEvaluator.h in Headers */,
+ 7E016D7F1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */,
DABFB8701CBE9A0F00D62B32 /* MGLMapView+IBAdditions.h in Headers */,
353AFA151D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */,
350098D91D4830D5004B2AF0 /* NSString+MGLStyleAttributeAdditions_Private.h in Headers */,
@@ -1583,6 +1602,7 @@
4018B1CB1CDC288E00F666AF /* MGLAnnotationView.h in Headers */,
DABFB85F1CBE99E500D62B32 /* MGLGeometry.h in Headers */,
354D42DD1D4919F900F400A1 /* NSValue+MGLStyleAttributeAdditions_Private.h in Headers */,
+ 7E016D851D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */,
353933F61D3FB785003F57D7 /* MGLBackgroundStyleLayer.h in Headers */,
DABFB85D1CBE99E500D62B32 /* MGLAccountManager.h in Headers */,
353933F91D3FB79F003F57D7 /* MGLLineStyleLayer.h in Headers */,
@@ -1932,6 +1952,7 @@
files = (
35136D391D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */,
3510FFEC1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
+ 7E016D801D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */,
350098D51D4830A6004B2AF0 /* NSString+MGLStyleAttributeAdditions.mm in Sources */,
3593E5231D529C29006D9365 /* MGLStyleAttribute.mm in Sources */,
350098B11D47E6F4004B2AF0 /* UIColor+MGLStyleAttributeAdditions.mm in Sources */,
@@ -1981,6 +2002,7 @@
DA88481D1CBAFA6200AB86E3 /* MGLMapCamera.mm in Sources */,
DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */,
35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
+ 7E016D861D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */,
DA8848521CBAFB9800AB86E3 /* MGLAPIClient.m in Sources */,
DA8848301CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m in Sources */,
353AFA161D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
@@ -2003,6 +2025,7 @@
files = (
35136D3A1D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */,
3510FFED1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
+ 7E016D811D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */,
350098D61D4830A6004B2AF0 /* NSString+MGLStyleAttributeAdditions.mm in Sources */,
354B83991D2E873E005D9406 /* MGLUserLocationAnnotationView.m in Sources */,
DAA4E4221CBB730400178DFB /* MGLPointAnnotation.m in Sources */,
@@ -2052,6 +2075,7 @@
4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */,
DAA4E4341CBB730400178DFB /* MGLFaux3DUserLocationAnnotationView.m in Sources */,
35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
+ 7E016D871D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */,
DAA4E4311CBB730400178DFB /* MGLMapboxEvents.m in Sources */,
DAA4E4231CBB730400178DFB /* MGLPolygon.mm in Sources */,
353AFA171D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
diff --git a/platform/ios/test/MGLGeoJSONSourceTests.mm b/platform/ios/test/MGLGeoJSONSourceTests.mm
index eed2112211..ce92ec24ab 100644
--- a/platform/ios/test/MGLGeoJSONSourceTests.mm
+++ b/platform/ios/test/MGLGeoJSONSourceTests.mm
@@ -2,6 +2,7 @@
#import <Mapbox/Mapbox.h>
#import "MGLGeoJSONSource_Private.h"
+#import "MGLSource_Private.h"
#include <mbgl/style/sources/geojson_source.hpp>
@@ -30,10 +31,221 @@
XCTAssertEqual(mbglOptions.buffer, 1976);
XCTAssertEqual(mbglOptions.tolerance, 0.42);
- // when the supplied option cluster value is not of the correct type
options = @{MGLGeoJSONClusterOption: @"number 1"};
source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" URL:url options:options];
XCTAssertThrows([source geoJSONOptions]);
}
+- (void)testMGLGeoJSONSourceWithData {
+
+ NSString *data = @"{\"type\": \"FeatureCollection\",\"features\": [{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[-107.75390625,40.329795743702064],[-104.34814453125,37.64903402157866]]}}]}";
+
+ NSData *geoJSON = [data dataUsingEncoding:NSUTF8StringEncoding];
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"test-id" geoJSONData:geoJSON options:nil];
+
+ [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolylineFeature class]]);
+}
+
+- (void)testMGLGeoJSONSourceWithPolylineFeatures {
+ CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)};
+ MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:2];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[polylineFeature] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolylineFeature class]]);
+}
+
+
+- (void)testMGLGeoJSONSourceWithPolygonFeatures {
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 0.0)};
+ MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[polygonFeature] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolygonFeature class]]);
+}
+
+- (void)testMGLGeoJSONSourceWithPolygonFeaturesInculdingInteriorPolygons {
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 0.0)};
+
+ CLLocationCoordinate2D interiorCoordinates[] = {
+ CLLocationCoordinate2DMake(100.2, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.2)};
+
+ MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5];
+
+ MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[polygonFeature] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolygonFeature class]]);
+}
+
+
+- (void)testMGLGeoJSONSourceWithMultiPointFeaturesUsingPolylines {
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0)};
+
+ MGLMultiPointFeature *multiPointFeature = (MGLMultiPointFeature *)[MGLPolylineFeature polylineWithCoordinates:coordinates count:2];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[multiPointFeature] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolylineFeature class]]);
+}
+
+- (void)testMGLGeoJSONSourceWithMultiPointFeaturesUsingPolygons {
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 0.0)};
+
+ CLLocationCoordinate2D interiorCoordinates[] = {
+ CLLocationCoordinate2DMake(100.2, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.2)};
+
+ MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5];
+
+ MGLMultiPointFeature *multiPointFeature = (MGLMultiPointFeature *)[MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[multiPointFeature] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolygonFeature class]]);
+}
+
+- (void)testMGLGeoJSONSourceWithMultiPolylineFeatures {
+ CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)};
+ MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:2];
+ CLLocationCoordinate2D coordinates_1[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)};
+ MGLPolylineFeature *polylineFeature_1 = [MGLPolylineFeature polylineWithCoordinates:coordinates_1 count:2];
+ MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[polylineFeature, polylineFeature_1]];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[multiPolylineFeature] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLMultiPolylineFeature class]]);
+}
+
+- (void)testMGLGeoJSONSourceWithMultiPolygonFeatures {
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 0.0)};
+
+ CLLocationCoordinate2D interiorCoordinates[] = {
+ CLLocationCoordinate2DMake(100.2, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.2)};
+
+ MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5];
+
+ MGLPolygonFeature *polygon_1 = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
+ MGLPolygonFeature *polygon_2 = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
+
+ MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:@[polygon_1, polygon_2]];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[multiPolygonFeature] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLMultiPolygonFeature class]]);
+
+}
+
+- (void)testMGLGeoJSONSourceWithShapeCollectionFeatures {
+ CLLocationCoordinate2D coordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 0.0)};
+
+ CLLocationCoordinate2D interiorCoordinates[] = {
+ CLLocationCoordinate2DMake(100.2, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.2),
+ CLLocationCoordinate2DMake(100.8, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.8),
+ CLLocationCoordinate2DMake(100.2, 0.2)};
+
+ MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5];
+
+ MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
+
+ CLLocationCoordinate2D coordinates_2[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)};
+ MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates_2 count:2];
+
+ MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:@[polygonFeature, polygonFeature]];
+
+ MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[polylineFeature, polylineFeature]];
+
+ MGLMultiPointFeature *multiPointFeature = (MGLMultiPointFeature *)[MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
+
+ MGLPointFeature *pointFeature = [MGLPointFeature new];
+ pointFeature.coordinate = CLLocationCoordinate2DMake(100.2, 0.2);
+
+ MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, multiPointFeature, pointFeature]];
+
+ MGLShapeCollectionFeature *shapeCollectionFeature_1 = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, multiPointFeature, pointFeature, shapeCollectionFeature]];
+
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"" features:@[shapeCollectionFeature_1] options:nil];
+
+ std::unique_ptr<mbgl::style::Source> mbglSource = [source mbglSource];
+
+ XCTAssertNotNil(source.features);
+ XCTAssertEqual(source.features.count, 1);
+ XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLShapeCollectionFeature class]]);
+
+}
+
@end