summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYoung Hahn <young@mapbox.com>2016-07-06 17:29:34 -0400
committerGitHub <noreply@github.com>2016-07-06 17:29:34 -0400
commit71a3b1d0db170cfc1786be88c3e7b286c50dece9 (patch)
tree1d51cc28946dc990f8f613795417cb76ea8c00df /src
parent903d609b40b6d0f4873f7bb46d96f4a06d7b17d6 (diff)
downloadqtlocation-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.cpp2
-rw-r--r--src/mbgl/annotation/line_annotation_impl.cpp2
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.cpp109
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.hpp30
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp9
-rw-r--r--src/mbgl/tile/geojson_tile.cpp48
-rw-r--r--src/mbgl/tile/geometry_tile_data.hpp71
-rw-r--r--src/mbgl/tile/vector_tile.cpp8
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;
}