summaryrefslogtreecommitdiff
path: root/platform/darwin/src/MGLFeature.mm
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-05-24 23:27:19 -0700
committerMinh Nguyễn <mxn@1ec5.org>2016-05-27 21:42:38 -0700
commitff0cc1c9ef4b1a8e2f6014fd9ef8cd7a3800e5f0 (patch)
tree492225217f9bd8a05192b7e36e36f9b1823dab64 /platform/darwin/src/MGLFeature.mm
parentc6683ee1d3baebf46f3397e7ed2e44e8a23dc8ed (diff)
downloadqtlocation-mapboxgl-ff0cc1c9ef4b1a8e2f6014fd9ef8cd7a3800e5f0.tar.gz
[ios, osx] Streamlined conversion to MGLFeature
Made writability of MGLFeature properties private, to avoid having to awkwardly explain that changes to the properties don’t change the map (maybe someday they will). This allows the identifier and attributes to be set in only one place, avoiding copy-pasta.
Diffstat (limited to 'platform/darwin/src/MGLFeature.mm')
-rw-r--r--platform/darwin/src/MGLFeature.mm263
1 files changed, 146 insertions, 117 deletions
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
index 68c57a193a..3e60b2061b 100644
--- a/platform/darwin/src/MGLFeature.mm
+++ b/platform/darwin/src/MGLFeature.mm
@@ -6,10 +6,116 @@
#import "MGLMultiPoint_Private.h"
+@protocol MGLFeaturePrivate <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+@interface MGLPointFeature () <MGLFeaturePrivate>
+@end
+
+@implementation MGLPointFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLPolylineFeature () <MGLFeaturePrivate>
+@end
+
+@implementation MGLPolylineFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLPolygonFeature () <MGLFeaturePrivate>
+@end
+
+@implementation MGLPolygonFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLMultiPointFeature () <MGLFeaturePrivate>
+@end
+
+@implementation MGLMultiPointFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLMultiPolylineFeature () <MGLFeaturePrivate>
+@end
+
+@implementation MGLMultiPolylineFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLMultiPolygonFeature () <MGLFeaturePrivate>
+@end
+
+@implementation MGLMultiPolygonFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@interface MGLShapeCollectionFeature () <MGLFeaturePrivate>
+@end
+
+@implementation MGLShapeCollectionFeature
+
+@synthesize identifier;
+@synthesize attributes;
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+/**
+ Recursively transforms a C++ type into the corresponding Foundation type.
+ */
class PropertyValueEvaluator {
public:
- PropertyValueEvaluator() {}
-
id operator()(const std::nullptr_t &) const {
return [NSNull null];
}
@@ -37,10 +143,9 @@ public:
id operator()(const std::vector<mbgl::Value> &values) const {
std::vector<id> objects;
objects.reserve(values.size());
- std::transform(values.begin(), values.end(), std::back_inserter(objects), ^id (const mbgl::Value &value) {
- PropertyValueEvaluator evaluator;
- return mbgl::Value::visit(value, evaluator);
- });
+ for (const auto &v : values) {
+ objects.push_back(mbgl::Value::visit(v, *this));
+ }
return [NSArray arrayWithObjects:&objects[0] count:objects.size()];
}
@@ -51,49 +156,34 @@ public:
objects.reserve(items.size());
for (auto &item : items) {
keys.push_back(@(item.first.c_str()));
- PropertyValueEvaluator evaluator;
- objects.push_back(mbgl::Value::visit(item.second, evaluator));
+ objects.push_back(mbgl::Value::visit(item.second, *this));
}
return [NSDictionary dictionaryWithObjects:&objects[0] forKeys:&keys[0] count:keys.size()];
}
};
+/**
+ Transforms an `mbgl::geometry::geometry` type into an instance of the
+ corresponding Objective-C geometry class.
+ */
template <typename T>
class GeometryEvaluator {
public:
- GeometryEvaluator()
- : attributes([NSMutableDictionary dictionary]) {}
-
- GeometryEvaluator(const mbgl::Feature &feature)
- : tag(feature.id ? @(*feature.id) : nullptr),
- attributes([NSMutableDictionary dictionaryWithCapacity:feature.properties.size()]) {
- for (auto &pair : feature.properties) {
- auto &value = pair.second;
- PropertyValueEvaluator evaluator;
- attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator);
- }
- }
-
- MGLShape <MGLFeature> * operator()(const mapbox::geometry::point<T> &geometry) const {
+ MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::point<T> &geometry) const {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
feature.coordinate = coordinateFromPoint(geometry);
- feature.identifier = tag;
- feature.attributes = attributes;
return feature;
}
- MGLShape <MGLFeature> * operator()(const mapbox::geometry::line_string<T> &geometry) const {
+ MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::line_string<T> &geometry) const {
std::vector<CLLocationCoordinate2D> coordinates;
coordinates.reserve(geometry.size());
std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPoint);
- MGLPolylineFeature *feature = [[MGLPolylineFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [[MGLPolylineFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
}
- MGLShape <MGLFeature> * operator()(const mapbox::geometry::polygon<T> &geometry) const {
+ MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::polygon<T> &geometry) const {
// TODO: MGLPolygon doesn’t support holes, so what to do?
auto &linearRing = geometry.front();
@@ -101,24 +191,18 @@ public:
coordinates.reserve(linearRing.size());
std::transform(linearRing.begin(), linearRing.end(), std::back_inserter(coordinates), coordinateFromPoint);
- MGLPolygonFeature *feature = [[MGLPolygonFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [[MGLPolygonFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
}
- MGLShape <MGLFeature> * operator()(const mapbox::geometry::multi_point<T> &geometry) const {
+ MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::multi_point<T> &geometry) const {
std::vector<CLLocationCoordinate2D> coordinates;
coordinates.reserve(geometry.size());
std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPoint);
- MGLMultiPointFeature *feature = [[MGLMultiPointFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [[MGLMultiPointFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
}
- MGLShape <MGLFeature> * operator()(const mapbox::geometry::multi_line_string<T> &geometry) const {
+ MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::multi_line_string<T> &geometry) const {
NSMutableArray *polylines = [NSMutableArray arrayWithCapacity:geometry.size()];
for (auto &lineString : geometry) {
std::vector<CLLocationCoordinate2D> coordinates;
@@ -129,13 +213,10 @@ public:
[polylines addObject:polyline];
}
- MGLMultiPolylineFeature *feature = [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
}
- MGLShape <MGLFeature> * operator()(const mapbox::geometry::multi_polygon<T> &geometry) const {
+ MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::multi_polygon<T> &geometry) const {
NSMutableArray *polygons = [NSMutableArray arrayWithCapacity:geometry.size()];
for (auto &polygon : geometry) {
// TODO: MGLPolygon doesn’t support holes, so what to do?
@@ -149,29 +230,21 @@ public:
[polygons addObject:polygonObject];
}
- MGLMultiPolygonFeature *feature = [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
}
- MGLShape <MGLFeature> * operator()(const mapbox::geometry::geometry_collection<T> &collection) const {
+ MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::geometry_collection<T> &collection) const {
NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()];
for (auto &geometry : collection) {
+ // This is very much like the transformation that happens in MGLFeaturesFromMBGLFeatures(), but these are raw geometries with no associated feature IDs or attributes.
GeometryEvaluator<T> evaluator;
- id <MGLFeature> feature = mapbox::geometry::geometry<T>::visit(geometry, evaluator);
- [shapes addObject:feature];
+ MGLShape <MGLFeaturePrivate> *shape = mapbox::geometry::geometry<T>::visit(geometry, evaluator);
+ [shapes addObject:shape];
}
- MGLShapeCollectionFeature *feature = [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes];
- feature.identifier = tag;
- feature.attributes = attributes;
- return feature;
+ return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes];
}
private:
- NSNumber *tag = nullptr;
- NS_MUTABLE_DICTIONARY_OF(NSString *, id) *attributes;
-
static CLLocationCoordinate2D coordinateFromPoint(const mapbox::geometry::point<T> &point) {
return CLLocationCoordinate2DMake(point.y, point.x);
}
@@ -181,64 +254,20 @@ NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vec
std::vector<MGLShape <MGLFeature> *> shapes;
shapes.reserve(features.size());
std::transform(features.begin(), features.end(), std::back_inserter(shapes), ^MGLShape <MGLFeature> * (const mbgl::Feature &feature) {
- GeometryEvaluator<double> evaluator(feature);
- return mapbox::geometry::geometry<double>::visit(feature.geometry, evaluator);
+ NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()];
+ for (auto &pair : feature.properties) {
+ auto &value = pair.second;
+ PropertyValueEvaluator 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 = @(*feature.id);
+ }
+ shape.attributes = attributes;
+ return shape;
});
return [NSArray arrayWithObjects:&shapes[0] count:shapes.size()];
}
-
-@implementation MGLPointFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLPolylineFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLPolygonFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLMultiPointFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLMultiPolylineFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLMultiPolygonFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end
-
-@implementation MGLShapeCollectionFeature
-
-- (id)attributeForKey:(NSString *)key {
- return self.attributes[key];
-}
-
-@end