Files
MapLibreParticleLab/src/mbgl/tile/geometry_tile_data.hpp
Tim Sylvester 29428dce42 Add support for parsing MLT-format vector tile sources (#3246)
Co-authored-by: Bart Louwers <bart@emeel.net>
Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
2025-10-31 17:24:12 -07:00

149 lines
5.5 KiB
C++

#pragma once
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/feature.hpp>
#include <cstdint>
#include <memory>
#include <span>
#include <string>
#include <vector>
namespace mlt {
class MapLibreTile;
}
namespace mbgl {
class CanonicalTileID;
// Normalized vector tile coordinates.
// Each geometry coordinate represents a point in a bidimensional space,
// varying from -V...0...+V, where V is the maximum extent applicable.
using GeometryCoordinate = Point<int16_t>;
class GeometryCoordinates : public std::vector<GeometryCoordinate> {
public:
using coordinate_type = int16_t;
template <class... Args>
GeometryCoordinates(Args&&... args)
: std::vector<GeometryCoordinate>(std::forward<Args>(args)...) {}
GeometryCoordinates(std::initializer_list<GeometryCoordinate> args)
: std::vector<GeometryCoordinate>(args) {}
GeometryCoordinates() = default;
};
class GeometryCollection : public std::vector<GeometryCoordinates> {
public:
using coordinate_type = int16_t;
template <class... Args>
GeometryCollection(Args&&... args)
: std::vector<GeometryCoordinates>(std::forward<Args>(args)...) {}
GeometryCollection(std::initializer_list<GeometryCoordinates> args)
: std::vector<GeometryCoordinates>(args) {}
GeometryCollection(GeometryCollection&&) = default;
GeometryCollection& operator=(GeometryCollection&&) = default;
GeometryCollection() = default;
GeometryCollection clone() const { return GeometryCollection(*this); }
const auto& getTriangles() const { return triangles; }
void setTriangles(std::shared_ptr<const mlt::MapLibreTile> owner, std::span<const std::uint32_t> triangles_) {
triangleOwner = std::move(owner);
triangles = triangles_;
}
private:
GeometryCollection(const GeometryCollection&) = default;
std::shared_ptr<const mlt::MapLibreTile> triangleOwner;
std::span<const std::uint32_t> triangles = {};
};
class GeometryTileFeature {
public:
virtual ~GeometryTileFeature() = default;
virtual FeatureType getType() const = 0;
virtual std::optional<Value> getValue(const std::string& key) const = 0;
virtual const PropertyMap& getProperties() const;
virtual FeatureIdentifier getID() const { return NullValue{}; }
virtual const GeometryCollection& getGeometries() const;
};
class GeometryTileLayer {
public:
virtual ~GeometryTileLayer() = default;
virtual std::size_t featureCount() const = 0;
// Returns the feature object at the given position within the layer. The
// returned feature object may *not* outlive the layer object.
virtual std::unique_ptr<GeometryTileFeature> getFeature(std::size_t) const = 0;
virtual std::string getName() const = 0;
};
class GeometryTileData {
public:
virtual ~GeometryTileData() = default;
virtual std::unique_ptr<GeometryTileData> clone() const = 0;
// Returns the layer with the given name. The returned layer object *may*
// outlive the data object.
virtual std::unique_ptr<GeometryTileLayer> getLayer(const std::string&) const = 0;
};
// classifies an array of rings into polygons with outer rings and holes
std::vector<GeometryCollection> classifyRings(const GeometryCollection&);
// Truncate polygon to the largest `maxHoles` inner rings by area.
void limitHoles(GeometryCollection&, uint32_t maxHoles);
Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID);
GeometryCollection convertGeometry(const Feature::geometry_type& geometryTileFeature, const CanonicalTileID& tileID);
// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature)
Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
// Fix up possibly-non-V2-compliant polygon geometry using angus clipper.
// The result is guaranteed to have correctly wound, strictly simple rings.
GeometryCollection fixupPolygons(const GeometryCollection&);
struct ToGeometryCollection {
GeometryCollection operator()(const mapbox::geometry::empty&) const { return GeometryCollection(); }
GeometryCollection operator()(const mapbox::geometry::point<int16_t>& geom) const { return {{geom}}; }
GeometryCollection operator()(const mapbox::geometry::multi_point<int16_t>& geom) const { return {geom}; }
GeometryCollection operator()(const mapbox::geometry::line_string<int16_t>& geom) const { return {geom}; }
GeometryCollection operator()(const mapbox::geometry::multi_line_string<int16_t>& geom) const {
GeometryCollection collection;
collection.reserve(geom.size());
for (const auto& ring : geom) {
collection.emplace_back(ring);
}
return collection;
}
GeometryCollection operator()(const mapbox::geometry::polygon<int16_t>& geom) const {
GeometryCollection collection;
collection.reserve(geom.size());
for (const auto& ring : geom) {
collection.emplace_back(ring);
}
return collection;
}
GeometryCollection operator()(const mapbox::geometry::multi_polygon<int16_t>& geom) const {
GeometryCollection collection;
for (const auto& polygon : geom) {
for (const auto& ring : polygon) {
collection.emplace_back(ring);
}
}
return collection;
}
GeometryCollection operator()(const mapbox::geometry::geometry_collection<int16_t>&) const {
GeometryCollection collection;
return collection;
}
};
} // namespace mbgl