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

Commit

Permalink
[ios, macos] MGLGeoJSONSource can now be initialized with any shape
Browse files Browse the repository at this point in the history
  • Loading branch information
frederoni committed Dec 6, 2016
1 parent 9456bec commit fdd3c40
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 131 deletions.
75 changes: 55 additions & 20 deletions platform/darwin/src/MGLFeature.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "NSExpression+MGLAdditions.h"

#import <mbgl/util/geometry.hpp>
#import <mbgl/style/conversion/geojson.hpp>
#import <mapbox/geometry/feature.hpp>

@interface MGLPointFeature () <MGLFeaturePrivate>
Expand All @@ -33,7 +34,7 @@ - (NSDictionary *)geoJSONDictionary {
}

- (mbgl::Feature)mbglFeature {
return mbglFeature([self featureObject], identifier, self.attributes);
return mbglFeature({[self geometryObject]}, identifier, self.attributes);
}

@end
Expand All @@ -55,7 +56,7 @@ - (NSDictionary *)geoJSONDictionary {
}

- (mbgl::Feature)mbglFeature {
return mbglFeature([self featureObject], identifier, self.attributes);
return mbglFeature({[self geometryObject]}, identifier, self.attributes);
}

@end
Expand All @@ -77,7 +78,7 @@ - (NSDictionary *)geoJSONDictionary {
}

- (mbgl::Feature)mbglFeature {
return mbglFeature([self featureObject], identifier, self.attributes);
return mbglFeature({[self geometryObject]}, identifier, self.attributes);
}

@end
Expand All @@ -99,7 +100,7 @@ - (NSDictionary *)geoJSONDictionary {
}

- (mbgl::Feature)mbglFeature {
return mbglFeature([self featureObject], identifier, self.attributes);
return mbglFeature({[self geometryObject]}, identifier, self.attributes);
}

@end
Expand All @@ -121,7 +122,7 @@ - (NSDictionary *)geoJSONDictionary {
}

- (mbgl::Feature)mbglFeature {
return mbglFeature([self featureObject], identifier, self.attributes);
return mbglFeature({[self geometryObject]}, identifier, self.attributes);
}

@end
Expand All @@ -143,7 +144,7 @@ - (NSDictionary *)geoJSONDictionary {
}

- (mbgl::Feature)mbglFeature {
return mbglFeature([self featureObject], identifier, self.attributes);
return mbglFeature({[self geometryObject]}, identifier, self.attributes);
}

@end
Expand Down Expand Up @@ -266,27 +267,61 @@ static CLLocationCoordinate2D toLocationCoordinate2D(const mbgl::Point<T> &point
}
};

template <typename T>
class GeoJSONEvaluator {
public:
MGLShape <MGLFeaturePrivate> * operator()(const mbgl::Geometry<T> &geometry) const {
GeometryEvaluator<T> evaluator;
MGLShape <MGLFeaturePrivate> *shape = mapbox::geometry::geometry<T>::visit(geometry, evaluator);
return shape;
}

MGLShape <MGLFeaturePrivate> * operator()(const mbgl::Feature &feature) const {
GeometryEvaluator<T> evaluator;
MGLShape <MGLFeaturePrivate> *shape = mapbox::geometry::geometry<T>::visit(feature.geometry, evaluator);
return shape;
}

MGLShape <MGLFeaturePrivate> * operator()(const mbgl::FeatureCollection &collection) const {
NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()];
for (const auto &feature : collection) {
[shapes addObject:MGLFeatureFromMBGLFeature(feature)];
}
return [MGLShapeCollection<MGLFeaturePrivate> shapeCollectionWithShapes:shapes];
}
};

NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features) {
NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:features.size()];
for (const auto &feature : features) {
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()];
for (auto &pair : feature.properties) {
auto &value = pair.second;
ValueEvaluator evaluator;
attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator);
}

GeometryEvaluator<double> evaluator;
MGLShape <MGLFeaturePrivate> *shape = mapbox::geometry::geometry<double>::visit(feature.geometry, evaluator);
if (feature.id) {
shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, ValueEvaluator());
}
shape.attributes = attributes;
[shapes addObject:shape];
[shapes addObject:MGLFeatureFromMBGLFeature(feature)];
}
return shapes;
}

id <MGLFeature> MGLFeatureFromMBGLFeature(const mbgl::Feature &feature) {
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()];
for (auto &pair : feature.properties) {
auto &value = pair.second;
ValueEvaluator evaluator;
attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator);
}
GeometryEvaluator<double> evaluator;
MGLShape <MGLFeaturePrivate> *shape = mapbox::geometry::geometry<double>::visit(feature.geometry, evaluator);
if (feature.id) {
shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, ValueEvaluator());
}
shape.attributes = attributes;

return shape;
}

MGLShape* MGLShapeFromGeoJSON(const mapbox::geojson::geojson &geojson) {
GeoJSONEvaluator<double> evaluator;
MGLShape *shape = mapbox::geojson::geojson::visit(geojson, evaluator);
return shape;
}

mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *attributes)
{
if (identifier) {
Expand Down
12 changes: 12 additions & 0 deletions platform/darwin/src/MGLFeature_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#import <mbgl/util/geo.hpp>
#import <mbgl/util/feature.hpp>
#import <mbgl/style/conversion/geojson.hpp>

NS_ASSUME_NONNULL_BEGIN

Expand All @@ -12,6 +13,17 @@ NS_ASSUME_NONNULL_BEGIN
*/
NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features);

/**
Returns an `MGLFeature` object converted from the given mbgl::Feature
*/
id <MGLFeature> MGLFeatureFromMBGLFeature(const mbgl::Feature &feature);

/**
Returns an `MGLShape` representing the given geojson. The shape can be
a feature, a collection of features, or a geometry.
*/
MGLShape* MGLShapeFromGeoJSON(const mapbox::geojson::geojson &geojson);

/**
Takes an `mbgl::Feature` object, an identifer, and attributes dictionary and
returns the feature object with converted `mbgl::FeatureIdentifier` and
Expand Down
13 changes: 7 additions & 6 deletions platform/darwin/src/MGLGeoJSONSource.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "MGLSource.h"

#import "MGLTypes.h"
#import "MGLShape.h"

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -93,28 +94,29 @@ extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationToleranc
- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER;

/**
Returns a GeoJSON source with an identifier, features dictionary, and dictionary
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 shape A concrete subclass of `MGLShape`
@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(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithIdentifier:(NSString *)identifier shape:(nullable MGLShape *)shape options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER;

#pragma mark Accessing a Source’s Content

/**
The contents of the source.
The contents of the source. A shape can represent a GeoJSON geometry, a feature,
or a collection of features.
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]`.
*/
@property (nonatomic, nullable) NS_ARRAY_OF(id <MGLFeature>) *features;
@property (nonatomic, nullable) MGLShape *shape;

/**
A GeoJSON representation of the contents of the source.
Expand All @@ -138,7 +140,6 @@ extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationToleranc
*/
@property (nonatomic, nullable) NSURL *URL;


@end

NS_ASSUME_NONNULL_END
43 changes: 17 additions & 26 deletions platform/darwin/src/MGLGeoJSONSource.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import "MGLMapView_Private.h"
#import "MGLSource_Private.h"
#import "MGLFeature_Private.h"
#import "MGLShape_Private.h"

#import "NSURL+MGLAdditions.h"

Expand Down Expand Up @@ -49,13 +50,13 @@ - (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 {
- (instancetype)initWithIdentifier:(NSString *)identifier shape:(nullable MGLShape *)shape options:(NSDictionary<MGLGeoJSONSourceOption,id> *)options
{
if (self = [super initWithIdentifier:identifier]) {
_features = features;
_shape = shape;
_options = options;
[self commonInit];
}

return self;
}

Expand Down Expand Up @@ -85,21 +86,15 @@ - (void)commonInit
if (self.URL) {
NSURL *url = self.URL.mgl_URLByStandardizingScheme;
source->setURL(url.absoluteString.UTF8String);
_features = nil;
_shape = nil;
} 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>();
const auto geojson = mapbox::geojson::parse(string.UTF8String);
source->setGeoJSON(geojson);
_features = MGLFeaturesFromMBGLFeatures(geojson);
_shape = MGLShapeFromGeoJSON(geojson);
} else {
mbgl::FeatureCollection featureCollection;
featureCollection.reserve(self.features.count);
for (id <MGLFeaturePrivate> feature in self.features) {
featureCollection.push_back([feature mbglFeature]);
}
const auto geojson = mbgl::GeoJSON{featureCollection};
const auto geojson = mbgl::GeoJSON{self.shape.geometryObject};
source->setGeoJSON(geojson);
_features = MGLFeaturesFromMBGLFeatures(featureCollection);
}

_pendingSource = std::move(source);
Expand Down Expand Up @@ -161,10 +156,10 @@ - (void)setGeoJSONData:(NSData *)geoJSONData
}

NSString *string = [[NSString alloc] initWithData:_geoJSONData encoding:NSUTF8StringEncoding];
const auto geojson = mapbox::geojson::parse(string.UTF8String).get<mapbox::geojson::feature_collection>();
const auto geojson = mapbox::geojson::parse(string.UTF8String);
self.rawSource->setGeoJSON(geojson);

_features = MGLFeaturesFromMBGLFeatures(geojson);
_shape = MGLShapeFromGeoJSON(geojson);
}

- (void)setURL:(NSURL *)URL
Expand All @@ -180,28 +175,24 @@ - (void)setURL:(NSURL *)URL
self.rawSource->setURL(url.absoluteString.UTF8String);
}

- (void)setFeatures:(NSArray *)features

- (void)setShape:(MGLShape *)shape
{
if (self.rawSource == NULL)
{
[self commonInit];
}

mbgl::FeatureCollection featureCollection;
featureCollection.reserve(features.count);
for (id <MGLFeaturePrivate> feature in features) {
featureCollection.push_back([feature mbglFeature]);
}
const auto geojson = mbgl::GeoJSON{featureCollection};

const auto geojson = mbgl::GeoJSON{shape.geometryObject};
self.rawSource->setGeoJSON(geojson);

_features = MGLFeaturesFromMBGLFeatures(featureCollection);
_shape = shape;
}

- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; geoJSONData = %@; features = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.geoJSONData, self.features];
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; geoJSONData = %@; shape = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.geoJSONData, self.shape];
}

@end
4 changes: 2 additions & 2 deletions platform/darwin/src/MGLPointAnnotation.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ - (NSDictionary *)geoJSONDictionary
@"coordinates": @[@(self.coordinate.longitude), @(self.coordinate.latitude)]};
}

- (mbgl::Feature)featureObject
- (mbgl::Geometry<double>)geometryObject
{
mbgl::Point<double> point = { self.coordinate.longitude, self.coordinate.latitude };
return mbgl::Feature {point};
return point;
}

@end
Expand Down
4 changes: 2 additions & 2 deletions platform/darwin/src/MGLPointCollection.mm
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds
return MGLLatLngBoundsFromCoordinateBounds(_bounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
}

- (mbgl::Feature)featureObject
- (mbgl::Geometry<double>)geometryObject
{
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};
return multiPoint;
}

- (NSDictionary *)geoJSONDictionary
Expand Down
21 changes: 10 additions & 11 deletions platform/darwin/src/MGLPolygon.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,22 @@ - (instancetype)initWithCoordinates:(const CLLocationCoordinate2D *)coords count
return result;
}

- (mbgl::Feature)featureObject {
- (mbgl::Polygon<double>)polygon {
mbgl::Polygon<double> geometry;
geometry.push_back(self.ring);
for (MGLPolygon *polygon in self.interiorPolygons) {
geometry.push_back(polygon.ring);
}
return mbgl::Feature{geometry};
return geometry;
}

- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
mbgl::Polygon<double> geometry;
geometry.push_back(self.ring);
for (MGLPolygon *polygon in self.interiorPolygons) {
geometry.push_back(polygon.ring);
}
- (mbgl::Geometry<double>)geometryObject {
return [self polygon];
}

mbgl::FillAnnotation annotation { geometry };
- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {

mbgl::FillAnnotation annotation { [self polygon] };
annotation.opacity = { static_cast<float>([delegate alphaForShapeAnnotation:self]) };
annotation.outlineColor = { [delegate strokeColorForShapeAnnotation:self] };
annotation.color = { [delegate fillColorForPolygonAnnotation:self] };
Expand Down Expand Up @@ -103,7 +102,7 @@ - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
return MGLLatLngBoundsFromCoordinateBounds(_overlayBounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
}

- (mbgl::Feature)featureObject {
- (mbgl::Geometry<double>)geometryObject {
mbgl::MultiPolygon<double> multiPolygon;
multiPolygon.reserve(self.polygons.count);
for (MGLPolygon *polygon in self.polygons) {
Expand All @@ -114,7 +113,7 @@ - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
}
multiPolygon.push_back(geometry);
}
return mbgl::Feature {multiPolygon};
return multiPolygon;
}

- (NSDictionary *)geoJSONDictionary {
Expand Down
Loading

0 comments on commit fdd3c40

Please sign in to comment.