diff options
author | Young Hahn <young@mapbox.com> | 2016-07-06 17:29:34 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-06 17:29:34 -0400 |
commit | 71a3b1d0db170cfc1786be88c3e7b286c50dece9 (patch) | |
tree | 1d51cc28946dc990f8f613795417cb76ea8c00df /src | |
parent | 903d609b40b6d0f4873f7bb46d96f4a06d7b17d6 (diff) | |
download | qtlocation-mapboxgl-71a3b1d0db170cfc1786be88c3e7b286c50dece9.tar.gz |
[core] geometry@0.8.0 / geojsonvt@6.0.0 (#5514)
* [core] geometry.hpp 0.8.0
* geojsonvt @ 6.0.0
* Update platform deps, build scripts
* Perf optimizations/cleanup
* Rebase in geometry@080
* D.R.Y. etc
* Ensure fill annotation geometries have closed rings.
* Optimizations
* Update to geojsonvt @ 6.1.0 for clean handoff between geojson parsing and geojsonvt
* Apply close multi/poly geoms for line annotations as well
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/annotation/fill_annotation_impl.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/annotation/line_annotation_impl.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/annotation/shape_annotation_impl.cpp | 109 | ||||
-rw-r--r-- | src/mbgl/annotation/shape_annotation_impl.hpp | 30 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source_impl.cpp | 9 | ||||
-rw-r--r-- | src/mbgl/tile/geojson_tile.cpp | 48 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_data.hpp | 71 | ||||
-rw-r--r-- | src/mbgl/tile/vector_tile.cpp | 8 |
8 files changed, 136 insertions, 143 deletions
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; } |