From 360b8b42471d7196511ab11edb4f9f277329af13 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Thu, 3 Oct 2019 15:57:05 +0300 Subject: [core,android,darwin,qt] Add fields related to feature-state Move the fields from geometry.hpp/feature.hpp as they are not part of the GeoJSON specification. --- include/mbgl/util/feature.hpp | 16 +++++++++++++++- platform/android/src/geojson/feature.cpp | 25 +++++++++++++++++-------- platform/android/src/geojson/feature.hpp | 3 ++- platform/darwin/src/MGLComputedShapeSource.mm | 4 ++-- platform/darwin/src/MGLFeature.mm | 18 +++++++++++++----- platform/darwin/src/MGLFeature_Private.h | 15 +++++++++++---- platform/darwin/src/MGLShapeSource.mm | 8 ++++---- platform/qt/src/qt_geojson.cpp | 2 +- platform/qt/src/qt_geojson.hpp | 2 +- render-test/parser.cpp | 20 +++++++++++++------- 10 files changed, 79 insertions(+), 34 deletions(-) diff --git a/include/mbgl/util/feature.hpp b/include/mbgl/util/feature.hpp index 6080976945..5d8fe89e36 100644 --- a/include/mbgl/util/feature.hpp +++ b/include/mbgl/util/feature.hpp @@ -11,11 +11,25 @@ using Value = mapbox::base::Value; using NullValue = mapbox::base::NullValue; using PropertyMap = mapbox::base::ValueObject; using FeatureIdentifier = mapbox::feature::identifier; -using Feature = mapbox::feature::feature; +using GeoJSONFeature = mapbox::feature::feature; using FeatureState = mapbox::base::ValueObject; using FeatureStates = std::unordered_map; // using LayerFeatureStates = std::unordered_map; // +class Feature : public GeoJSONFeature { +public: + std::string source; + std::string sourceLayer; + PropertyMap state; + + using GeometryType = mapbox::geometry::geometry; + + Feature() = default; + Feature(const GeoJSONFeature& f) : GeoJSONFeature(f) {} + Feature(const GeometryType& geom_) : GeoJSONFeature(geom_) {} + Feature(GeometryType&& geom_) : GeoJSONFeature(std::move(geom_)) {} +}; + template optional numericValue(const Value& value) { return value.match( diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index 8d30404a50..afbf1ee11e 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -10,7 +10,7 @@ namespace geojson { using namespace gson; -mbgl::Feature Feature::convert(jni::JNIEnv& env, const jni::Object& jFeature) { +mbgl::GeoJSONFeature Feature::convert(jni::JNIEnv& env, const jni::Object& jFeature) { static auto& javaClass = jni::Class::Singleton(env); static auto id = javaClass.GetMethod(env, "id"); static auto geometry = javaClass.GetMethod ()>(env, "geometry"); @@ -20,11 +20,9 @@ mbgl::Feature Feature::convert(jni::JNIEnv& env, const jni::Object& jFe using mbid = mapbox::feature::identifier; - return mbgl::Feature { - Geometry::convert(env, jFeature.Call(env, geometry)), - JsonObject::convert(env, jFeature.Call(env, properties)), - jId ? mbid { jni::Make(env, jId) } : mbid { mapbox::feature::null_value } - }; + return mbgl::GeoJSONFeature{Geometry::convert(env, jFeature.Call(env, geometry)), + JsonObject::convert(env, jFeature.Call(env, properties)), + jId ? mbid{jni::Make(env, jId)} : mbid{mapbox::feature::null_value}}; } /** @@ -50,7 +48,7 @@ public: } }; -jni::Local> convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { +jni::Local> convertFeature(jni::JNIEnv& env, const mbgl::GeoJSONFeature& value) { static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); @@ -63,7 +61,18 @@ jni::Local> convertFeature(jni::JNIEnv& env, const mbgl::Fe jni::Local>> Feature::convert(jni::JNIEnv& env, const std::vector& value) { auto features = jni::Array>::New(env, value.size()); - for (size_t i = 0; i < value.size(); i = i + 1) { + for (size_t i = 0; i < value.size(); ++i) { + features.Set(env, i, convertFeature(env, static_cast(value.at(i)))); + } + + return features; +} + +jni::Local>> Feature::convert(jni::JNIEnv& env, + const std::vector& value) { + auto features = jni::Array>::New(env, value.size()); + + for (size_t i = 0; i < value.size(); ++i) { features.Set(env, i, convertFeature(env, value.at(i))); } diff --git a/platform/android/src/geojson/feature.hpp b/platform/android/src/geojson/feature.hpp index fdf5d977ba..aee45262e3 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -12,8 +12,9 @@ class Feature { public: static constexpr auto Name() { return "com/mapbox/geojson/Feature"; }; - static mbgl::Feature convert(jni::JNIEnv&, const jni::Object&); + static mbgl::GeoJSONFeature convert(jni::JNIEnv&, const jni::Object&); static jni::Local>> convert(jni::JNIEnv&, const std::vector&); + static jni::Local>> convert(jni::JNIEnv&, const std::vector&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/darwin/src/MGLComputedShapeSource.mm b/platform/darwin/src/MGLComputedShapeSource.mm index a04181af2f..ceb83b3740 100644 --- a/platform/darwin/src/MGLComputedShapeSource.mm +++ b/platform/darwin/src/MGLComputedShapeSource.mm @@ -140,7 +140,7 @@ mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDi @"This will be logged only once."); }); } - mbgl::Feature geoJsonObject = [feature geoJSONObject].get(); + mbgl::GeoJSONFeature geoJsonObject = [feature geoJSONObject].get(); featureCollection.push_back(geoJsonObject); } const auto geojson = mbgl::GeoJSON{featureCollection}; @@ -204,7 +204,7 @@ mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDi mbgl::FeatureCollection featureCollection; featureCollection.reserve(features.count); for (MGLShape * feature in features) { - mbgl::Feature geoJsonObject = [feature geoJSONObject].get(); + mbgl::GeoJSONFeature geoJsonObject = [feature geoJSONObject].get(); featureCollection.push_back(geoJsonObject); if ([feature isMemberOfClass:[MGLShapeCollection class]]) { static dispatch_once_t onceToken; diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm index fbf262af29..df6b1bffea 100644 --- a/platform/darwin/src/MGLFeature.mm +++ b/platform/darwin/src/MGLFeature.mm @@ -336,8 +336,8 @@ MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER(); featureCollection.reserve(self.shapes.count); for (MGLShape *feature in self.shapes) { auto geoJSONObject = feature.geoJSONObject; - MGLAssert(geoJSONObject.is(), @"Feature collection must only contain features."); - featureCollection.push_back(geoJSONObject.get()); + MGLAssert(geoJSONObject.is(), @"Feature collection must only contain features."); + featureCollection.push_back(geoJSONObject.get()); } return featureCollection; } @@ -470,7 +470,7 @@ public: return shape; } - MGLShape * operator()(const mbgl::Feature &feature) const { + MGLShape * operator()(const mbgl::GeoJSONFeature &feature) const { MGLShape *shape = (MGLShape *)MGLFeatureFromMBGLFeature(feature); return shape; } @@ -485,6 +485,14 @@ public: }; NSArray *> *MGLFeaturesFromMBGLFeatures(const std::vector &features) { + NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:features.size()]; + for (const auto &feature : features) { + [shapes addObject:MGLFeatureFromMBGLFeature(static_cast(feature))]; + } + return shapes; +} + +NSArray *> *MGLFeaturesFromMBGLFeatures(const std::vector &features) { NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:features.size()]; for (const auto &feature : features) { [shapes addObject:MGLFeatureFromMBGLFeature(feature)]; @@ -492,7 +500,7 @@ NSArray *> *MGLFeaturesFromMBGLFeatures(const std::vector< return shapes; } -id MGLFeatureFromMBGLFeature(const mbgl::Feature &feature) { +id MGLFeatureFromMBGLFeature(const mbgl::GeoJSONFeature &feature) { NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()]; for (auto &pair : feature.properties) { auto &value = pair.second; @@ -515,7 +523,7 @@ MGLShape* MGLShapeFromGeoJSON(const mapbox::geojson::geojson &geojson) { return shape; } -mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *attributes) +mbgl::GeoJSONFeature mbglFeature(mbgl::GeoJSONFeature feature, id identifier, NSDictionary *attributes) { if (identifier) { NSExpression *identifierExpression = [NSExpression expressionForConstantValue:identifier]; diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h index 9b0e16f4b9..599633dd31 100644 --- a/platform/darwin/src/MGLFeature_Private.h +++ b/platform/darwin/src/MGLFeature_Private.h @@ -16,10 +16,17 @@ MGL_EXPORT NSArray *> *MGLFeaturesFromMBGLFeatures(const std::vector &features); /** - Returns an `MGLFeature` object converted from the given mbgl::Feature + Returns an array of `MGLFeature` objects converted from the given vector of + vector tile features. + */ +MGL_EXPORT +NSArray *> *MGLFeaturesFromMBGLFeatures(const std::vector &features); + +/** + Returns an `MGLFeature` object converted from the given mbgl::GeoJSONFeature */ MGL_EXPORT -id MGLFeatureFromMBGLFeature(const mbgl::Feature &feature); +id MGLFeatureFromMBGLFeature(const mbgl::GeoJSONFeature &feature); /** Returns an `MGLShape` representing the given geojson. The shape can be @@ -28,11 +35,11 @@ id MGLFeatureFromMBGLFeature(const mbgl::Feature &feature); MGLShape* MGLShapeFromGeoJSON(const mapbox::geojson::geojson &geojson); /** - Takes an `mbgl::Feature` object, an identifer, and attributes dictionary and + Takes an `mbgl::GeoJSONFeature` object, an identifer, and attributes dictionary and returns the feature object with converted `mbgl::FeatureIdentifier` and `mbgl::PropertyMap` properties. */ -mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary * attributes); +mbgl::GeoJSONFeature mbglFeature(mbgl::GeoJSONFeature feature, id identifier, NSDictionary * attributes); /** Returns an `NSDictionary` representation of an `MGLFeature`. diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm index 3820fe9d60..a4a100aaa2 100644 --- a/platform/darwin/src/MGLShapeSource.mm +++ b/platform/darwin/src/MGLShapeSource.mm @@ -262,12 +262,12 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary()) { + if (!geoJSON.is()) { MGLAssert(0, @"cluster geoJSON object is not a feature."); return extensionValue; } - auto clusterFeature = geoJSON.get(); + auto clusterFeature = geoJSON.get(); extensionValue = self.mapView.renderer->queryFeatureExtensions(self.rawSource->getID(), clusterFeature, @@ -293,7 +293,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary leaves = featureExtension->get(); + std::vector leaves = featureExtension->get(); return MGLFeaturesFromMBGLFeatures(leaves); } @@ -308,7 +308,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary leaves = featureExtension->get(); + std::vector leaves = featureExtension->get(); return MGLFeaturesFromMBGLFeatures(leaves); } diff --git a/platform/qt/src/qt_geojson.cpp b/platform/qt/src/qt_geojson.cpp index 48d78abfe0..3b775685b1 100644 --- a/platform/qt/src/qt_geojson.cpp +++ b/platform/qt/src/qt_geojson.cpp @@ -121,7 +121,7 @@ mbgl::FeatureIdentifier asMapboxGLFeatureIdentifier(const QVariant &id) { } } -mbgl::Feature asMapboxGLFeature(const QMapbox::Feature &feature) { +mbgl::GeoJSONFeature asMapboxGLFeature(const QMapbox::Feature &feature) { mbgl::PropertyMap properties; properties.reserve(feature.properties.size()); for (auto it = feature.properties.constBegin(); it != feature.properties.constEnd(); ++it) { diff --git a/platform/qt/src/qt_geojson.hpp b/platform/qt/src/qt_geojson.hpp index a9c10272ab..a7db3ba644 100644 --- a/platform/qt/src/qt_geojson.hpp +++ b/platform/qt/src/qt_geojson.hpp @@ -22,6 +22,6 @@ mbgl::Polygon asMapboxGLPolygon(const QMapbox::CoordinatesCollection &po mbgl::MultiPolygon asMapboxGLMultiPolygon(const QMapbox::CoordinatesCollections &multiPolygon); mbgl::Value asMapboxGLPropertyValue(const QVariant &value); mbgl::FeatureIdentifier asMapboxGLFeatureIdentifier(const QVariant &id); -mbgl::Feature asMapboxGLFeature(const QMapbox::Feature &feature); +mbgl::GeoJSONFeature asMapboxGLFeature(const QMapbox::Feature &feature); } // namespace QMapbox diff --git a/render-test/parser.cpp b/render-test/parser.cpp index f410ffa860..11a42f3202 100644 --- a/render-test/parser.cpp +++ b/render-test/parser.cpp @@ -252,14 +252,20 @@ std::string toJSON(const std::vector& features, unsigned indent, } writer.SetIndent(' ', indent); writer.StartArray(); - for (size_t i = 0; i < features.size(); ++i) { - auto result = mapbox::geojson::convert(features[i], allocator); - - result.AddMember("source", features[i].source, allocator); - if (!features[i].sourceLayer.empty()) { - result.AddMember("sourceLayer", features[i].sourceLayer, allocator); + for (const auto& feature : features) { + mbgl::JSValue result(rapidjson::kObjectType); + result.AddMember("type", "Feature", allocator); + if (!feature.id.is()) { + result.AddMember( + "id", mapbox::geojson::identifier::visit(feature.id, mapbox::geojson::to_value{allocator}), allocator); + } + result.AddMember("geometry", mapbox::geojson::convert(feature.geometry, allocator), allocator); + result.AddMember("properties", mapbox::geojson::to_value{allocator}(feature.properties), allocator); + result.AddMember("source", feature.source, allocator); + if (!feature.sourceLayer.empty()) { + result.AddMember("sourceLayer", feature.sourceLayer, allocator); } - result.AddMember("state", mapbox::geojson::to_value{allocator}(features[i].state), allocator); + result.AddMember("state", mapbox::geojson::to_value{allocator}(feature.state), allocator); result.Accept(writer); } writer.EndArray(); -- cgit v1.2.1