This repository has been archived by the owner on Aug 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[core] create GeoJSON tiles from inline GeoJSON in sources
- Loading branch information
Showing
6 changed files
with
231 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#include <mbgl/tile/geojson_tile.hpp> | ||
#include <mbgl/storage/file_source.hpp> | ||
#include <mapbox/geojsonvt.hpp> | ||
|
||
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; | ||
} | ||
|
||
mapbox::util::optional<Value> GeoJSONTileFeature::getValue(const std::string& key) const { | ||
auto it = tags.find(key); | ||
if (it != tags.end()) { | ||
return mapbox::util::optional<Value>(it->second); | ||
} | ||
return mapbox::util::optional<Value>(); | ||
} | ||
|
||
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<const GeometryTileFeature> GeoJSONTileLayer::getFeature(std::size_t i) const { | ||
return features[i]; | ||
} | ||
|
||
GeoJSONTile::GeoJSONTile(std::shared_ptr<GeoJSONTileLayer> layer_) : layer(std::move(layer_)) { | ||
} | ||
|
||
util::ptr<GeometryTileLayer> 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<GeoJSONTile> convertTile(const mapbox::geojsonvt::Tile& tile) { | ||
std::shared_ptr<GeoJSONTileLayer> layer; | ||
|
||
if (tile) { | ||
std::vector<std::shared_ptr<const GeoJSONTileFeature>> features; | ||
std::vector<Coordinate> 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<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)); | ||
} | ||
} | ||
|
||
GeoJSONTileFeature::Tags tags{ feature.tags.begin(), feature.tags.end() }; | ||
|
||
features.emplace_back(std::make_shared<GeoJSONTileFeature>( | ||
featureType, std::move(geometry), std::move(tags))); | ||
} | ||
|
||
layer = std::make_unique<GeoJSONTileLayer>(std::move(features)); | ||
} | ||
|
||
return std::make_unique<GeoJSONTile>(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), Seconds::zero(), Seconds::zero()); | ||
} | ||
} | ||
|
||
std::unique_ptr<FileRequest> | ||
GeoJSONTileMonitor::monitorTile(const GeometryTileMonitor::Callback& cb) { | ||
callback = cb; | ||
update(); | ||
return nullptr; | ||
} | ||
|
||
} // namespace mbgl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#ifndef MBGL_ANNOTATION_GEOJSON_VT_TILE | ||
#define MBGL_ANNOTATION_GEOJSON_VT_TILE | ||
|
||
#include <mbgl/map/geometry_tile.hpp> | ||
#include <mbgl/map/tile_id.hpp> | ||
|
||
#include <unordered_map> | ||
|
||
namespace mapbox { | ||
namespace geojsonvt { | ||
class GeoJSONVT; | ||
} // namespace geojsonvt | ||
} // namespace mapbox | ||
|
||
namespace mbgl { | ||
|
||
// Implements a simple in-memory Tile type that holds GeoJSON values. A GeoJSON tile can only have | ||
// one layer, and it is always returned regardless of which layer is requested. | ||
|
||
class GeoJSONTileFeature : public GeometryTileFeature { | ||
public: | ||
using Tags = std::unordered_map<std::string, std::string>; | ||
|
||
GeoJSONTileFeature(FeatureType, GeometryCollection&&, Tags&& = {}); | ||
FeatureType getType() const override; | ||
mapbox::util::optional<Value> getValue(const std::string&) const override; | ||
GeometryCollection getGeometries() const override; | ||
|
||
private: | ||
const FeatureType type; | ||
const GeometryCollection geometries; | ||
const Tags tags; | ||
}; | ||
|
||
class GeoJSONTileLayer : public GeometryTileLayer { | ||
public: | ||
using Features = std::vector<std::shared_ptr<const GeoJSONTileFeature>>; | ||
|
||
GeoJSONTileLayer(Features&&); | ||
std::size_t featureCount() const override; | ||
util::ptr<const GeometryTileFeature> getFeature(std::size_t) const override; | ||
|
||
private: | ||
const Features features; | ||
}; | ||
|
||
class GeoJSONTile : public GeometryTile { | ||
public: | ||
GeoJSONTile(std::shared_ptr<GeoJSONTileLayer>); | ||
util::ptr<GeometryTileLayer> getLayer(const std::string&) const override; | ||
|
||
private: | ||
const std::shared_ptr<GeoJSONTileLayer> layer; | ||
}; | ||
|
||
class GeoJSONTileMonitor : public GeometryTileMonitor { | ||
public: | ||
GeoJSONTileMonitor(mapbox::geojsonvt::GeoJSONVT*, const TileID&); | ||
virtual ~GeoJSONTileMonitor(); | ||
|
||
std::unique_ptr<FileRequest> monitorTile(const GeometryTileMonitor::Callback&) override; | ||
|
||
void setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT*); | ||
|
||
private: | ||
void update(); | ||
|
||
public: | ||
const TileID tileID; | ||
|
||
private: | ||
mapbox::geojsonvt::GeoJSONVT* geojsonvt = nullptr; | ||
GeometryTileMonitor::Callback callback; | ||
}; | ||
|
||
} // namespace mbgl | ||
|
||
#endif |