summaryrefslogtreecommitdiff
path: root/src/mbgl/tile/geojson_tile.cpp
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2015-12-09 16:24:51 -0800
committerKonstantin Käfer <mail@kkaefer.com>2015-12-11 16:23:42 -0800
commit0f9922cff59772375d81202a43284b732b6aacb3 (patch)
treec2fb557962ddbaddf7269ac39e55b02a96c3e63d /src/mbgl/tile/geojson_tile.cpp
parent2f973d0a7e29bdaaa0fc8f2b13d040ef0c189544 (diff)
downloadqtlocation-mapboxgl-0f9922cff59772375d81202a43284b732b6aacb3.tar.gz
[core] create GeoJSON tiles from inline GeoJSON in sources
Diffstat (limited to 'src/mbgl/tile/geojson_tile.cpp')
-rw-r--r--src/mbgl/tile/geojson_tile.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp
new file mode 100644
index 0000000000..9f14780ca4
--- /dev/null
+++ b/src/mbgl/tile/geojson_tile.cpp
@@ -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