From 957296b2fbbac8803025d50ccc57c7addd704567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 28 Feb 2020 18:46:10 -0800 Subject: [PATCH] [ios, macos] Convert geometries to shapes, not features Fixed an issue where GeoJSON geometries were converted to MGLFeature instances instead of MGLShape objects. --- platform/darwin/src/MGLFeature.mm | 71 +++++++++++++++++-------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm index df6b1bffe..f8806b3f3 100644 --- a/platform/darwin/src/MGLFeature.mm +++ b/platform/darwin/src/MGLFeature.mm @@ -352,19 +352,20 @@ template class GeometryEvaluator { private: const mbgl::PropertyMap *shared_properties; + const bool is_in_feature; public: - GeometryEvaluator(const mbgl::PropertyMap *properties = nullptr): - shared_properties(properties) + GeometryEvaluator(const mbgl::PropertyMap *properties = nullptr, const bool isInFeature = false): + shared_properties(properties), + is_in_feature(isInFeature) {} - MGLShape * operator()(const mbgl::EmptyGeometry &) const { - MGLEmptyFeature *feature = [[MGLEmptyFeature alloc] init]; - return feature; + MGLShape * operator()(const mbgl::EmptyGeometry &) const { + return is_in_feature ? [[MGLEmptyFeature alloc] init] : [[MGLShape alloc] init]; } - MGLShape * operator()(const mbgl::Point &geometry) const { - Class pointFeatureClass = [MGLPointFeature class]; + MGLShape * operator()(const mbgl::Point &geometry) const { + Class shapeClass = is_in_feature ? [MGLPointFeature class] : [MGLPointAnnotation 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 @@ -375,32 +376,34 @@ public: auto clusterValue = clusterIt->second; if (clusterValue.template is()) { if (clusterValue.template get()) { - pointFeatureClass = [MGLPointFeatureCluster class]; + shapeClass = [MGLPointFeatureCluster class]; } } } } - MGLPointFeature *feature = [[pointFeatureClass alloc] init]; - feature.coordinate = toLocationCoordinate2D(geometry); - return feature; + MGLPointAnnotation *shape = [[shapeClass alloc] init]; + shape.coordinate = toLocationCoordinate2D(geometry); + return shape; } - MGLShape * operator()(const mbgl::LineString &geometry) const { + MGLShape * operator()(const mbgl::LineString &geometry) const { std::vector coordinates = toLocationCoordinates2D(geometry); - return [MGLPolylineFeature polylineWithCoordinates:&coordinates[0] count:coordinates.size()]; + Class shapeClass = is_in_feature ? [MGLPolylineFeature class] : [MGLPolyline class]; + return [shapeClass polylineWithCoordinates:&coordinates[0] count:coordinates.size()]; } - MGLShape * operator()(const mbgl::Polygon &geometry) const { - return toShape(geometry); + MGLShape * operator()(const mbgl::Polygon &geometry) const { + return toShape(geometry, is_in_feature); } - MGLShape * operator()(const mbgl::MultiPoint &geometry) const { + MGLShape * operator()(const mbgl::MultiPoint &geometry) const { std::vector coordinates = toLocationCoordinates2D(geometry); - return [[MGLPointCollectionFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()]; + Class shapeClass = is_in_feature ? [MGLPointCollectionFeature class] : [MGLPointCollection class]; + return [[shapeClass alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()]; } - MGLShape * operator()(const mbgl::MultiLineString &geometry) const { + MGLShape * operator()(const mbgl::MultiLineString &geometry) const { NSMutableArray *polylines = [NSMutableArray arrayWithCapacity:geometry.size()]; for (auto &lineString : geometry) { std::vector coordinates = toLocationCoordinates2D(lineString); @@ -408,26 +411,29 @@ public: [polylines addObject:polyline]; } - return [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines]; + Class shapeClass = is_in_feature ? [MGLMultiPolylineFeature class] : [MGLMultiPolyline class]; + return [shapeClass multiPolylineWithPolylines:polylines]; } - MGLShape * operator()(const mbgl::MultiPolygon &geometry) const { + MGLShape * operator()(const mbgl::MultiPolygon &geometry) const { NSMutableArray *polygons = [NSMutableArray arrayWithCapacity:geometry.size()]; for (auto &polygon : geometry) { - [polygons addObject:toShape(polygon)]; + [polygons addObject:toShape(polygon, false)]; } - return [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons]; + Class shapeClass = is_in_feature ? [MGLMultiPolygonFeature class] : [MGLMultiPolygon class]; + return [shapeClass multiPolygonWithPolygons:polygons]; } - MGLShape * operator()(const mapbox::geometry::geometry_collection &collection) const { + MGLShape * operator()(const mapbox::geometry::geometry_collection &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 *shape = mapbox::geometry::geometry::visit(geometry, *this); + MGLShape *shape = mapbox::geometry::geometry::visit(geometry, *this); [shapes addObject:shape]; } - return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes]; + Class shapeClass = is_in_feature ? [MGLShapeCollectionFeature class] : [MGLShapeCollection class]; + return [shapeClass shapeCollectionWithShapes:shapes]; } private: @@ -442,8 +448,8 @@ private: return coordinates; } - template - static U *toShape(const mbgl::Polygon &geometry) { + template + static U *toShape(const mbgl::Polygon &geometry, const bool isInFeature) { auto &linearRing = geometry.front(); std::vector coordinates = toLocationCoordinates2D(linearRing); NSMutableArray *innerPolygons; @@ -457,16 +463,17 @@ private: } } - return [U polygonWithCoordinates:&coordinates[0] count:coordinates.size() interiorPolygons:innerPolygons]; + Class shapeClass = isInFeature ? [V class] : [U class]; + return [shapeClass polygonWithCoordinates:&coordinates[0] count:coordinates.size() interiorPolygons:innerPolygons]; } }; template class GeoJSONEvaluator { public: - MGLShape * operator()(const mbgl::Geometry &geometry) const { + MGLShape * operator()(const mbgl::Geometry &geometry) const { GeometryEvaluator evaluator; - MGLShape *shape = mapbox::geometry::geometry::visit(geometry, evaluator); + MGLShape *shape = mapbox::geometry::geometry::visit(geometry, evaluator); return shape; } @@ -507,8 +514,8 @@ id MGLFeatureFromMBGLFeature(const mbgl::GeoJSONFeature &feature) { ValueEvaluator evaluator; attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator); } - GeometryEvaluator evaluator(&feature.properties); - MGLShape *shape = mapbox::geometry::geometry::visit(feature.geometry, evaluator); + GeometryEvaluator evaluator(&feature.properties, true); + MGLShape *shape = (MGLShape *)mapbox::geometry::geometry::visit(feature.geometry, evaluator); if (!feature.id.is()) { shape.identifier = mbgl::FeatureIdentifier::visit(feature.id, ValueEvaluator()); }