diff options
Diffstat (limited to 'platform/darwin/src/MGLFeature.mm')
-rw-r--r-- | platform/darwin/src/MGLFeature.mm | 542 |
1 files changed, 0 insertions, 542 deletions
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm deleted file mode 100644 index df6b1bffea..0000000000 --- a/platform/darwin/src/MGLFeature.mm +++ /dev/null @@ -1,542 +0,0 @@ -#import "MGLFoundation_Private.h" -#import "MGLFeature_Private.h" -#import "MGLCluster.h" - -#import "MGLPointAnnotation.h" -#import "MGLPolyline.h" -#import "MGLPolygon.h" -#import "MGLValueEvaluator.h" - -#import "MGLShape_Private.h" -#import "MGLPointCollection_Private.h" -#import "MGLPolyline_Private.h" -#import "MGLPolygon_Private.h" - -#import "NSDictionary+MGLAdditions.h" -#import "NSArray+MGLAdditions.h" -#import "NSExpression+MGLPrivateAdditions.h" -#import "MGLLoggingConfiguration_Private.h" - -#import <mbgl/util/geometry.hpp> -#import <mbgl/style/conversion/geojson.hpp> -#import <mapbox/feature.hpp> - -// Cluster constants -static NSString * const MGLClusterIdentifierKey = @"cluster_id"; -static NSString * const MGLClusterCountKey = @"point_count"; -const NSUInteger MGLClusterIdentifierInvalid = NSUIntegerMax; - -@interface MGLEmptyFeature () -@end - -@implementation MGLEmptyFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - MGLLogDebug(@"Retrieving attributeForKey: %@", key); - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - return mbglFeature({[self geometryObject]}, identifier, self.attributes); -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@, attributes = %@>", - NSStringFromClass([self class]), (void *)self, - self.identifier ? [NSString stringWithFormat:@"\"%@\"", self.identifier] : self.identifier, - self.attributes.count ? self.attributes : @"none"]; -} - -@end - -@interface MGLPointFeature () -@end - -@implementation MGLPointFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - MGLLogDebug(@"Retrieving attributeForKey: %@", key); - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - return mbglFeature({[self geometryObject]}, identifier, self.attributes); -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@, coordinate = %f, %f, attributes = %@>", - NSStringFromClass([self class]), (void *)self, - self.identifier ? [NSString stringWithFormat:@"\"%@\"", self.identifier] : self.identifier, - self.coordinate.latitude, self.coordinate.longitude, - self.attributes.count ? self.attributes : @"none"]; -} - -@end - -@implementation MGLPointFeatureCluster - -- (NSUInteger)clusterIdentifier { - NSNumber *clusterNumber = MGL_OBJC_DYNAMIC_CAST([self attributeForKey:MGLClusterIdentifierKey], NSNumber); - MGLAssert(clusterNumber, @"Clusters should have a cluster_id"); - - if (!clusterNumber) { - return MGLClusterIdentifierInvalid; - } - - NSUInteger clusterIdentifier = [clusterNumber unsignedIntegerValue]; - MGLAssert(clusterIdentifier <= UINT32_MAX, @"Cluster identifiers are 32bit"); - - return clusterIdentifier; -} - -- (NSUInteger)clusterPointCount { - NSNumber *count = MGL_OBJC_DYNAMIC_CAST([self attributeForKey:MGLClusterCountKey], NSNumber); - MGLAssert(count, @"Clusters should have a point_count"); - - return [count unsignedIntegerValue]; -} -@end - - -@interface MGLPolylineFeature () -@end - -@implementation MGLPolylineFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - MGLLogDebug(@"Retrieving attributeForKey: %@", key); - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - return mbglFeature({[self geometryObject]}, identifier, self.attributes); -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@, count = %lu, bounds = %@, attributes = %@>", - NSStringFromClass([self class]), (void *)self, - self.identifier ? [NSString stringWithFormat:@"\"%@\"", self.identifier] : self.identifier, - (unsigned long)[self pointCount], - MGLStringFromCoordinateBounds(self.overlayBounds), - self.attributes.count ? self.attributes : @"none"]; -} - -@end - -@interface MGLPolygonFeature () -@end - -@implementation MGLPolygonFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - MGLLogDebug(@"Retrieving attributeForKey: %@", key); - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - return mbglFeature({[self geometryObject]}, identifier, self.attributes); -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@, count = %lu, bounds = %@, attributes = %@>", - NSStringFromClass([self class]), (void *)self, - self.identifier ? [NSString stringWithFormat:@"\"%@\"", self.identifier] : self.identifier, - (unsigned long)[self pointCount], - MGLStringFromCoordinateBounds(self.overlayBounds), - self.attributes.count ? self.attributes : @"none"]; -} - -@end - -@interface MGLPointCollectionFeature () -@end - -@implementation MGLPointCollectionFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - MGLLogDebug(@"Retrieving attributeForKey: %@", key); - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - return mbglFeature({[self geometryObject]}, identifier, self.attributes); -} - -@end - -@interface MGLMultiPolylineFeature () -@end - -@implementation MGLMultiPolylineFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - MGLLogDebug(@"Retrieving attributeForKey: %@", key); - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - return mbglFeature({[self geometryObject]}, identifier, self.attributes); -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@, count = %lu, bounds = %@, attributes = %@>", - NSStringFromClass([self class]), (void *)self, - self.identifier ? [NSString stringWithFormat:@"\"%@\"", self.identifier] : self.identifier, - (unsigned long)self.polylines.count, - MGLStringFromCoordinateBounds(self.overlayBounds), - self.attributes.count ? self.attributes : @"none"]; -} - -@end - -@interface MGLMultiPolygonFeature () -@end - -@implementation MGLMultiPolygonFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - MGLLogDebug(@"Retrieving attributeForKey: %@", key); - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - return mbglFeature({[self geometryObject]}, identifier, self.attributes); -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@, count = %lu, bounds = %@, attributes = %@>", - NSStringFromClass([self class]), (void *)self, - self.identifier ? [NSString stringWithFormat:@"\"%@\"", self.identifier] : self.identifier, - (unsigned long)self.polygons.count, - MGLStringFromCoordinateBounds(self.overlayBounds), - self.attributes.count ? self.attributes : @"none"]; -} - -@end - -@interface MGLShapeCollectionFeature () -@end - -@implementation MGLShapeCollectionFeature - -@synthesize identifier; -@synthesize attributes = _attributes; - -@dynamic shapes; - -+ (instancetype)shapeCollectionWithShapes:(NSArray<MGLShape<MGLFeature> *> *)shapes { - return [super shapeCollectionWithShapes:shapes]; -} - -MGL_DEFINE_FEATURE_INIT_WITH_CODER(); -MGL_DEFINE_FEATURE_ENCODE(); -MGL_DEFINE_FEATURE_IS_EQUAL(); -MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); - -- (id)attributeForKey:(NSString *)key { - return self.attributes[key]; -} - -- (NSDictionary *)geoJSONDictionary { - return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); -} - -- (mbgl::GeoJSON)geoJSONObject { - mbgl::FeatureCollection featureCollection; - featureCollection.reserve(self.shapes.count); - for (MGLShape <MGLFeature> *feature in self.shapes) { - auto geoJSONObject = feature.geoJSONObject; - MGLAssert(geoJSONObject.is<mbgl::GeoJSONFeature>(), @"Feature collection must only contain features."); - featureCollection.push_back(geoJSONObject.get<mbgl::GeoJSONFeature>()); - } - return featureCollection; -} - -@end - -/** - Transforms an `mbgl::geometry::geometry` type into an instance of the - corresponding Objective-C geometry class. - */ -template <typename T> -class GeometryEvaluator { -private: - const mbgl::PropertyMap *shared_properties; - -public: - GeometryEvaluator(const mbgl::PropertyMap *properties = nullptr): - shared_properties(properties) - {} - - MGLShape <MGLFeature> * operator()(const mbgl::EmptyGeometry &) const { - MGLEmptyFeature *feature = [[MGLEmptyFeature alloc] init]; - return feature; - } - - MGLShape <MGLFeature> * operator()(const mbgl::Point<T> &geometry) const { - Class pointFeatureClass = [MGLPointFeature class]; - - // If we're dealing with a cluster, we should change the class type. - // This could be generic and build the subclass at runtime if it turns - // out we need to support more than point clusters. - if (shared_properties) { - auto clusterIt = shared_properties->find("cluster"); - if (clusterIt != shared_properties->end()) { - auto clusterValue = clusterIt->second; - if (clusterValue.template is<bool>()) { - if (clusterValue.template get<bool>()) { - pointFeatureClass = [MGLPointFeatureCluster class]; - } - } - } - } - - MGLPointFeature *feature = [[pointFeatureClass alloc] init]; - feature.coordinate = toLocationCoordinate2D(geometry); - return feature; - } - - MGLShape <MGLFeature> * operator()(const mbgl::LineString<T> &geometry) const { - std::vector<CLLocationCoordinate2D> coordinates = toLocationCoordinates2D(geometry); - return [MGLPolylineFeature polylineWithCoordinates:&coordinates[0] count:coordinates.size()]; - } - - MGLShape <MGLFeature> * operator()(const mbgl::Polygon<T> &geometry) const { - return toShape<MGLPolygonFeature>(geometry); - } - - MGLShape <MGLFeature> * operator()(const mbgl::MultiPoint<T> &geometry) const { - std::vector<CLLocationCoordinate2D> coordinates = toLocationCoordinates2D(geometry); - return [[MGLPointCollectionFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()]; - } - - MGLShape <MGLFeature> * operator()(const mbgl::MultiLineString<T> &geometry) const { - NSMutableArray *polylines = [NSMutableArray arrayWithCapacity:geometry.size()]; - for (auto &lineString : geometry) { - std::vector<CLLocationCoordinate2D> coordinates = toLocationCoordinates2D(lineString); - MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:&coordinates[0] count:coordinates.size()]; - [polylines addObject:polyline]; - } - - return [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines]; - } - - MGLShape <MGLFeature> * operator()(const mbgl::MultiPolygon<T> &geometry) const { - NSMutableArray *polygons = [NSMutableArray arrayWithCapacity:geometry.size()]; - for (auto &polygon : geometry) { - [polygons addObject:toShape(polygon)]; - } - - return [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons]; - } - - MGLShape <MGLFeature> * 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. - MGLShape <MGLFeature> *shape = mapbox::geometry::geometry<T>::visit(geometry, *this); - [shapes addObject:shape]; - } - return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes]; - } - -private: - static CLLocationCoordinate2D toLocationCoordinate2D(const mbgl::Point<T> &point) { - return CLLocationCoordinate2DMake(point.y, point.x); - } - - static std::vector<CLLocationCoordinate2D> toLocationCoordinates2D(const std::vector<mbgl::Point<T>> &points) { - std::vector<CLLocationCoordinate2D> coordinates; - coordinates.reserve(points.size()); - std::transform(points.begin(), points.end(), std::back_inserter(coordinates), toLocationCoordinate2D); - return coordinates; - } - - template<typename U = MGLPolygon> - static U *toShape(const mbgl::Polygon<T> &geometry) { - auto &linearRing = geometry.front(); - std::vector<CLLocationCoordinate2D> coordinates = toLocationCoordinates2D(linearRing); - NSMutableArray *innerPolygons; - if (geometry.size() > 1) { - innerPolygons = [NSMutableArray arrayWithCapacity:geometry.size() - 1]; - for (auto iter = geometry.begin() + 1; iter != geometry.end(); iter++) { - auto &innerRing = *iter; - std::vector<CLLocationCoordinate2D> innerCoordinates = toLocationCoordinates2D(innerRing); - MGLPolygon *innerPolygon = [MGLPolygon polygonWithCoordinates:&innerCoordinates[0] count:innerCoordinates.size()]; - [innerPolygons addObject:innerPolygon]; - } - } - - return [U polygonWithCoordinates:&coordinates[0] count:coordinates.size() interiorPolygons:innerPolygons]; - } -}; - -template <typename T> -class GeoJSONEvaluator { -public: - MGLShape <MGLFeature> * operator()(const mbgl::Geometry<T> &geometry) const { - GeometryEvaluator<T> evaluator; - MGLShape <MGLFeature> *shape = mapbox::geometry::geometry<T>::visit(geometry, evaluator); - return shape; - } - - MGLShape <MGLFeature> * operator()(const mbgl::GeoJSONFeature &feature) const { - MGLShape <MGLFeature> *shape = (MGLShape <MGLFeature> *)MGLFeatureFromMBGLFeature(feature); - return shape; - } - - MGLShape <MGLFeature> * operator()(const mbgl::FeatureCollection &collection) const { - NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()]; - for (const auto &feature : collection) { - [shapes addObject:MGLFeatureFromMBGLFeature(feature)]; - } - return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes]; - } -}; - -NSArray<MGLShape <MGLFeature> *> *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features) { - NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:features.size()]; - for (const auto &feature : features) { - [shapes addObject:MGLFeatureFromMBGLFeature(static_cast<mbgl::GeoJSONFeature>(feature))]; - } - return shapes; -} - -NSArray<MGLShape <MGLFeature> *> *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::GeoJSONFeature> &features) { - NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:features.size()]; - for (const auto &feature : features) { - [shapes addObject:MGLFeatureFromMBGLFeature(feature)]; - } - return shapes; -} - -id <MGLFeature> MGLFeatureFromMBGLFeature(const mbgl::GeoJSONFeature &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(&feature.properties); - MGLShape <MGLFeature> *shape = mapbox::geometry::geometry<double>::visit(feature.geometry, evaluator); - if (!feature.id.is<mapbox::feature::null_value_t>()) { - 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::GeoJSONFeature mbglFeature(mbgl::GeoJSONFeature feature, id identifier, NSDictionary *attributes) -{ - if (identifier) { - NSExpression *identifierExpression = [NSExpression expressionForConstantValue:identifier]; - feature.id = [identifierExpression mgl_featureIdentifier]; - } - feature.properties = [attributes mgl_propertyMap]; - return feature; -} - -NSDictionary<NSString *, id> *NSDictionaryFeatureForGeometry(NSDictionary *geometry, NSDictionary *attributes, id identifier) { - NSMutableDictionary *feature = [@{@"type": @"Feature", - @"properties": attributes, - @"geometry": geometry} mutableCopy]; - feature[@"id"] = identifier; - return [feature copy]; -} |