diff options
29 files changed, 205 insertions, 183 deletions
diff --git a/.mason b/.mason -Subproject 3017f674227ff7a7d915911157cdff62079c308 +Subproject c3be66082b836fe9dc852ee72837e8156661523 diff --git a/benchmark/parse/filter.cpp b/benchmark/parse/filter.cpp index 24314e8584..6b430a9b11 100644 --- a/benchmark/parse/filter.cpp +++ b/benchmark/parse/filter.cpp @@ -9,12 +9,8 @@ #include <rapidjson/document.h> -#include <map> - using namespace mbgl; -typedef std::multimap<std::string, Value> Properties; - style::Filter parse(const char* expression) { rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc; doc.Parse<0>(expression); @@ -29,7 +25,7 @@ static void Parse_Filter(benchmark::State& state) { static void Parse_EvaluateFilter(benchmark::State& state) { const style::Filter filter = parse(R"FILTER(["==", "foo", "bar"])FILTER"); - const Properties properties = { { "foo", std::string("bar") } }; + const PropertyMap properties = { { "foo", std::string("bar") } }; while (state.KeepRunning()) { filter(FeatureType::Unknown, [&] (const std::string& key) -> optional<Value> { @@ -118,6 +118,7 @@ print_flags zlib static_libs cflags ldflags print_flags nunicode static_libs cflags ldflags print_flags libzip static_libs cflags ldflags print_flags geometry cflags +print_flags geojson static_libs cflags ldflags print_flags geojsonvt static_libs cflags ldflags print_flags variant cflags print_flags rapidjson static_libs cflags ldflags diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp index e7b6e0f5a0..cf91fdab1f 100644 --- a/include/mbgl/style/filter_evaluator.hpp +++ b/include/mbgl/style/filter_evaluator.hpp @@ -151,13 +151,24 @@ private: return false; } + bool operator()(const NullValue&, + const NullValue&) const { + // Should be unreachable; null is not currently allowed by the style specification. + assert(false); + return false; + } + bool operator()(const std::vector<Value>&, const std::vector<Value>&) const { + // Should be unreachable; nested values are not currently allowed by the style specification. + assert(false); return false; } bool operator()(const std::unordered_map<std::string, Value>&, const std::unordered_map<std::string, Value>&) const { + // Should be unreachable; nested values are not currently allowed by the style specification. + assert(false); return false; } }; diff --git a/include/mbgl/util/feature.hpp b/include/mbgl/util/feature.hpp index 7747d34ee9..7c5c8d7625 100644 --- a/include/mbgl/util/feature.hpp +++ b/include/mbgl/util/feature.hpp @@ -7,13 +7,13 @@ namespace mbgl { using Value = mapbox::geometry::value; - +using NullValue = mapbox::geometry::null_value_t; +using PropertyMap = mapbox::geometry::property_map; +using FeatureIdentifier = mapbox::geometry::identifier; class Feature : public mapbox::geometry::feature<double> { public: Feature(geometry_type&& geometry_) : mapbox::geometry::feature<double> { std::move(geometry_) } {} - - optional<uint64_t> id; }; } // namespace mbgl diff --git a/include/mbgl/util/geometry.hpp b/include/mbgl/util/geometry.hpp index 7fc2668c2c..6dc16bc514 100644 --- a/include/mbgl/util/geometry.hpp +++ b/include/mbgl/util/geometry.hpp @@ -41,4 +41,21 @@ Point<S> convertPoint(const Point<T>& p) { return Point<S>(p.x, p.y); } +struct ToFeatureType { + template <class T> + FeatureType operator()(const Point<T> &) const { return FeatureType::Point; } + template <class T> + FeatureType operator()(const MultiPoint<T> &) const { return FeatureType::Point; } + template <class T> + FeatureType operator()(const LineString<T> &) const { return FeatureType::LineString; } + template <class T> + FeatureType operator()(const MultiLineString<T> &) const { return FeatureType::LineString; } + template <class T> + FeatureType operator()(const Polygon<T> &) const { return FeatureType::Polygon; } + template <class T> + FeatureType operator()(const MultiPolygon<T> &) const { return FeatureType::Polygon; } + template <class T> + FeatureType operator()(const mapbox::geometry::geometry_collection<T> &) const { return FeatureType::Unknown; } +}; + } // namespace mbgl @@ -192,6 +192,7 @@ '<@(protozero_cflags)', '<@(boost_cflags)', '<@(geometry_cflags)', + '<@(geojson_cflags)', '<@(geojsonvt_cflags)', '<@(rapidjson_cflags)', '<@(variant_cflags)', @@ -207,7 +208,7 @@ '<@(opengl_ldflags)', ], 'libraries': [ - '<@(geojsonvt_static_libs)', + '<@(geojson_static_libs)', ], }, diff --git a/platform/android/scripts/configure.sh b/platform/android/scripts/configure.sh index b2bdce556d..a9a5b25ff7 100644 --- a/platform/android/scripts/configure.sh +++ b/platform/android/scripts/configure.sh @@ -9,8 +9,9 @@ SQLITE_VERSION=3.9.1 ZLIB_VERSION=system NUNICODE_VERSION=1.6 LIBZIP_VERSION=0.11.2 -GEOMETRY_VERSION=0.5.0 -GEOJSONVT_VERSION=4.1.2-cxx11abi +GEOMETRY_VERSION=0.8.0 +GEOJSON_VERSION=0.1.4 +GEOJSONVT_VERSION=6.1.0 VARIANT_VERSION=1.1.0 RAPIDJSON_VERSION=1.0.2 JNI_HPP_VERSION=2.0.0 diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm index 777b296303..3bf1e61153 100644 --- a/platform/darwin/src/MGLFeature.mm +++ b/platform/darwin/src/MGLFeature.mm @@ -118,7 +118,7 @@ */ class PropertyValueEvaluator { public: - id operator()(const std::nullptr_t &) const { + id operator()(const mbgl::NullValue &) const { return [NSNull null]; } @@ -260,7 +260,7 @@ NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vec GeometryEvaluator<double> evaluator; MGLShape <MGLFeaturePrivate> *shape = mapbox::geometry::geometry<double>::visit(feature.geometry, evaluator); if (feature.id) { - shape.identifier = @(*feature.id); + shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, PropertyValueEvaluator()); } shape.attributes = attributes; [shapes addObject:shape]; diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm index 6cf038d4fb..13ad8759b0 100644 --- a/platform/darwin/test/MGLFeatureTests.mm +++ b/platform/darwin/test/MGLFeatureTests.mm @@ -89,7 +89,7 @@ mapbox::geometry::point<double> point = { -90.066667, 29.95 }; mbgl::Feature pointFeature(point); - pointFeature.id = UINT64_MAX; + pointFeature.id = { UINT64_MAX }; pointFeature.properties["null"] = nullptr; pointFeature.properties["bool"] = true; pointFeature.properties["unsigned int"] = UINT64_MAX; diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index ec0957a4f5..590a119600 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -1739,7 +1739,7 @@ "$(sqlite_ldflags)", "$(zlib_ldflags)", "$(opengl_ldflags)", - "$(geojsonvt_static_libs)", + "$(geojson_static_libs)", ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.sdk.ios; PRODUCT_NAME = Mapbox; @@ -1779,7 +1779,7 @@ "$(sqlite_ldflags)", "$(zlib_ldflags)", "$(opengl_ldflags)", - "$(geojsonvt_static_libs)", + "$(geojson_static_libs)", ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.sdk.ios; PRODUCT_NAME = Mapbox; @@ -1833,7 +1833,7 @@ "$(sqlite_ldflags)", "$(zlib_ldflags)", "$(opengl_ldflags)", - "$(geojsonvt_static_libs)", + "$(geojson_static_libs)", ); PRODUCT_NAME = Mapbox; PUBLIC_HEADERS_FOLDER_PATH = Headers; @@ -1863,7 +1863,7 @@ "$(sqlite_ldflags)", "$(zlib_ldflags)", "$(opengl_ldflags)", - "$(geojsonvt_static_libs)", + "$(geojson_static_libs)", ); PRODUCT_NAME = Mapbox; PUBLIC_HEADERS_FOLDER_PATH = Headers; diff --git a/platform/ios/scripts/configure.sh b/platform/ios/scripts/configure.sh index 408180881c..a0791e3108 100644 --- a/platform/ios/scripts/configure.sh +++ b/platform/ios/scripts/configure.sh @@ -5,8 +5,9 @@ PROTOZERO_VERSION=1.3.0 BOOST_VERSION=1.60.0 SQLITE_VERSION=system ZLIB_VERSION=system -GEOMETRY_VERSION=0.5.0 -GEOJSONVT_VERSION=4.1.2 +GEOMETRY_VERSION=0.8.0 +GEOJSON_VERSION=0.1.4 +GEOJSONVT_VERSION=6.1.0 VARIANT_VERSION=1.1.0 RAPIDJSON_VERSION=1.0.2 GTEST_VERSION=1.7.0 diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh index f0ca683389..8bc2a3fd63 100755 --- a/platform/ios/scripts/package.sh +++ b/platform/ios/scripts/package.sh @@ -119,7 +119,7 @@ if [[ "${BUILD_FOR_DEVICE}" == true ]]; then -o ${OUTPUT}/static/${NAME}.framework/${NAME} \ ${LIBS[@]/#/${PRODUCTS}/${BUILDTYPE}-iphoneos/lib} \ ${LIBS[@]/#/${PRODUCTS}/${BUILDTYPE}-iphonesimulator/lib} \ - `find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libgeojsonvt.a` + `find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libgeojson.a` cp -rv ${PRODUCTS}/${BUILDTYPE}-iphoneos/${NAME}.bundle ${STATIC_BUNDLE_DIR} fi @@ -149,7 +149,7 @@ else libtool -static -no_warning_for_no_symbols \ -o ${OUTPUT}/static/${NAME}.framework/${NAME} \ ${LIBS[@]/#/${PRODUCTS}/${BUILDTYPE}-iphonesimulator/lib} \ - `find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libgeojsonvt.a` + `find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libgeojson.a` cp -rv ${PRODUCTS}/${BUILDTYPE}-iphonesimulator/${NAME}.bundle ${STATIC_BUNDLE_DIR} fi diff --git a/platform/linux/scripts/configure.sh b/platform/linux/scripts/configure.sh index 6521fc8ccd..c4f6dc606d 100644 --- a/platform/linux/scripts/configure.sh +++ b/platform/linux/scripts/configure.sh @@ -14,8 +14,9 @@ SQLITE_VERSION=3.9.1 LIBUV_VERSION=1.7.5 ZLIB_VERSION=system NUNICODE_VERSION=1.6 -GEOMETRY_VERSION=0.5.0 -GEOJSONVT_VERSION=4.1.2${CXX11ABI:-} +GEOMETRY_VERSION=0.8.0 +GEOJSON_VERSION=0.1.4${CXX11ABI:-} +GEOJSONVT_VERSION=6.1.0 VARIANT_VERSION=1.1.0 RAPIDJSON_VERSION=1.0.2 GTEST_VERSION=1.7.0${CXX11ABI:-} diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index 7271356f2a..10f57a369a 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -1039,7 +1039,7 @@ OTHER_LDFLAGS = ( "$(zlib_ldflags)", "$(opengl_ldflags)", - "$(geojsonvt_static_libs)", + "$(geojson_static_libs)", ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.MapboxGL; PRODUCT_NAME = Mapbox; @@ -1078,7 +1078,7 @@ OTHER_LDFLAGS = ( "$(zlib_ldflags)", "$(opengl_ldflags)", - "$(geojsonvt_static_libs)", + "$(geojson_static_libs)", ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.MapboxGL; PRODUCT_NAME = Mapbox; diff --git a/platform/macos/scripts/configure.sh b/platform/macos/scripts/configure.sh index 2952ec2535..47d9b381ba 100644 --- a/platform/macos/scripts/configure.sh +++ b/platform/macos/scripts/configure.sh @@ -8,8 +8,9 @@ GLFW_VERSION=3.1.2 SQLITE_VERSION=3.9.1 ZLIB_VERSION=system NUNICODE_VERSION=1.6 -GEOMETRY_VERSION=0.5.0 -GEOJSONVT_VERSION=4.1.2 +GEOMETRY_VERSION=0.8.0 +GEOJSON_VERSION=0.1.4 +GEOJSONVT_VERSION=6.1.0 VARIANT_VERSION=1.1.0 RAPIDJSON_VERSION=1.0.2 GTEST_VERSION=1.7.0 diff --git a/platform/node/src/node_feature.cpp b/platform/node/src/node_feature.cpp index 1a5e31fe97..6620cf1852 100644 --- a/platform/node/src/node_feature.cpp +++ b/platform/node/src/node_feature.cpp @@ -6,9 +6,10 @@ using namespace mapbox::geometry; using Value = mbgl::Value; using Feature = mbgl::Feature; +using FeatureIdentifier = mbgl::FeatureIdentifier; using Geometry = mbgl::Feature::geometry_type; using GeometryCollection = mapbox::geometry::geometry_collection<double>; -using Properties = mbgl::Feature::property_map; +using Properties = mbgl::PropertyMap; template <class T> struct ToType { @@ -76,7 +77,7 @@ public: }; struct ToValue { - v8::Local<v8::Value> operator()(std::nullptr_t) { + v8::Local<v8::Value> operator()(mbgl::NullValue) { Nan::EscapableHandleScope scope; return scope.Escape(Nan::Null()); } @@ -159,7 +160,7 @@ v8::Local<v8::Object> toJS(const Feature& feature) { Nan::Set(result, Nan::New("properties").ToLocalChecked(), toJS(feature.properties)); if (feature.id) { - Nan::Set(result, Nan::New("id").ToLocalChecked(), Nan::New(double(*feature.id))); + Nan::Set(result, Nan::New("id").ToLocalChecked(), FeatureIdentifier::visit(*feature.id, ToValue())); } return scope.Escape(result); diff --git a/platform/node/src/node_feature.hpp b/platform/node/src/node_feature.hpp index 7973ee19d4..8d1eceba38 100644 --- a/platform/node/src/node_feature.hpp +++ b/platform/node/src/node_feature.hpp @@ -13,6 +13,6 @@ namespace node_mbgl { v8::Local<v8::Value> toJS(const mbgl::Value&); v8::Local<v8::Object> toJS(const mbgl::Feature&); v8::Local<v8::Object> toJS(const mbgl::Feature::geometry_type&); -v8::Local<v8::Object> toJS(const mbgl::Feature::property_map&); +v8::Local<v8::Object> toJS(const mbgl::PropertyMap&); } diff --git a/platform/qt/scripts/configure.sh b/platform/qt/scripts/configure.sh index 461c1cc1b3..6b501d271c 100644 --- a/platform/qt/scripts/configure.sh +++ b/platform/qt/scripts/configure.sh @@ -5,8 +5,9 @@ CXX11ABI=${CXX11ABI:-$(scripts/check-cxx11abi.sh)} UNIQUE_RESOURCE_VERSION=dev PROTOZERO_VERSION=1.3.0 BOOST_VERSION=1.60.0 -GEOMETRY_VERSION=0.5.0 -GEOJSONVT_VERSION=4.1.2${CXX11ABI:-} +GEOMETRY_VERSION=0.8.0 +GEOJSON_VERSION=0.1.4${CXX11ABI:-} +GEOJSONVT_VERSION=6.1.0 GTEST_VERSION=1.7.0${CXX11ABI:-} LIBJPEG_TURBO_VERSION=1.4.2 NUNICODE_VERSION=1.6 diff --git a/src/mbgl/annotation/fill_annotation_impl.cpp b/src/mbgl/annotation/fill_annotation_impl.cpp index 8146c68a53..fe520451f7 100644 --- a/src/mbgl/annotation/fill_annotation_impl.cpp +++ b/src/mbgl/annotation/fill_annotation_impl.cpp @@ -9,7 +9,7 @@ using namespace style; FillAnnotationImpl::FillAnnotationImpl(AnnotationID id_, FillAnnotation annotation_, uint8_t maxZoom_) : ShapeAnnotationImpl(id_, maxZoom_), - annotation(std::move(annotation_)) { + annotation({ ShapeAnnotationGeometry::visit(annotation_.geometry, CloseShapeAnnotation{}), annotation_.opacity, annotation_.color, annotation_.outlineColor }) { } void FillAnnotationImpl::updateStyle(Style& style) const { diff --git a/src/mbgl/annotation/line_annotation_impl.cpp b/src/mbgl/annotation/line_annotation_impl.cpp index bc7b8df50e..f18ca9fadc 100644 --- a/src/mbgl/annotation/line_annotation_impl.cpp +++ b/src/mbgl/annotation/line_annotation_impl.cpp @@ -9,7 +9,7 @@ using namespace style; LineAnnotationImpl::LineAnnotationImpl(AnnotationID id_, LineAnnotation annotation_, uint8_t maxZoom_) : ShapeAnnotationImpl(id_, maxZoom_), - annotation(std::move(annotation_)) { + annotation({ ShapeAnnotationGeometry::visit(annotation_.geometry, CloseShapeAnnotation{}), annotation_.opacity, annotation_.width, annotation_.color }) { } void LineAnnotationImpl::updateStyle(Style& style) const { diff --git a/src/mbgl/annotation/shape_annotation_impl.cpp b/src/mbgl/annotation/shape_annotation_impl.cpp index f22debdd81..620b1acc76 100644 --- a/src/mbgl/annotation/shape_annotation_impl.cpp +++ b/src/mbgl/annotation/shape_annotation_impl.cpp @@ -1,5 +1,3 @@ -#include <mapbox/geojsonvt/convert.hpp> - #include <mbgl/annotation/shape_annotation_impl.hpp> #include <mbgl/annotation/annotation_tile.hpp> #include <mbgl/tile/tile_id.hpp> @@ -7,6 +5,7 @@ #include <mbgl/math/clamp.hpp> #include <mbgl/util/string.hpp> #include <mbgl/util/constants.hpp> +#include <mbgl/util/geometry.hpp> namespace mbgl { @@ -19,86 +18,16 @@ ShapeAnnotationImpl::ShapeAnnotationImpl(const AnnotationID id_, const uint8_t m layerID("com.mapbox.annotations.shape." + util::toString(id)) { } -struct ToGeoJSONVT { - const double tolerance; - - ToGeoJSONVT(const double tolerance_) - : tolerance(tolerance_) { - } - - geojsonvt::ProjectedFeature operator()(const LineString<double>& line) const { - geojsonvt::ProjectedRings converted; - converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::LineString, line)); - return convertFeature(geojsonvt::ProjectedFeatureType::LineString, converted); - } - - geojsonvt::ProjectedFeature operator()(const Polygon<double>& polygon) const { - geojsonvt::ProjectedRings converted; - for (const auto& ring : polygon) { - converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::Polygon, ring)); - } - return convertFeature(geojsonvt::ProjectedFeatureType::Polygon, converted); - } - - geojsonvt::ProjectedFeature operator()(const MultiLineString<double>& lines) const { - geojsonvt::ProjectedRings converted; - for (const auto& line : lines) { - converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::LineString, line)); - } - return convertFeature(geojsonvt::ProjectedFeatureType::LineString, converted); - } - - geojsonvt::ProjectedFeature operator()(const MultiPolygon<double>& polygons) const { - geojsonvt::ProjectedRings converted; - for (const auto& polygon : polygons) { - for (const auto& ring : polygon) { - converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::Polygon, ring)); - } - } - return convertFeature(geojsonvt::ProjectedFeatureType::Polygon, converted); - } - -private: - geojsonvt::LonLat convertPoint(const Point<double>& p) const { - return { - util::wrap(p.x, -util::LONGITUDE_MAX, util::LONGITUDE_MAX), - util::clamp(p.y, -util::LATITUDE_MAX, util::LATITUDE_MAX) - }; - } - - geojsonvt::ProjectedRing convertPoints(geojsonvt::ProjectedFeatureType type, const std::vector<Point<double>>& points) const { - std::vector<geojsonvt::LonLat> converted; - - for (const auto& p : points) { - converted.push_back(convertPoint(p)); - } - - assert(points.size() > 0); - if (type == geojsonvt::ProjectedFeatureType::Polygon && points.size() > 0 && points.front() != points.back()) { - converted.push_back(converted.front()); - } - - return geojsonvt::Convert::projectRing(converted, tolerance); - } - - geojsonvt::ProjectedFeature convertFeature(geojsonvt::ProjectedFeatureType type, const geojsonvt::ProjectedRings& rings) const { - return geojsonvt::Convert::create(geojsonvt::Tags(), type, rings); - } -}; - void ShapeAnnotationImpl::updateTileData(const CanonicalTileID& tileID, AnnotationTileData& data) { static const double baseTolerance = 4; if (!shapeTiler) { - const uint64_t maxAmountOfTileFeatures = (1ull << maxZoom) * util::EXTENT; - const double tolerance = baseTolerance / maxAmountOfTileFeatures; - - std::vector<geojsonvt::ProjectedFeature> features = { - ShapeAnnotationGeometry::visit(geometry(), ToGeoJSONVT(tolerance)) - }; - + mapbox::geometry::feature_collection<double> features; + features.emplace_back(ShapeAnnotationGeometry::visit(geometry(), [] (auto&& geom) { + return Feature(std::move(geom)); + })); mapbox::geojsonvt::Options options; - options.maxZoom = maxZoom; + options.maxZoom = util::clamp<uint8_t>(maxZoom, 0, 18); options.buffer = 255u; options.extent = util::EXTENT; options.tolerance = baseTolerance; @@ -106,34 +35,20 @@ void ShapeAnnotationImpl::updateTileData(const CanonicalTileID& tileID, Annotati } const auto& shapeTile = shapeTiler->getTile(tileID.z, tileID.x, tileID.y); - if (!shapeTile) + if (shapeTile.features.empty()) return; AnnotationTileLayer& layer = *data.layers.emplace(layerID, std::make_unique<AnnotationTileLayer>(layerID)).first->second; - for (auto& shapeFeature : shapeTile.features) { - FeatureType featureType = FeatureType::Unknown; - - if (shapeFeature.type == geojsonvt::TileFeatureType::LineString) { - featureType = FeatureType::LineString; - } else if (shapeFeature.type == geojsonvt::TileFeatureType::Polygon) { - featureType = FeatureType::Polygon; - } + ToGeometryCollection toGeometryCollection; + ToFeatureType toFeatureType; + for (const auto& shapeFeature : shapeTile.features) { + FeatureType featureType = apply_visitor(toFeatureType, shapeFeature.geometry); + GeometryCollection renderGeometry = apply_visitor(toGeometryCollection, shapeFeature.geometry); assert(featureType != FeatureType::Unknown); - GeometryCollection renderGeometry; - for (auto& shapeRing : shapeFeature.tileGeometry.get<geojsonvt::TileRings>()) { - GeometryCoordinates renderLine; - - for (auto& shapePoint : shapeRing) { - renderLine.emplace_back(shapePoint.x, shapePoint.y); - } - - renderGeometry.push_back(renderLine); - } - // https://github.com/mapbox/geojson-vt-cpp/issues/44 if (featureType == FeatureType::Polygon) { renderGeometry = fixupPolygons(renderGeometry); diff --git a/src/mbgl/annotation/shape_annotation_impl.hpp b/src/mbgl/annotation/shape_annotation_impl.hpp index 1b8fcd5777..800b4ec313 100644 --- a/src/mbgl/annotation/shape_annotation_impl.hpp +++ b/src/mbgl/annotation/shape_annotation_impl.hpp @@ -3,6 +3,7 @@ #include <mapbox/geojsonvt.hpp> #include <mbgl/annotation/annotation.hpp> +#include <mbgl/util/geometry.hpp> #include <string> #include <memory> @@ -32,4 +33,33 @@ public: std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> shapeTiler; }; +struct CloseShapeAnnotation { + ShapeAnnotationGeometry operator()(const mbgl::LineString<double> &geom) const { + return geom; + } + ShapeAnnotationGeometry operator()(const mbgl::MultiLineString<double> &geom) const { + return geom; + } + ShapeAnnotationGeometry operator()(const mbgl::Polygon<double> &geom) const { + mbgl::Polygon<double> closed = geom; + for (auto &ring : closed) { + if (!ring.empty() && ring.front() != ring.back()) { + ring.emplace_back(ring.front()); + } + } + return closed; + } + ShapeAnnotationGeometry operator()(const mbgl::MultiPolygon<double> &geom) const { + mbgl::MultiPolygon<double> closed = geom; + for (auto &polygon : closed) { + for (auto &ring : polygon) { + if (!ring.empty() && ring.front() != ring.back()) { + ring.emplace_back(ring.front()); + } + } + } + return closed; + } +}; + } // namespace mbgl diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp index b9744d193a..d71df28378 100644 --- a/src/mbgl/style/sources/geojson_source_impl.cpp +++ b/src/mbgl/style/sources/geojson_source_impl.cpp @@ -6,6 +6,8 @@ #include <mbgl/platform/log.hpp> #include <mbgl/util/rapidjson.hpp> +#include <mapbox/geojson.hpp> +#include <mapbox/geojson/rapidjson.hpp> #include <mapbox/geojsonvt.hpp> #include <mapbox/geojsonvt/convert.hpp> @@ -18,6 +20,7 @@ using namespace mapbox::geojsonvt; namespace mbgl { namespace style { namespace conversion { + template <> Result<GeoJSON> convertGeoJSON(const JSValue& value) { Options options; @@ -25,7 +28,8 @@ Result<GeoJSON> convertGeoJSON(const JSValue& value) { options.extent = util::EXTENT; try { - return GeoJSON { std::make_unique<GeoJSONVT>(Convert::convert(value, 0), options) }; + const auto geojson = mapbox::geojson::convert(value); + return GeoJSON { std::make_unique<GeoJSONVT>(geojson, options) }; } catch (const std::exception& ex) { return Error { ex.what() }; } @@ -82,7 +86,8 @@ void GeoJSONSource::Impl::load(FileSource& fileSource) { Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", geoJSON.error().message); // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for // tiles to load. - urlOrGeoJSON = GeoJSON { std::make_unique<GeoJSONVT>(std::vector<ProjectedFeature>()) }; + mapbox::geojson::feature_collection features; + urlOrGeoJSON = GeoJSON { std::make_unique<GeoJSONVT>(features) }; } else { urlOrGeoJSON = std::move(*geoJSON); } diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp index e2f8b69e4d..0dc4ac9107 100644 --- a/src/mbgl/tile/geojson_tile.cpp +++ b/src/mbgl/tile/geojson_tile.cpp @@ -11,16 +11,16 @@ namespace mbgl { class GeoJSONTileFeature : public GeometryTileFeature { public: - GeoJSONTileFeature(FeatureType, GeometryCollection&&, Feature::property_map&&); + GeoJSONTileFeature(FeatureType, GeometryCollection&&, PropertyMap&&); FeatureType getType() const override; optional<Value> getValue(const std::string&) const override; - Feature::property_map getProperties() const override { return properties; } + PropertyMap getProperties() const override { return properties; } GeometryCollection getGeometries() const override; private: const FeatureType type; const GeometryCollection geometries; - const Feature::property_map properties; + const PropertyMap properties; }; class GeoJSONTileLayer : public GeometryTileLayer { @@ -49,52 +49,28 @@ private: std::unique_ptr<GeoJSONTileData> convertTile(const mapbox::geojsonvt::Tile& tile) { std::shared_ptr<GeoJSONTileLayer> layer; - if (tile) { + if (!tile.features.empty()) { std::vector<std::shared_ptr<const GeoJSONTileFeature>> features; GeometryCoordinates line; + ToFeatureType toFeatureType; + ToGeometryCollection toGeometryCollection; + for (auto& feature : tile.features) { - const FeatureType featureType = - (feature.type == mapbox::geojsonvt::TileFeatureType::Point - ? FeatureType::Point - : (feature.type == mapbox::geojsonvt::TileFeatureType::LineString - ? FeatureType::LineString - : (feature.type == mapbox::geojsonvt::TileFeatureType::Polygon - ? FeatureType::Polygon - : FeatureType::Unknown))); + const FeatureType featureType = apply_visitor(toFeatureType, feature.geometry); + if (featureType == FeatureType::Unknown) { continue; } - GeometryCollection geometry; - - // Flatten the geometry; GeoJSONVT distinguishes between a Points array and Rings array - // (Points = GeoJSON types Point, MultiPoint, LineString) - // (Rings = GeoJSON types MultiLineString, Polygon, MultiPolygon) - // However, in Mapbox GL, we use one structure for both types, and just have one outer - // element for Points. - if (feature.tileGeometry.is<mapbox::geojsonvt::TilePoints>()) { - line.clear(); - for (auto& point : feature.tileGeometry.get<mapbox::geojsonvt::TilePoints>()) { - line.emplace_back(point.x, point.y); - } - geometry.emplace_back(std::move(line)); - } else if (feature.tileGeometry.is<mapbox::geojsonvt::TileRings>()) { - for (auto& ring : feature.tileGeometry.get<mapbox::geojsonvt::TileRings>()) { - line.clear(); - for (auto& point : ring) { - line.emplace_back(point.x, point.y); - } - geometry.emplace_back(std::move(line)); - } - } + GeometryCollection geometry = apply_visitor(toGeometryCollection, feature.geometry); // https://github.com/mapbox/geojson-vt-cpp/issues/44 if (featureType == FeatureType::Polygon) { geometry = fixupPolygons(geometry); } - Feature::property_map properties{ feature.tags.begin(), feature.tags.end() }; + PropertyMap properties = feature.properties; features.emplace_back(std::make_shared<GeoJSONTileFeature>( featureType, std::move(geometry), std::move(properties))); @@ -118,7 +94,7 @@ void GeoJSONTile::setNecessity(Necessity) {} GeoJSONTileFeature::GeoJSONTileFeature(FeatureType type_, GeometryCollection&& geometries_, - Feature::property_map&& properties_) + PropertyMap&& properties_) : type(type_), geometries(std::move(geometries_)), properties(std::move(properties_)) { } diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp index 1dc22e0c55..4055a80ecf 100644 --- a/src/mbgl/tile/geometry_tile_data.hpp +++ b/src/mbgl/tile/geometry_tile_data.hpp @@ -14,6 +14,7 @@ #include <vector> #include <unordered_map> #include <functional> +#include <iostream> namespace mbgl { @@ -41,8 +42,8 @@ public: virtual ~GeometryTileFeature() = default; virtual FeatureType getType() const = 0; virtual optional<Value> getValue(const std::string& key) const = 0; - virtual Feature::property_map getProperties() const { return Feature::property_map(); } - virtual optional<uint64_t> getID() const { return {}; } + virtual PropertyMap getProperties() const { return PropertyMap(); } + virtual optional<FeatureIdentifier> getID() const { return {}; } virtual GeometryCollection getGeometries() const = 0; }; @@ -73,4 +74,70 @@ Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&); // The result is guaranteed to have correctly wound, strictly simple rings. GeometryCollection fixupPolygons(const GeometryCollection&); +struct ToGeometryCollection { + GeometryCollection operator()(const mapbox::geometry::point<int16_t>& geom) const { + return { { geom } }; + } + GeometryCollection operator()(const mapbox::geometry::multi_point<int16_t>& geom) const { + GeometryCoordinates coordinates; + coordinates.reserve(geom.size()); + for (const auto& point : geom) { + coordinates.emplace_back(point); + } + return { coordinates }; + } + GeometryCollection operator()(const mapbox::geometry::line_string<int16_t>& geom) const { + GeometryCoordinates coordinates; + coordinates.reserve(geom.size()); + for (const auto& point : geom) { + coordinates.emplace_back(point); + } + return { coordinates }; + } + GeometryCollection operator()(const mapbox::geometry::multi_line_string<int16_t>& geom) const { + GeometryCollection collection; + collection.reserve(geom.size()); + for (const auto& ring : geom) { + GeometryCoordinates coordinates; + coordinates.reserve(ring.size()); + for (const auto& point : ring) { + coordinates.emplace_back(point); + } + collection.push_back(std::move(coordinates)); + } + return collection; + } + GeometryCollection operator()(const mapbox::geometry::polygon<int16_t>& geom) const { + GeometryCollection collection; + collection.reserve(geom.size()); + for (const auto& ring : geom) { + GeometryCoordinates coordinates; + coordinates.reserve(ring.size()); + for (const auto& point : ring) { + coordinates.emplace_back(point); + } + collection.push_back(std::move(coordinates)); + } + return collection; + } + GeometryCollection operator()(const mapbox::geometry::multi_polygon<int16_t>& geom) const { + GeometryCollection collection; + for (auto& polygon : geom) { + for (auto& ring : polygon) { + GeometryCoordinates coordinates; + coordinates.reserve(ring.size()); + for (auto& point : ring) { + coordinates.emplace_back(point); + } + collection.push_back(std::move(coordinates)); + } + } + return collection; + } + GeometryCollection operator()(const mapbox::geometry::geometry_collection<int16_t>&) const { + GeometryCollection collection; + return collection; + } +}; + } // namespace mbgl diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp index 1f924a45e1..6a3c51c05d 100644 --- a/src/mbgl/tile/vector_tile.cpp +++ b/src/mbgl/tile/vector_tile.cpp @@ -24,12 +24,12 @@ public: FeatureType getType() const override { return type; } optional<Value> getValue(const std::string&) const override; std::unordered_map<std::string,Value> getProperties() const override; - optional<uint64_t> getID() const override; + optional<FeatureIdentifier> getID() const override; GeometryCollection getGeometries() const override; private: const VectorTileLayer& layer; - optional<uint64_t> id; + optional<FeatureIdentifier> id; FeatureType type = FeatureType::Unknown; packed_iter_type tags_iter; packed_iter_type geometry_iter; @@ -120,7 +120,7 @@ VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const Ve while (feature_pbf.next()) { switch (feature_pbf.tag()) { case 1: // id - id = feature_pbf.get_uint64(); + id = { feature_pbf.get_uint64() }; break; case 2: // tags tags_iter = feature_pbf.get_packed_uint32(); @@ -185,7 +185,7 @@ std::unordered_map<std::string,Value> VectorTileFeature::getProperties() const { return properties; } -optional<uint64_t> VectorTileFeature::getID() const { +optional<FeatureIdentifier> VectorTileFeature::getID() const { return id; } diff --git a/test/fixtures/style_parser/geojson-data-inline.style.json b/test/fixtures/style_parser/geojson-data-inline.style.json index fc4fe97c78..a5d19eea60 100644 --- a/test/fixtures/style_parser/geojson-data-inline.style.json +++ b/test/fixtures/style_parser/geojson-data-inline.style.json @@ -3,7 +3,7 @@ "sources": { "mapbox": { "type": "geojson", - "data": { "type": "Feature", "geometry": { "type": "Point", "coordinates": [100.0, 0.0] } } + "data": { "type": "Feature", "geometry": { "type": "Point", "coordinates": [100.0, 0.0] }, "properties": {} } } } } diff --git a/test/style/filter.cpp b/test/style/filter.cpp index 2d26a8eb61..53504d84ae 100644 --- a/test/style/filter.cpp +++ b/test/style/filter.cpp @@ -8,20 +8,16 @@ #include <rapidjson/document.h> -#include <map> - using namespace mbgl; using namespace mbgl::style; -typedef std::multimap<std::string, mbgl::Value> Properties; - Filter parse(const char * expression) { rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc; doc.Parse<0>(expression); return *conversion::convert<Filter>(doc); } -bool evaluate(const Filter& filter, const Properties& properties, FeatureType type = FeatureType::Unknown) { +bool evaluate(const Filter& filter, const PropertyMap& properties, FeatureType type = FeatureType::Unknown) { return filter(type, [&] (const std::string& key) -> optional<Value> { auto it = properties.find(key); if (it == properties.end()) @@ -47,6 +43,7 @@ TEST(Filter, EqualsNumber) { ASSERT_FALSE(evaluate(f, {{ "foo", std::string("0") }})); ASSERT_FALSE(evaluate(f, {{ "foo", false }})); ASSERT_FALSE(evaluate(f, {{ "foo", true }})); + ASSERT_FALSE(evaluate(f, {{ "foo", nullptr }})); ASSERT_FALSE(evaluate(f, {{}})); } |