diff options
Diffstat (limited to 'deps/geojsonvt/6.3.0/include/mapbox/geojsonvt/tile.hpp')
-rw-r--r-- | deps/geojsonvt/6.3.0/include/mapbox/geojsonvt/tile.hpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/deps/geojsonvt/6.3.0/include/mapbox/geojsonvt/tile.hpp b/deps/geojsonvt/6.3.0/include/mapbox/geojsonvt/tile.hpp new file mode 100644 index 0000000000..ccb230bb9c --- /dev/null +++ b/deps/geojsonvt/6.3.0/include/mapbox/geojsonvt/tile.hpp @@ -0,0 +1,207 @@ +#pragma once + +#include <algorithm> +#include <cmath> +#include <mapbox/geojsonvt/types.hpp> + +namespace mapbox { +namespace geojsonvt { + +struct Tile { + mapbox::geometry::feature_collection<int16_t> features; + uint32_t num_points = 0; + uint32_t num_simplified = 0; +}; + +namespace detail { + +class InternalTile { +public: + const uint8_t z; + const uint32_t x; + const uint32_t y; + + vt_features source_features; + bool is_solid = false; + mapbox::geometry::box<double> bbox = { { 2, 1 }, { -1, 0 } }; + + Tile tile; + + InternalTile(const vt_features& source, + const uint8_t z_, + const uint32_t x_, + const uint32_t y_, + const uint16_t extent_, + const uint16_t buffer, + const double tolerance_) + : z(z_), + x(x_), + y(y_), + z2(std::pow(2, z)), + extent(extent_), + tolerance(tolerance_), + sq_tolerance(tolerance_ * tolerance_) { + + for (const auto& feature : source) { + const auto& geom = feature.geometry; + const auto& props = feature.properties; + const auto& id = feature.id; + + tile.num_points += feature.num_points; + + vt_geometry::visit(geom, [&](const auto& g) { + // `this->` is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636 + this->addFeature(g, props, id); + }); + + bbox.min.x = std::min(feature.bbox.min.x, bbox.min.x); + bbox.min.y = std::min(feature.bbox.min.y, bbox.min.y); + bbox.max.x = std::max(feature.bbox.max.x, bbox.max.x); + bbox.max.y = std::max(feature.bbox.max.y, bbox.max.y); + } + + is_solid = isSolid(buffer); + } + +private: + const double z2; + const uint16_t extent; + const double tolerance; + const double sq_tolerance; + + bool isSolid(const uint16_t buffer) { + if (tile.features.size() != 1) + return false; + + const auto& geom = tile.features.front().geometry; + if (!geom.is<mapbox::geometry::polygon<int16_t>>()) + return false; + + const auto& rings = geom.get<mapbox::geometry::polygon<int16_t>>(); + if (rings.size() > 1) + return false; + + const auto& ring = rings.front(); + if (ring.size() != 5) + return false; + + const int16_t min = -static_cast<int16_t>(buffer); + const int16_t max = static_cast<int16_t>(extent + buffer); + for (const auto& p : ring) { + if ((p.x != min && p.x != max) || (p.y != min && p.y != max)) + return false; + } + + return true; + } + + void addFeature(const vt_point& point, const property_map& props, const optional<identifier>& id) { + tile.features.push_back({ transform(point), props, id }); + } + + void addFeature(const vt_line_string& line, const property_map& props, const optional<identifier>& id) { + const auto new_line = transform(line); + if (!new_line.empty()) + tile.features.push_back({ std::move(new_line), props, id }); + } + + void addFeature(const vt_polygon& polygon, const property_map& props, const optional<identifier>& id) { + const auto new_polygon = transform(polygon); + if (!new_polygon.empty()) + tile.features.push_back({ std::move(new_polygon), props, id }); + } + + void addFeature(const vt_geometry_collection& collection, const property_map& props, const optional<identifier>& id) { + for (const auto& geom : collection) { + vt_geometry::visit(geom, [&](const auto& g) { + // `this->` is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636 + this->addFeature(g, props, id); + }); + } + } + + template <class T> + void addFeature(const T& multi, const property_map& props, const optional<identifier>& id) { + const auto new_multi = transform(multi); + + switch (new_multi.size()) { + case 0: + break; + case 1: + tile.features.push_back({ std::move(new_multi[0]), props, id }); + break; + default: + tile.features.push_back({ std::move(new_multi), props, id }); + break; + } + } + + mapbox::geometry::point<int16_t> transform(const vt_point& p) { + ++tile.num_simplified; + return { static_cast<int16_t>(::round((p.x * z2 - x) * extent)), + static_cast<int16_t>(::round((p.y * z2 - y) * extent)) }; + } + + mapbox::geometry::multi_point<int16_t> transform(const vt_multi_point& points) { + mapbox::geometry::multi_point<int16_t> result; + result.reserve(points.size()); + for (const auto& p : points) { + result.push_back(transform(p)); + } + return result; + } + + mapbox::geometry::line_string<int16_t> transform(const vt_line_string& line) { + mapbox::geometry::line_string<int16_t> result; + if (line.dist > tolerance) { + for (const auto& p : line) { + if (p.z > sq_tolerance) + result.push_back(transform(p)); + } + } + return result; + } + + mapbox::geometry::linear_ring<int16_t> transform(const vt_linear_ring& ring) { + mapbox::geometry::linear_ring<int16_t> result; + if (ring.area > sq_tolerance) { + for (const auto& p : ring) { + if (p.z > sq_tolerance) + result.push_back(transform(p)); + } + } + return result; + } + + mapbox::geometry::multi_line_string<int16_t> transform(const vt_multi_line_string& lines) { + mapbox::geometry::multi_line_string<int16_t> result; + for (const auto& line : lines) { + if (line.dist > tolerance) + result.push_back(transform(line)); + } + return result; + } + + mapbox::geometry::polygon<int16_t> transform(const vt_polygon& rings) { + mapbox::geometry::polygon<int16_t> result; + for (const auto& ring : rings) { + if (ring.area > sq_tolerance) + result.push_back(transform(ring)); + } + return result; + } + + mapbox::geometry::multi_polygon<int16_t> transform(const vt_multi_polygon& polygons) { + mapbox::geometry::multi_polygon<int16_t> result; + for (const auto& polygon : polygons) { + const auto p = transform(polygon); + if (!p.empty()) + result.push_back(std::move(p)); + } + return result; + } +}; + +} // namespace detail +} // namespace geojsonvt +} // namespace mapbox |