#include #include #include namespace mbgl { GeoJSONTileFeature::GeoJSONTileFeature(FeatureType type_, GeometryCollection&& geometries_, GeoJSONTileFeature::Tags&& tags_) : type(type_), geometries(std::move(geometries_)), tags(std::move(tags_)) { } FeatureType GeoJSONTileFeature::getType() const { return type; } optional GeoJSONTileFeature::getValue(const std::string& key) const { auto it = tags.find(key); if (it != tags.end()) { return optional(it->second); } return optional(); } GeometryCollection GeoJSONTileFeature::getGeometries() const { return geometries; } GeoJSONTileLayer::GeoJSONTileLayer(Features&& features_) : features(std::move(features_)) { } std::size_t GeoJSONTileLayer::featureCount() const { return features.size(); } util::ptr GeoJSONTileLayer::getFeature(std::size_t i) const { return features[i]; } GeoJSONTile::GeoJSONTile(std::shared_ptr layer_) : layer(std::move(layer_)) { } util::ptr GeoJSONTile::getLayer(const std::string&) const { // We're ignoring the layer name because GeoJSON tiles only have one layer. return layer; } // Converts the geojsonvt::Tile to a a GeoJSONTile. They have a differing internal structure. std::unique_ptr convertTile(const mapbox::geojsonvt::Tile& tile) { std::shared_ptr layer; if (tile) { std::vector> features; GeometryCoordinates line; 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))); 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()) { line.clear(); for (auto& point : feature.tileGeometry.get()) { line.emplace_back(point.x, point.y); } geometry.emplace_back(std::move(line)); } else if (feature.tileGeometry.is()) { for (auto& ring : feature.tileGeometry.get()) { line.clear(); for (auto& point : ring) { line.emplace_back(point.x, point.y); } geometry.emplace_back(std::move(line)); } } GeoJSONTileFeature::Tags tags{ feature.tags.begin(), feature.tags.end() }; features.emplace_back(std::make_shared( featureType, std::move(geometry), std::move(tags))); } layer = std::make_unique(std::move(features)); } return std::make_unique(layer); } GeoJSONTileMonitor::GeoJSONTileMonitor(mapbox::geojsonvt::GeoJSONVT* geojsonvt_, const TileID& id) : tileID(id), geojsonvt(geojsonvt_) { } GeoJSONTileMonitor::~GeoJSONTileMonitor() = default; // A monitor can have its GeoJSONVT object swapped out (e.g. when loading a new GeoJSON file). // In that case, we're sending new notifications to all observers. void GeoJSONTileMonitor::setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT* vt) { // Don't duplicate notifications in case of nil changes. if (geojsonvt != vt) { geojsonvt = vt; update(); } } void GeoJSONTileMonitor::update() { if (geojsonvt) { auto tile = convertTile(geojsonvt->getTile(tileID.z, tileID.x, tileID.y)); callback(nullptr, std::move(tile), {}, {}); } } std::unique_ptr GeoJSONTileMonitor::monitorTile(const GeometryTileMonitor::Callback& cb) { callback = cb; update(); return nullptr; } } // namespace mbgl