Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios, macos] Add feature initializer
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
ituaijagbone authored and boundsj committed Oct 7, 2016
1 parent 740c995 commit 113c1dd
Show file tree
Hide file tree
Showing 11 changed files with 527 additions and 11 deletions.
9 changes: 9 additions & 0 deletions platform/darwin/src/MGLFeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
115 changes: 114 additions & 1 deletion platform/darwin/src/MGLFeature.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -28,6 +29,17 @@ - (id)attributeForKey:(NSString *)key {
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>
Expand All @@ -37,11 +49,22 @@ @implementation MGLPolylineFeature

@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>
Expand All @@ -56,6 +79,16 @@ - (id)attributeForKey:(NSString *)key {
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>
Expand All @@ -70,6 +103,23 @@ - (id)attributeForKey:(NSString *)key {
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>
Expand All @@ -84,6 +134,21 @@ - (id)attributeForKey:(NSString *)key {
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>
Expand All @@ -98,6 +163,21 @@ - (id)attributeForKey:(NSString *)key {
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>
Expand All @@ -108,10 +188,43 @@ @implementation MGLShapeCollectionFeature
@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


Expand Down
31 changes: 23 additions & 8 deletions platform/darwin/src/MGLGeoJSONSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]`.
*/
Expand All @@ -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
29 changes: 28 additions & 1 deletion platform/darwin/src/MGLGeoJSONSource.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ - (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url optio
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();
Expand Down Expand Up @@ -100,11 +109,29 @@ - (void)validateValue:(id)value
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);
Expand Down
15 changes: 15 additions & 0 deletions platform/darwin/src/MGLPolygon+MGLAdditions.h
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions platform/darwin/src/MGLPolygon+MGLAdditions.m
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions platform/darwin/src/MGLPolyline+MGLAdditions.h
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 113c1dd

Please sign in to comment.