summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/src/MGLFeature.h15
-rw-r--r--platform/darwin/src/MGLFeature.mm167
-rw-r--r--platform/darwin/src/MGLFeature_Private.h25
-rw-r--r--platform/darwin/src/MGLGeoJSONSource.mm23
-rw-r--r--platform/darwin/src/MGLMultiPoint.h21
-rw-r--r--platform/darwin/src/MGLMultiPoint.mm28
-rw-r--r--platform/darwin/src/MGLMultiPoint_Private.h1
-rw-r--r--platform/darwin/src/MGLPointAnnotation.mm (renamed from platform/darwin/src/MGLPointAnnotation.m)18
-rw-r--r--platform/darwin/src/MGLPolygon+MGLAdditions.h8
-rw-r--r--platform/darwin/src/MGLPolygon+MGLAdditions.m16
-rw-r--r--platform/darwin/src/MGLPolygon.mm39
-rw-r--r--platform/darwin/src/MGLPolyline+MGLAdditions.h8
-rw-r--r--platform/darwin/src/MGLPolyline+MGLAdditions.m15
-rw-r--r--platform/darwin/src/MGLPolyline.mm39
-rw-r--r--platform/darwin/src/MGLShape.mm (renamed from platform/darwin/src/MGLShape.m)0
-rw-r--r--platform/darwin/src/MGLShapeCollection.m14
-rw-r--r--platform/darwin/src/MGLShape_Private.h17
-rw-r--r--platform/darwin/src/NSArray+MGLAdditions.h9
-rw-r--r--platform/darwin/src/NSArray+MGLAdditions.mm26
-rw-r--r--platform/darwin/src/NSDictionary+MGLAdditions.h13
-rw-r--r--platform/darwin/src/NSDictionary+MGLAdditions.mm24
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.h2
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm26
-rw-r--r--platform/darwin/test/MGLFeatureTests.mm165
24 files changed, 548 insertions, 171 deletions
diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
index d187e9cf06..239a338f67 100644
--- a/platform/darwin/src/MGLFeature.h
+++ b/platform/darwin/src/MGLFeature.h
@@ -83,10 +83,6 @@ 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.
@@ -95,6 +91,17 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (nullable id)attributeForKey:(NSString *)key;
+/**
+ Returns a dictionary that can be serialized as a GeoJSON Feature representation
+ of an instance of an `MGLFeature` subclass.
+
+ The dictionary includes a `geometry` key corresponding to the receiver’s
+ underlying geometry data, a `properties` key corresponding to the receiver’s
+ `attributes` property, and an `id` key corresponding to the receiver’s
+ `identifier` property.
+ */
+- (NS_DICTIONARY_OF(NSString *, id) *)geoJSONDictionary;
+
@end
/**
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
index 142a5e7ae6..84dcc4f0bb 100644
--- a/platform/darwin/src/MGLFeature.mm
+++ b/platform/darwin/src/MGLFeature.mm
@@ -5,17 +5,16 @@
#import "MGLPolygon.h"
#import "MGLValueEvaluator.h"
+#import "MGLShape_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLPolyline+MGLAdditions.h"
#import "MGLPolygon+MGLAdditions.h"
-#import <mbgl/util/geometry.hpp>
-
-@protocol MGLFeaturePrivate <MGLFeature>
+#import "NSDictionary+MGLAdditions.h"
-@property (nonatomic, copy, nullable, readwrite) id identifier;
-@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+#import "NSExpression+MGLAdditions.h"
-@end
+#import <mbgl/util/geometry.hpp>
+#import <mapbox/geometry/feature.hpp>
@interface MGLPointFeature () <MGLFeaturePrivate>
@end
@@ -29,15 +28,12 @@
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)]
- }
- };
+- (NSDictionary *)geoJSONDictionary {
+ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier);
+}
+
+- (mbgl::Feature)mbglFeature {
+ return mbglFeature([self featureObject], identifier, self.attributes);
}
@end
@@ -49,20 +45,17 @@
@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
- }
- };;
+- (NSDictionary *)geoJSONDictionary {
+ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier);
+}
+
+- (mbgl::Feature)mbglFeature {
+ return mbglFeature([self featureObject], identifier, self.attributes);
}
@end
@@ -79,14 +72,12 @@
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
- }
- };
+- (NSDictionary *)geoJSONDictionary {
+ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier);
+}
+
+- (mbgl::Feature)mbglFeature {
+ return mbglFeature([self featureObject], identifier, self.attributes);
}
@end
@@ -103,21 +94,12 @@
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
- }
- };
+- (NSDictionary *)geoJSONDictionary {
+ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier);
+}
+
+- (mbgl::Feature)mbglFeature {
+ return mbglFeature([self featureObject], identifier, self.attributes);
}
@end
@@ -134,19 +116,12 @@
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
- }
- };
+- (NSDictionary *)geoJSONDictionary {
+ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier);
+}
+
+- (mbgl::Feature)mbglFeature {
+ return mbglFeature([self featureObject], identifier, self.attributes);
}
@end
@@ -163,19 +138,12 @@
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
- }
- };
+- (NSDictionary *)geoJSONDictionary {
+ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier);
+}
+
+- (mbgl::Feature)mbglFeature {
+ return mbglFeature([self featureObject], identifier, self.attributes);
}
@end
@@ -190,7 +158,7 @@
@dynamic shapes;
-+ (instancetype)shapeCollectionWithShapes:(NS_ARRAY_OF(MGLShape<MGLFeature> *) *)shapes {
++ (instancetype)shapeCollectionWithShapes:(NSArray *)shapes {
return [super shapeCollectionWithShapes:shapes];
}
@@ -198,36 +166,17 @@
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]
- }
- };
+- (NSDictionary *)geoJSONDictionary {
+ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier);
}
-- (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;
+- (mbgl::Feature)mbglFeature {
+ [NSException raise:@"Method unavailable" format:@"%s is not available on %@.", __PRETTY_FUNCTION__, [self class]];
+ mbgl::Polygon<double> geometry;
+ return mbgl::Feature{geometry};
}
-@end
-
+@end
/**
Transforms an `mbgl::geometry::geometry` type into an instance of the
@@ -337,3 +286,21 @@ NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vec
}
return shapes;
}
+
+mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *attributes)
+{
+ if (identifier) {
+ NSExpression *identifierExpression = [NSExpression expressionForConstantValue:identifier];
+ feature.id = [identifierExpression mgl_featureIdentifier];
+ }
+ feature.properties = [attributes mgl_propertyMap];
+ return feature;
+}
+
+NS_DICTIONARY_OF(NSString *, id) *NSDictionaryFeatureForGeometry(NSDictionary *geometry, NSDictionary *attributes, id identifier) {
+ NSMutableDictionary *feature = [@{@"type": @"Feature",
+ @"properties": (attributes) ?: [NSNull null],
+ @"geometry": geometry} mutableCopy];
+ feature[@"id"] = identifier;
+ return [feature copy];
+}
diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h
index fbc7f88559..5fb82bde5b 100644
--- a/platform/darwin/src/MGLFeature_Private.h
+++ b/platform/darwin/src/MGLFeature_Private.h
@@ -4,8 +4,33 @@
#import <mbgl/util/geo.hpp>
#import <mbgl/util/feature.hpp>
+NS_ASSUME_NONNULL_BEGIN
+
/**
Returns an array of `MGLFeature` objects converted from the given vector of
vector tile features.
*/
NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features);
+
+/**
+ Takes an `mbgl::Feature` object, an identifer, and attributes dictionary and
+ returns the feature object with converted `mbgl::FeatureIdentifier` and
+ `mbgl::PropertyMap` properties.
+ */
+mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *attributes);
+
+/**
+ Returns an `NSDictionary` representation of an `MGLFeature`.
+ */
+NS_DICTIONARY_OF(NSString *, id) *NSDictionaryFeatureForGeometry(NSDictionary *geometry, NSDictionary *attributes, id identifier);
+
+@protocol MGLFeaturePrivate <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+- (mbgl::Feature)mbglFeature;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLGeoJSONSource.mm b/platform/darwin/src/MGLGeoJSONSource.mm
index 4417788851..27f2eb8bda 100644
--- a/platform/darwin/src/MGLGeoJSONSource.mm
+++ b/platform/darwin/src/MGLGeoJSONSource.mm
@@ -115,23 +115,14 @@ NSString * const MGLGeoJSONToleranceOption = @"MGLGeoJSONOptionsClusterTolerance
source->setGeoJSON(geojson);
_features = MGLFeaturesFromMBGLFeatures(geojson);
} else {
-
- NSMutableArray *featuresArray = [NSMutableArray array];
- for (id<MGLFeature> feature in self.features) {
- [featuresArray addObject:[feature featureDictionary]];
+ mbgl::FeatureCollection featureCollection;
+ featureCollection.reserve(self.features.count);
+ for (id <MGLFeaturePrivate> feature in self.features) {
+ featureCollection.push_back([feature mbglFeature]);
}
-
- 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);
+ const auto geojson = mbgl::GeoJSON{featureCollection};
+ source->setGeoJSON(geojson);
+ _features = MGLFeaturesFromMBGLFeatures(featureCollection);
}
return std::move(source);
diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h
index 69c7295842..b33d68f867 100644
--- a/platform/darwin/src/MGLMultiPoint.h
+++ b/platform/darwin/src/MGLMultiPoint.h
@@ -6,16 +6,25 @@
NS_ASSUME_NONNULL_BEGIN
/**
- The `MGLMultiPoint` class is an abstract superclass used to define shapes
- composed of multiple points. You should not create instances of this class
- directly. Instead, you should create instances of the `MGLPolyline` or
- `MGLPolygon` classes. However, you can use the method and properties of this
- class to access information about the specific points associated with the line
- or polygon.
+ The `MGLMultiPoint` class is used to define shapes composed of multiple points.
+ This class is also the superclass of `MGLPolyline` and `MGLPolygon`. The
+ methods and properties of this class can be used to access information about
+ the specific points associated with a line or polygon.
*/
@interface MGLMultiPoint : MGLShape
/**
+ Creates and returns an `MGLMultiPoint` object from the specified set of
+ coordinates.
+
+ @param coords The array of coordinates defining the shape. The data in this
+ array is copied to the new object.
+ @param count The number of items in the `coords` array.
+ @return A new multipoint object.
+ */
++ (instancetype)multiPointWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
+
+/**
The array of coordinates associated with the shape.
This C array is a pointer to a structure inside the multipoint object,
diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm
index 17a61ed081..0090c5e35f 100644
--- a/platform/darwin/src/MGLMultiPoint.mm
+++ b/platform/darwin/src/MGLMultiPoint.mm
@@ -18,6 +18,11 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor)
MGLCoordinateBounds _bounds;
}
++ (instancetype)multiPointWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
+{
+ return [[self alloc] initWithCoordinates:coords count:count];
+}
+
- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
{
self = [super init];
@@ -141,6 +146,29 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor)
return mbgl::SymbolAnnotation({mbgl::Point<double>()});
}
+- (mbgl::Feature)featureObject
+{
+ mbgl::MultiPoint<double> multiPoint;
+ multiPoint.reserve(self.pointCount);
+ for (NSInteger i = 0; i< self.pointCount; i++)
+ {
+ multiPoint.push_back(mbgl::Point<double>(self.coordinates[i].longitude, self.coordinates[i].latitude));
+ }
+ return mbgl::Feature {multiPoint};
+}
+
+- (NSDictionary *)geoJSONDictionary
+{
+ NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.pointCount];
+ for (NSUInteger index = 0; index < self.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = self.coordinates[index];
+ [coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+
+ return @{@"type": @"MultiPoint",
+ @"coordinates": coordinates};
+}
+
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; count = %lu; bounds = %@>",
diff --git a/platform/darwin/src/MGLMultiPoint_Private.h b/platform/darwin/src/MGLMultiPoint_Private.h
index dc39172723..7bc3cae58a 100644
--- a/platform/darwin/src/MGLMultiPoint_Private.h
+++ b/platform/darwin/src/MGLMultiPoint_Private.h
@@ -3,6 +3,7 @@
#import "MGLGeometry.h"
#import <mbgl/annotation/annotation.hpp>
+#import <mbgl/util/feature.hpp>
#import <vector>
#import <CoreGraphics/CoreGraphics.h>
diff --git a/platform/darwin/src/MGLPointAnnotation.m b/platform/darwin/src/MGLPointAnnotation.mm
index 9495a2c6f8..ce8e4a2355 100644
--- a/platform/darwin/src/MGLPointAnnotation.m
+++ b/platform/darwin/src/MGLPointAnnotation.mm
@@ -1,5 +1,10 @@
#import "MGLPointAnnotation.h"
+#import "MGLShape_Private.h"
+
+#import <mbgl/util/geometry.hpp>
+
+
@implementation MGLPointAnnotation
@synthesize coordinate;
@@ -13,4 +18,17 @@
coordinate.latitude, coordinate.longitude];
}
+- (NSDictionary *)geoJSONDictionary
+{
+ return @{@"type": @"Point",
+ @"coordinates": @[@(self.coordinate.longitude), @(self.coordinate.latitude)]};
+}
+
+- (mbgl::Feature)featureObject
+{
+ mbgl::Point<double> point = { self.coordinate.longitude, self.coordinate.latitude };
+ return mbgl::Feature {point};
+}
+
@end
+
diff --git a/platform/darwin/src/MGLPolygon+MGLAdditions.h b/platform/darwin/src/MGLPolygon+MGLAdditions.h
index c9ef95b6bc..f409fb96ca 100644
--- a/platform/darwin/src/MGLPolygon+MGLAdditions.h
+++ b/platform/darwin/src/MGLPolygon+MGLAdditions.h
@@ -1,11 +1,3 @@
-//
-// MGLPolygonFeature+MGLAdditions.h
-// ios
-//
-// Created by Mapbox on 9/30/16.
-// Copyright © 2016 Mapbox. All rights reserved.
-//
-
#import <Mapbox/Mapbox.h>
@interface MGLPolygon (MGLAdditions)
diff --git a/platform/darwin/src/MGLPolygon+MGLAdditions.m b/platform/darwin/src/MGLPolygon+MGLAdditions.m
index 74fb5668d1..def4687016 100644
--- a/platform/darwin/src/MGLPolygon+MGLAdditions.m
+++ b/platform/darwin/src/MGLPolygon+MGLAdditions.m
@@ -1,19 +1,11 @@
-//
-// 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];
+ NSMutableArray *coordinates = [NSMutableArray array];
- NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *exteriorRing = [NSMutableArray array];
+ NSMutableArray *exteriorRing = [NSMutableArray array];
for (NSUInteger index = 0; index < self.pointCount; index++) {
CLLocationCoordinate2D coordinate = self.coordinates[index];
[exteriorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
@@ -21,7 +13,7 @@
[coordinates addObject:exteriorRing];
for (MGLPolygon *interiorPolygon in self.interiorPolygons) {
- NS_MUTABLE_ARRAY_OF(NS_ARRAY_OF(NSNumber *) *) *interiorRing = [NSMutableArray array];
+ NSMutableArray *interiorRing = [NSMutableArray array];
for (int index = 0; index < interiorPolygon.pointCount; index++) {
CLLocationCoordinate2D coordinate = interiorPolygon.coordinates[index];
[interiorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
@@ -29,7 +21,7 @@
[coordinates addObject:interiorRing];
}
- return coordinates;
+ return [coordinates copy];
}
@end
diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm
index b8f02b6406..eae2cfe75a 100644
--- a/platform/darwin/src/MGLPolygon.mm
+++ b/platform/darwin/src/MGLPolygon.mm
@@ -3,6 +3,8 @@
#import "MGLMultiPoint_Private.h"
#import "MGLGeometry_Private.h"
+#import "MGLPolygon+MGLAdditions.h"
+
@implementation MGLPolygon
@dynamic overlayBounds;
@@ -36,6 +38,15 @@
return result;
}
+- (mbgl::Feature)featureObject {
+ mbgl::Polygon<double> geometry;
+ geometry.push_back(self.ring);
+ for (MGLPolygon *polygon in self.interiorPolygons) {
+ geometry.push_back(polygon.ring);
+ }
+ return mbgl::Feature{geometry};
+}
+
- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
mbgl::Polygon<double> geometry;
geometry.push_back(self.ring);
@@ -51,6 +62,11 @@
return annotation;
}
+- (NSDictionary *)geoJSONDictionary {
+ return @{@"type": @"Polygon",
+ @"coordinates": self.mgl_coordinates};
+}
+
@end
@interface MGLMultiPolygon ()
@@ -87,4 +103,27 @@
return MGLLatLngBoundsFromCoordinateBounds(_overlayBounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
}
+- (mbgl::Feature)featureObject {
+ mbgl::MultiPolygon<double> multiPolygon;
+ multiPolygon.reserve(self.polygons.count);
+ for (MGLPolygon *polygon in self.polygons) {
+ mbgl::Polygon<double> geometry;
+ geometry.push_back(polygon.ring);
+ for (MGLPolygon *interiorPolygon in polygon.interiorPolygons) {
+ geometry.push_back(interiorPolygon.ring);
+ }
+ multiPolygon.push_back(geometry);
+ }
+ return mbgl::Feature {multiPolygon};
+}
+
+- (NSDictionary *)geoJSONDictionary {
+ NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.polygons.count];
+ for (MGLPolygonFeature *feature in self.polygons) {
+ [coordinates addObject: feature.mgl_coordinates];
+ }
+ return @{@"type": @"MultiPolygon",
+ @"coordinates": coordinates};
+}
+
@end
diff --git a/platform/darwin/src/MGLPolyline+MGLAdditions.h b/platform/darwin/src/MGLPolyline+MGLAdditions.h
index e1e24a8ebc..4cdbbf17f9 100644
--- a/platform/darwin/src/MGLPolyline+MGLAdditions.h
+++ b/platform/darwin/src/MGLPolyline+MGLAdditions.h
@@ -1,11 +1,3 @@
-//
-// 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)
diff --git a/platform/darwin/src/MGLPolyline+MGLAdditions.m b/platform/darwin/src/MGLPolyline+MGLAdditions.m
index e91e4fc192..d1db2c58a0 100644
--- a/platform/darwin/src/MGLPolyline+MGLAdditions.m
+++ b/platform/darwin/src/MGLPolyline+MGLAdditions.m
@@ -1,25 +1,14 @@
-//
-// 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];
-
+ NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.pointCount];
for (NSUInteger index = 0; index < self.pointCount; index++) {
CLLocationCoordinate2D coordinate = self.coordinates[index];
[coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
}
-
- return coordinates;
+ return [coordinates copy];
}
@end
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index b81147a3ba..dd2fccf53d 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -3,6 +3,8 @@
#import "MGLMultiPoint_Private.h"
#import "MGLGeometry_Private.h"
+#import "MGLPolyline+MGLAdditions.h"
+
@implementation MGLPolyline
@dynamic overlayBounds;
@@ -13,17 +15,21 @@
return [[self alloc] initWithCoordinates:coords count:count];
}
-- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
+- (mbgl::LineString<double>)lineString {
NSUInteger count = self.pointCount;
CLLocationCoordinate2D *coordinates = self.coordinates;
-
+
mbgl::LineString<double> geometry;
geometry.reserve(self.pointCount);
for (NSUInteger i = 0; i < count; i++) {
geometry.push_back(mbgl::Point<double>(coordinates[i].longitude, coordinates[i].latitude));
}
+
+ return geometry;
+}
- mbgl::LineAnnotation annotation { geometry };
+- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
+ mbgl::LineAnnotation annotation { [self lineString] };
annotation.opacity = { static_cast<float>([delegate alphaForShapeAnnotation:self]) };
annotation.color = { [delegate strokeColorForShapeAnnotation:self] };
annotation.width = { static_cast<float>([delegate lineWidthForPolylineAnnotation:self]) };
@@ -31,6 +37,15 @@
return annotation;
}
+- (mbgl::Feature)featureObject {
+ return mbgl::Feature {[self lineString]};
+}
+
+- (NSDictionary *)geoJSONDictionary {
+ return @{@"type": @"LineString",
+ @"coordinates": self.mgl_coordinates};
+}
+
@end
@interface MGLMultiPolyline ()
@@ -67,4 +82,22 @@
return MGLLatLngBoundsFromCoordinateBounds(_overlayBounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
}
+- (mbgl::Feature)featureObject {
+ mbgl::MultiLineString<double> multiLineString;
+ multiLineString.reserve(self.polylines.count);
+ for (MGLPolyline *polyline in self.polylines) {
+ multiLineString.push_back([polyline lineString]);
+ }
+ return mbgl::Feature {multiLineString};
+}
+
+- (NSDictionary *)geoJSONDictionary {
+ NSMutableArray *coordinates = [NSMutableArray array];
+ for (MGLPolylineFeature *feature in self.polylines) {
+ [coordinates addObject: feature.mgl_coordinates];
+ }
+ return @{@"type": @"MultiLineString",
+ @"coordinates": coordinates};
+}
+
@end
diff --git a/platform/darwin/src/MGLShape.m b/platform/darwin/src/MGLShape.mm
index e3d92c38c8..e3d92c38c8 100644
--- a/platform/darwin/src/MGLShape.m
+++ b/platform/darwin/src/MGLShape.mm
diff --git a/platform/darwin/src/MGLShapeCollection.m b/platform/darwin/src/MGLShapeCollection.m
index 5d42b5a51c..0f011bfd20 100644
--- a/platform/darwin/src/MGLShapeCollection.m
+++ b/platform/darwin/src/MGLShapeCollection.m
@@ -18,4 +18,18 @@
return _shapes.firstObject.coordinate;
}
+- (NSDictionary *)geoJSONDictionary {
+ return @{@"type": @"GeometryCollection",
+ @"geometries": [self geometryCollection]};
+}
+
+- (NSArray *)geometryCollection {
+ NSMutableArray *geometries = [[NSMutableArray alloc] initWithCapacity:self.shapes.count];
+ for (id shape in self.shapes) {
+ NSDictionary *geometry = [shape geoJSONDictionary];
+ [geometries addObject:geometry];
+ }
+ return [geometries copy];
+}
+
@end
diff --git a/platform/darwin/src/MGLShape_Private.h b/platform/darwin/src/MGLShape_Private.h
new file mode 100644
index 0000000000..a8ee12c207
--- /dev/null
+++ b/platform/darwin/src/MGLShape_Private.h
@@ -0,0 +1,17 @@
+#import "MGLShape.h"
+
+#import <mbgl/util/feature.hpp>
+
+@interface MGLShape (Private)
+
+/**
+ Returns an `mbgl::Feature` representation of the `MGLShape`.
+ */
+- (mbgl::Feature)featureObject;
+
+/**
+ Returns a dictionary with the GeoJSON geometry member object.
+ */
+- (NSDictionary *)geoJSONDictionary;
+
+@end
diff --git a/platform/darwin/src/NSArray+MGLAdditions.h b/platform/darwin/src/NSArray+MGLAdditions.h
new file mode 100644
index 0000000000..6871f15486
--- /dev/null
+++ b/platform/darwin/src/NSArray+MGLAdditions.h
@@ -0,0 +1,9 @@
+#import <Foundation/Foundation.h>
+
+#import <mbgl/util/feature.hpp>
+
+@interface NSArray (MGLAdditions)
+
+- (std::vector<mbgl::Value>)mgl_vector;
+
+@end
diff --git a/platform/darwin/src/NSArray+MGLAdditions.mm b/platform/darwin/src/NSArray+MGLAdditions.mm
new file mode 100644
index 0000000000..976eda704f
--- /dev/null
+++ b/platform/darwin/src/NSArray+MGLAdditions.mm
@@ -0,0 +1,26 @@
+#import "NSArray+MGLAdditions.h"
+
+#import "NSDictionary+MGLAdditions.h"
+#import "NSExpression+MGLAdditions.mm"
+
+@implementation NSArray (MGLAdditions)
+
+- (std::vector<mbgl::Value>)mgl_vector {
+ std::vector<mbgl::Value> vector;
+ vector.reserve(self.count);
+ for (id value in self) {
+ if ([value isKindOfClass:[NSArray class]]) {
+ std::vector<mbgl::Value> innerVector = [value mgl_vector];
+ vector.push_back(innerVector);
+ } else if ([value isKindOfClass:[NSDictionary class]]) {
+ mbgl::PropertyMap propertyMap = [value mgl_propertyMap];
+ vector.push_back(propertyMap);
+ } else {
+ NSExpression *expression = [NSExpression expressionForConstantValue:value];
+ vector.push_back([expression mgl_filterValue]);
+ }
+ }
+ return vector;
+}
+
+@end
diff --git a/platform/darwin/src/NSDictionary+MGLAdditions.h b/platform/darwin/src/NSDictionary+MGLAdditions.h
new file mode 100644
index 0000000000..556f21992b
--- /dev/null
+++ b/platform/darwin/src/NSDictionary+MGLAdditions.h
@@ -0,0 +1,13 @@
+#import <Foundation/Foundation.h>
+
+#import <mbgl/util/feature.hpp>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NSDictionary (MGLAdditions)
+
+- (mbgl::PropertyMap)mgl_propertyMap;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSDictionary+MGLAdditions.mm b/platform/darwin/src/NSDictionary+MGLAdditions.mm
new file mode 100644
index 0000000000..1023e91a48
--- /dev/null
+++ b/platform/darwin/src/NSDictionary+MGLAdditions.mm
@@ -0,0 +1,24 @@
+#import "NSDictionary+MGLAdditions.h"
+
+#import "NSExpression+MGLAdditions.mm"
+#import "NSArray+MGLAdditions.h"
+
+@implementation NSDictionary (MGLAdditions)
+
+- (mbgl::PropertyMap)mgl_propertyMap {
+ mbgl::PropertyMap propertyMap;
+ for (NSString *key in self.allKeys) {
+ if ([self[key] isKindOfClass:[NSDictionary class]]) {
+ propertyMap[[key UTF8String]] = [self[key] mgl_propertyMap];
+ } else if ([self[key] isKindOfClass:[NSArray class]]) {
+ NSArray *array = self[key];
+ propertyMap[[key UTF8String]] = [array mgl_vector];
+ } else {
+ NSExpression *expression = [NSExpression expressionForConstantValue:self[key]];
+ propertyMap[[key UTF8String]] = [expression mgl_filterValue];
+ }
+ }
+ return propertyMap;
+}
+
+@end
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.h b/platform/darwin/src/NSExpression+MGLAdditions.h
index 4e8c5ee071..6d0fff5760 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.h
+++ b/platform/darwin/src/NSExpression+MGLAdditions.h
@@ -5,7 +5,7 @@
@interface NSExpression (MGLAdditions)
- (mbgl::Value)mgl_filterValue;
-
- (std::vector<mbgl::Value>)mgl_filterValues;
+- (mbgl::FeatureIdentifier)mgl_featureIdentifier;
@end
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index 52a0b9bd88..392a6d7f5b 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -61,4 +61,30 @@
return { };
}
+- (mbgl::FeatureIdentifier)mgl_featureIdentifier
+{
+ id value = self.constantValue;
+ mbgl::Value mbglValue = [self mgl_filterValue];
+
+ if ([value isKindOfClass:NSString.class]) {
+ return mbglValue.get<std::string>();
+ } else if ([value isKindOfClass:NSNumber.class]) {
+ NSNumber *number = (NSNumber *)value;
+ if ((strcmp([number objCType], @encode(char)) == 0) ||
+ (strcmp([number objCType], @encode(BOOL)) == 0)) {
+ return mbglValue.get<bool>();
+ } else if ( strcmp([number objCType], @encode(double)) == 0 ||
+ strcmp([number objCType], @encode(float)) == 0) {
+ return mbglValue.get<double>();
+ } else if ([number compare:@(0)] == NSOrderedDescending ||
+ [number compare:@(0)] == NSOrderedSame) {
+ return mbglValue.get<uint64_t>();
+ } else if ([number compare:@(0)] == NSOrderedAscending) {
+ return mbglValue.get<int64_t>();
+ }
+ }
+
+ return {};
+}
+
@end
diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm
index 1b1722f172..18c3fd16c2 100644
--- a/platform/darwin/test/MGLFeatureTests.mm
+++ b/platform/darwin/test/MGLFeatureTests.mm
@@ -158,4 +158,169 @@
XCTAssertEqual(string, shape.attributes[@"string"]);
}
+- (void)testPointFeatureGeoJSONDictionary {
+ MGLPointFeature<MGLFeaturePrivate> *pointFeature = (MGLPointFeature<MGLFeaturePrivate> *)[[MGLPointFeature alloc] init];
+ CLLocationCoordinate2D coordinate = { 10, 10 };
+ pointFeature.coordinate = coordinate;
+
+ // A GeoJSON feature
+ // when there are no identifier or properties
+ NSDictionary *geoJSONFeature = [pointFeature geoJSONDictionary];
+
+ // it has the correct type
+ XCTAssertEqualObjects(geoJSONFeature[@"type"], @"Feature");
+ // it has the correct geometry
+ NSDictionary *expectedGeometry = @{@"type": @"Point",
+ @"coordinates": @[@(coordinate.longitude), @(coordinate.latitude)]};
+ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
+ // it has no "id" key (or value)
+ XCTAssertNil(geoJSONFeature[@"id"]);
+ // it has a null representation of the properties object
+ XCTAssertEqualObjects(geoJSONFeature[@"properties"], [NSNull null]);
+
+ // when there is a string identifier
+ pointFeature.identifier = @"string-id";
+
+ // it has the identifier in the result
+ geoJSONFeature = [pointFeature geoJSONDictionary];
+ XCTAssertEqualObjects(geoJSONFeature[@"id"], pointFeature.identifier);
+
+ // when there are properties
+ pointFeature.attributes = @{@"name": @"name-value"};
+
+ // it has the properties value in the result
+ geoJSONFeature = [pointFeature geoJSONDictionary];
+ XCTAssertEqualObjects(geoJSONFeature[@"properties"], pointFeature.attributes);
+}
+
+- (void)testPolylineFeatureGeoJSONDictionary {
+ CLLocationCoordinate2D coord1 = { 0, 0 };
+ CLLocationCoordinate2D coord2 = { 10, 10 };
+ CLLocationCoordinate2D coords[] = { coord1, coord2 };
+ MGLPolylineFeature *polyLineFeature = [MGLPolylineFeature polylineWithCoordinates:coords count:2];
+
+ // A GeoJSON feature
+ NSDictionary *geoJSONFeature = [polyLineFeature geoJSONDictionary];
+
+ // it has the correct geometry
+ NSDictionary *expectedGeometry = @{@"type": @"LineString",
+ @"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)]]};
+ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
+}
+
+- (void)testPolygonFeatureGeoJSONDictionary {
+ CLLocationCoordinate2D coord1 = { 0, 0 };
+ CLLocationCoordinate2D coord2 = { 10, 10 };
+ CLLocationCoordinate2D coord3 = { 0, 0 };
+ CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
+ MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coords count:3];
+
+ // A GeoJSON feature
+ NSDictionary *geoJSONFeature = [polygonFeature geoJSONDictionary];
+
+ // it has the correct geometry
+ NSDictionary *expectedGeometry = @{@"type": @"Polygon",
+ @"coordinates": @[@[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)],
+ @[@(coord3.longitude), @(coord3.latitude)]]]};
+ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
+}
+
+- (void)testMultiPointFeatureGeoJSONDictionary {
+ CLLocationCoordinate2D coord1 = { 0, 0 };
+ CLLocationCoordinate2D coord2 = { 10, 10 };
+ CLLocationCoordinate2D coord3 = { 0, 0 };
+ CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
+ MGLMultiPointFeature *multiPointFeature = [MGLMultiPointFeature multiPointWithCoordinates:coords count:3];
+
+ // A GeoJSON feature
+ NSDictionary *geoJSONFeature = [multiPointFeature geoJSONDictionary];
+
+ // it has the correct geometry
+ NSDictionary *expectedGeometry = @{@"type": @"MultiPoint",
+ @"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)],
+ @[@(coord3.longitude), @(coord3.latitude)]]};
+ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
+}
+
+- (void)testMultiPolylineFeatureGeoJSONDictionary {
+ CLLocationCoordinate2D coord1 = { 0, 0 };
+ CLLocationCoordinate2D coord2 = { 10, 10 };
+ CLLocationCoordinate2D coord3 = { 0, 0 };
+ CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
+
+ MGLPolyline *polyLine1 = [MGLPolyline polylineWithCoordinates:coords count:3];
+ MGLPolyline *polyLine2 = [MGLPolyline polylineWithCoordinates:coords count:3];
+
+ MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[polyLine1, polyLine2]];
+
+ // A GeoJSON feature
+ NSDictionary *geoJSONFeature = [multiPolylineFeature geoJSONDictionary];
+
+ // it has the correct geometry
+ NSDictionary *expectedGeometry = @{@"type": @"MultiLineString",
+ @"coordinates": @[@[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)],
+ @[@(coord3.longitude), @(coord3.latitude)]],
+ @[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)],
+ @[@(coord3.longitude), @(coord3.latitude)]]]};
+ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
+}
+
+- (void)testMultiPolygonFeatureGeoJSONDictionary {
+ CLLocationCoordinate2D coord1 = { 0, 0 };
+ CLLocationCoordinate2D coord2 = { 10, 10 };
+ CLLocationCoordinate2D coord3 = { 0, 0 };
+ CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
+
+ MGLPolygon *polygon1 = [MGLPolygon polygonWithCoordinates:coords count:3];
+ MGLPolygon *polygon2 = [MGLPolygon polygonWithCoordinates:coords count:3];
+
+ MGLMultiPolygonFeature *multiPolylineFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:@[polygon1, polygon2]];
+
+ // A GeoJSON feature
+ NSDictionary *geoJSONFeature = [multiPolylineFeature geoJSONDictionary];
+
+ // it has the correct geometry
+ NSDictionary *expectedGeometry = @{@"type": @"MultiPolygon",
+ @"coordinates": @[
+ @[@[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)],
+ @[@(coord3.longitude), @(coord3.latitude)]]],
+ @[@[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)],
+ @[@(coord3.longitude), @(coord3.latitude)]]]]};
+ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
+}
+
+- (void)testShapeCollectionFeatureGeoJSONDictionary {
+ MGLPointAnnotation *pointFeature = [[MGLPointAnnotation alloc] init];
+ CLLocationCoordinate2D pointCoordinate = { 10, 10 };
+ pointFeature.coordinate = pointCoordinate;
+
+ CLLocationCoordinate2D coord1 = { 0, 0 };
+ CLLocationCoordinate2D coord2 = { 10, 10 };
+ CLLocationCoordinate2D coords[] = { coord1, coord2 };
+ MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coords count:2];
+
+ MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[pointFeature,
+ polyline]];
+ // A GeoJSON feature
+ NSDictionary *geoJSONFeature = [shapeCollectionFeature geoJSONDictionary];
+
+ // it has the correct geometry
+ NSDictionary *expectedGeometry = @{@"type": @"GeometryCollection",
+ @"geometries": @[
+ @{@"type": @"Point",
+ @"coordinates": @[@(pointCoordinate.longitude), @(pointCoordinate.latitude)]},
+ @{@"type": @"LineString",
+ @"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)]]}
+ ]};
+ XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
+}
+
@end