summaryrefslogtreecommitdiff
path: root/src/mbgl/tile
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-06-13 10:59:33 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-06-13 10:59:33 -0700
commit5c7dfd948ffd52f2b60dcfe052176da788f17893 (patch)
tree596d02b0e28d6e7649f9527af2834c90c3c3b056 /src/mbgl/tile
parent3ab7c1cca3aa4658b40af1d7d591850e005d011e (diff)
downloadqtlocation-mapboxgl-5c7dfd948ffd52f2b60dcfe052176da788f17893.tar.gz
[core] *Tile ↔ *TileData
Tile is now the main base class; RasterTile, VectorTile, etc are its subclasses. GeometryTileData and its subclasses form the piece that's passed to the worker.
Diffstat (limited to 'src/mbgl/tile')
-rw-r--r--src/mbgl/tile/geojson_tile.cpp32
-rw-r--r--src/mbgl/tile/geojson_tile.hpp13
-rw-r--r--src/mbgl/tile/geometry_tile.cpp324
-rw-r--r--src/mbgl/tile/geometry_tile.hpp121
-rw-r--r--src/mbgl/tile/geometry_tile_data.cpp324
-rw-r--r--src/mbgl/tile/geometry_tile_data.hpp122
-rw-r--r--src/mbgl/tile/raster_tile.cpp (renamed from src/mbgl/tile/raster_tile_data.cpp)26
-rw-r--r--src/mbgl/tile/raster_tile.hpp (renamed from src/mbgl/tile/raster_tile_data.hpp)10
-rw-r--r--src/mbgl/tile/tile.cpp37
-rw-r--r--src/mbgl/tile/tile.hpp (renamed from src/mbgl/tile/tile_data.hpp)18
-rw-r--r--src/mbgl/tile/tile_cache.cpp26
-rw-r--r--src/mbgl/tile/tile_cache.hpp8
-rw-r--r--src/mbgl/tile/tile_data.cpp37
-rw-r--r--src/mbgl/tile/tile_data_observer.hpp18
-rw-r--r--src/mbgl/tile/tile_observer.hpp18
-rw-r--r--src/mbgl/tile/tile_source.hpp2
-rw-r--r--src/mbgl/tile/tile_source_impl.hpp12
-rw-r--r--src/mbgl/tile/tile_worker.cpp10
-rw-r--r--src/mbgl/tile/tile_worker.hpp8
-rw-r--r--src/mbgl/tile/vector_tile.cpp34
-rw-r--r--src/mbgl/tile/vector_tile.hpp14
21 files changed, 604 insertions, 610 deletions
diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp
index 4bea00bb45..b702400d47 100644
--- a/src/mbgl/tile/geojson_tile.cpp
+++ b/src/mbgl/tile/geojson_tile.cpp
@@ -1,5 +1,5 @@
#include <mbgl/tile/geojson_tile.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/update_parameters.hpp>
#include <mapbox/geojsonvt.hpp>
@@ -36,9 +36,9 @@ private:
const Features features;
};
-class GeoJSONTile : public GeometryTile {
+class GeoJSONTileData : public GeometryTileData {
public:
- GeoJSONTile(std::shared_ptr<GeoJSONTileLayer>);
+ GeoJSONTileData(std::shared_ptr<GeoJSONTileLayer>);
util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
private:
@@ -46,7 +46,7 @@ private:
};
// 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::unique_ptr<GeoJSONTileData> convertTile(const mapbox::geojsonvt::Tile& tile) {
std::shared_ptr<GeoJSONTileLayer> layer;
if (tile) {
@@ -103,24 +103,20 @@ std::unique_ptr<GeoJSONTile> convertTile(const mapbox::geojsonvt::Tile& tile) {
layer = std::make_unique<GeoJSONTileLayer>(std::move(features));
}
- return std::make_unique<GeoJSONTile>(layer);
+ return std::make_unique<GeoJSONTileData>(layer);
}
-GeoJSONTileData::GeoJSONTileData(const OverscaledTileID& overscaledTileID,
- std::string sourceID,
- const style::UpdateParameters& parameters,
- mapbox::geojsonvt::GeoJSONVT* geojsonvt)
- : GeometryTileData(overscaledTileID, sourceID, parameters.style, parameters.mode) {
+GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
+ std::string sourceID,
+ const style::UpdateParameters& parameters,
+ mapbox::geojsonvt::GeoJSONVT* geojsonvt)
+ : GeometryTile(overscaledTileID, sourceID, parameters.style, parameters.mode) {
if (geojsonvt) {
- auto tile = convertTile(
- geojsonvt->getTile(id.canonical.z, id.canonical.x, id.canonical.y));
- setData(std::move(tile), {}, {});
+ setData(convertTile(geojsonvt->getTile(id.canonical.z, id.canonical.x, id.canonical.y)), {}, {});
}
}
-GeoJSONTileData::~GeoJSONTileData() = default;
-
-void GeoJSONTileData::setNecessity(Necessity) {}
+void GeoJSONTile::setNecessity(Necessity) {}
GeoJSONTileFeature::GeoJSONTileFeature(FeatureType type_,
GeometryCollection&& geometries_,
@@ -155,10 +151,10 @@ util::ptr<const GeometryTileFeature> GeoJSONTileLayer::getFeature(std::size_t i)
return features[i];
}
-GeoJSONTile::GeoJSONTile(std::shared_ptr<GeoJSONTileLayer> layer_) : layer(std::move(layer_)) {
+GeoJSONTileData::GeoJSONTileData(std::shared_ptr<GeoJSONTileLayer> layer_) : layer(std::move(layer_)) {
}
-util::ptr<GeometryTileLayer> GeoJSONTile::getLayer(const std::string&) const {
+util::ptr<GeometryTileLayer> GeoJSONTileData::getLayer(const std::string&) const {
// We're ignoring the layer name because GeoJSON tiles only have one layer.
return layer;
}
diff --git a/src/mbgl/tile/geojson_tile.hpp b/src/mbgl/tile/geojson_tile.hpp
index 613ef2d962..9cdc705d32 100644
--- a/src/mbgl/tile/geojson_tile.hpp
+++ b/src/mbgl/tile/geojson_tile.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
namespace mapbox {
namespace geojsonvt {
@@ -14,13 +14,12 @@ namespace style {
class UpdateParameters;
}
-class GeoJSONTileData : public GeometryTileData {
+class GeoJSONTile : public GeometryTile {
public:
- GeoJSONTileData(const OverscaledTileID&,
- std::string sourceID,
- const style::UpdateParameters&,
- mapbox::geojsonvt::GeoJSONVT*);
- ~GeoJSONTileData();
+ GeoJSONTile(const OverscaledTileID&,
+ std::string sourceID,
+ const style::UpdateParameters&,
+ mapbox::geojsonvt::GeoJSONVT*);
void setNecessity(Necessity) final;
};
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index f4589b4052..cded448656 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -1,210 +1,206 @@
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/tile/tile_id.hpp>
-
-#include <clipper/clipper.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/tile/tile_source.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/util/worker.hpp>
+#include <mbgl/util/work_request.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/text/collision_tile.hpp>
+#include <mbgl/map/transform_state.hpp>
namespace mbgl {
-static double signedArea(const GeometryCoordinates& ring) {
- double sum = 0;
-
- for (std::size_t i = 0, len = ring.size(), j = len - 1; i < len; j = i++) {
- const GeometryCoordinate& p1 = ring[i];
- const GeometryCoordinate& p2 = ring[j];
- sum += (p2.x - p1.x) * (p1.y + p2.y);
- }
-
- return sum;
+GeometryTile::GeometryTile(const OverscaledTileID& id_,
+ std::string sourceID,
+ style::Style& style_,
+ const MapMode mode_)
+ : Tile(id_),
+ style(style_),
+ worker(style_.workers),
+ tileWorker(id_,
+ sourceID,
+ *style_.spriteStore,
+ *style_.glyphAtlas,
+ *style_.glyphStore,
+ obsolete,
+ mode_) {
}
-static ClipperLib::Path toClipperPath(const GeometryCoordinates& ring) {
- ClipperLib::Path result;
- result.reserve(ring.size());
- for (const auto& p : ring) {
- result.emplace_back(p.x, p.y);
- }
- return result;
+void GeometryTile::setError(std::exception_ptr err) {
+ observer->onTileError(*this, err);
}
-static GeometryCoordinates fromClipperPath(const ClipperLib::Path& path) {
- GeometryCoordinates result;
- result.reserve(path.size());
- for (const auto& p : path) {
- using Coordinate = GeometryCoordinates::coordinate_type;
- assert(p.x >= std::numeric_limits<Coordinate>::min());
- assert(p.x <= std::numeric_limits<Coordinate>::max());
- assert(p.y >= std::numeric_limits<Coordinate>::min());
- assert(p.y <= std::numeric_limits<Coordinate>::max());
- result.emplace_back(Coordinate(p.x), Coordinate(p.y));
+void GeometryTile::setData(std::unique_ptr<GeometryTileData> data_,
+ optional<Timestamp> modified_,
+ optional<Timestamp> expires_) {
+ modified = modified_;
+ expires = expires_;
+
+ if (!data_) {
+ // This is a 404 response. We're treating these as empty tiles.
+ workRequest.reset();
+ availableData = DataAvailability::All;
+ buckets.clear();
+ redoPlacement();
+ observer->onTileLoaded(*this, true);
+ return;
}
- return result;
-}
-
-static void processPolynodeBranch(ClipperLib::PolyNode* polynode, GeometryCollection& rings) {
- // Exterior ring.
- rings.push_back(fromClipperPath(polynode->Contour));
- assert(signedArea(rings.back()) > 0);
- // Interior rings.
- for (auto * ring : polynode->Childs) {
- rings.push_back(fromClipperPath(ring->Contour));
- assert(signedArea(rings.back()) < 0);
+ // Mark the tile as pending again if it was complete before to prevent signaling a complete
+ // state despite pending parse operations.
+ if (availableData == DataAvailability::All) {
+ availableData = DataAvailability::Some;
}
- // PolyNodes may be nested in the case of a polygon inside a hole.
- for (auto * ring : polynode->Childs) {
- for (auto * subRing : ring->Childs) {
- processPolynodeBranch(subRing, rings);
- }
- }
-}
+ // Kick off a fresh parse of this tile. This happens when the tile is new, or
+ // when tile data changed. Replacing the workdRequest will cancel a pending work
+ // request in case there is one.
+ workRequest.reset();
+ workRequest = worker.parseGeometryTile(tileWorker, style.getLayers(), std::move(data_), targetConfig, [this, config = targetConfig] (TileParseResult result) {
+ workRequest.reset();
-GeometryCollection fixupPolygons(const GeometryCollection& rings) {
- ClipperLib::Clipper clipper;
- clipper.StrictlySimple(true);
+ if (result.is<TileParseResultData>()) {
+ auto& resultBuckets = result.get<TileParseResultData>();
+ availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
- for (const auto& ring : rings) {
- clipper.AddPath(toClipperPath(ring), ClipperLib::ptSubject, true);
- }
+ // Persist the configuration we just placed so that we can later check whether we need to
+ // place again in case the configuration has changed.
+ placedConfig = config;
- ClipperLib::PolyTree polygons;
- clipper.Execute(ClipperLib::ctUnion, polygons, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
- clipper.Clear();
+ // Move over all buckets we received in this parse request, potentially overwriting
+ // existing buckets in case we got a refresh parse.
+ buckets = std::move(resultBuckets.buckets);
- GeometryCollection result;
- for (auto * polynode : polygons.Childs) {
- processPolynodeBranch(polynode, result);
- }
- return result;
-}
+ if (isComplete()) {
+ featureIndex = std::move(resultBuckets.featureIndex);
+ data = std::move(resultBuckets.tileData);
+ }
-std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
- std::vector<GeometryCollection> polygons;
+ redoPlacement();
+ observer->onTileLoaded(*this, true);
+ } else {
+ availableData = DataAvailability::All;
+ observer->onTileError(*this, result.get<std::exception_ptr>());
+ }
+ });
+}
- std::size_t len = rings.size();
+GeometryTile::~GeometryTile() {
+ cancel();
+}
- if (len <= 1) {
- polygons.push_back(rings);
- return polygons;
+bool GeometryTile::parsePending() {
+ if (workRequest) {
+ // There's already parsing or placement going on.
+ return false;
}
- GeometryCollection polygon;
- int8_t ccw = 0;
+ workRequest.reset();
+ workRequest = worker.parsePendingGeometryTileLayers(tileWorker, targetConfig, [this, config = targetConfig] (TileParseResult result) {
+ workRequest.reset();
- for (std::size_t i = 0; i < len; i++) {
- double area = signedArea(rings[i]);
+ if (result.is<TileParseResultData>()) {
+ auto& resultBuckets = result.get<TileParseResultData>();
+ availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
- if (area == 0)
- continue;
+ // Move over all buckets we received in this parse request, potentially overwriting
+ // existing buckets in case we got a refresh parse.
+ for (auto& bucket : resultBuckets.buckets) {
+ buckets[bucket.first] = std::move(bucket.second);
+ }
+
+ // Persist the configuration we just placed so that we can later check whether we need to
+ // place again in case the configuration has changed.
+ placedConfig = config;
- if (ccw == 0)
- ccw = (area < 0 ? -1 : 1);
+ if (isComplete()) {
+ featureIndex = std::move(resultBuckets.featureIndex);
+ data = std::move(resultBuckets.tileData);
+ }
- if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) {
- polygons.push_back(polygon);
- polygon.clear();
+ redoPlacement();
+ observer->onTileLoaded(*this, false);
+ } else {
+ availableData = DataAvailability::All;
+ observer->onTileError(*this, result.get<std::exception_ptr>());
}
+ });
+
+ return true;
+}
- polygon.push_back(rings[i]);
+Bucket* GeometryTile::getBucket(const style::Layer& layer) {
+ const auto it = buckets.find(layer.baseImpl->bucketName());
+ if (it == buckets.end()) {
+ return nullptr;
}
- if (!polygon.empty())
- polygons.push_back(polygon);
+ assert(it->second);
+ return it->second.get();
+}
- return polygons;
+void GeometryTile::redoPlacement(const PlacementConfig newConfig) {
+ targetConfig = newConfig;
+ redoPlacement();
}
-void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
- if (polygon.size() > 1 + maxHoles) {
- std::nth_element(polygon.begin() + 1,
- polygon.begin() + 1 + maxHoles,
- polygon.end(),
- [] (const auto& a, const auto& b) {
- return signedArea(a) > signedArea(b);
- });
- polygon.resize(1 + maxHoles);
+void GeometryTile::redoPlacement() {
+ // Don't start a new placement request when the current one hasn't completed yet, or when
+ // we are parsing buckets.
+ if (workRequest || targetConfig == placedConfig) {
+ return;
}
-}
-static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
- const double size = util::EXTENT * std::pow(2, tileID.z);
- const double x0 = util::EXTENT * tileID.x;
- const double y0 = util::EXTENT * tileID.y;
-
- auto tileCoordinatesToLatLng = [&] (const Point<int16_t>& p) {
- double y2 = 180 - (p.y + y0) * 360 / size;
- return Point<double>(
- (p.x + x0) * 360 / size - 180,
- 360.0 / M_PI * std::atan(std::exp(y2 * M_PI / 180)) - 90.0
- );
- };
-
- GeometryCollection geometries = geometryTileFeature.getGeometries();
-
- switch (geometryTileFeature.getType()) {
- case FeatureType::Unknown: {
- assert(false);
- return Point<double>(NAN, NAN);
- }
+ workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, config = targetConfig](std::unique_ptr<CollisionTile> collisionTile) {
+ workRequest.reset();
- case FeatureType::Point: {
- MultiPoint<double> multiPoint;
- for (const auto& p : geometries.at(0)) {
- multiPoint.push_back(tileCoordinatesToLatLng(p));
- }
- if (multiPoint.size() == 1) {
- return multiPoint[0];
- } else {
- return multiPoint;
- }
+ // Persist the configuration we just placed so that we can later check whether we need to
+ // place again in case the configuration has changed.
+ placedConfig = config;
+
+ for (auto& bucket : buckets) {
+ bucket.second->swapRenderData();
}
- case FeatureType::LineString: {
- MultiLineString<double> multiLineString;
- for (const auto& g : geometries) {
- LineString<double> lineString;
- for (const auto& p : g) {
- lineString.push_back(tileCoordinatesToLatLng(p));
- }
- multiLineString.push_back(std::move(lineString));
- }
- if (multiLineString.size() == 1) {
- return multiLineString[0];
- } else {
- return multiLineString;
- }
+ if (featureIndex) {
+ featureIndex->setCollisionTile(std::move(collisionTile));
}
- case FeatureType::Polygon: {
- MultiPolygon<double> multiPolygon;
- for (const auto& pg : classifyRings(geometries)) {
- Polygon<double> polygon;
- for (const auto& r : pg) {
- LinearRing<double> linearRing;
- for (const auto& p : r) {
- linearRing.push_back(tileCoordinatesToLatLng(p));
- }
- polygon.push_back(std::move(linearRing));
- }
- multiPolygon.push_back(std::move(polygon));
- }
- if (multiPolygon.size() == 1) {
- return multiPolygon[0];
- } else {
- return multiPolygon;
- }
+ // The target configuration could have changed since we started placement. In this case,
+ // we're starting another placement run.
+ if (placedConfig != targetConfig) {
+ redoPlacement();
+ } else {
+ observer->onNeedsRepaint();
}
- }
+ });
+}
- // Unreachable, but placate GCC.
- return Point<double>();
+void GeometryTile::queryRenderedFeatures(
+ std::unordered_map<std::string, std::vector<Feature>>& result,
+ const GeometryCoordinates& queryGeometry,
+ const TransformState& transformState,
+ const optional<std::vector<std::string>>& layerIDs) {
+
+ if (!featureIndex || !data) return;
+
+ featureIndex->query(result,
+ { queryGeometry },
+ transformState.getAngle(),
+ util::tileSize * id.overscaleFactor(),
+ std::pow(2, transformState.getZoom() - id.overscaledZ),
+ layerIDs,
+ *data,
+ id.canonical,
+ style);
}
-Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
- Feature feature { convertGeometry(geometryTileFeature, tileID) };
- feature.properties = geometryTileFeature.getProperties();
- feature.id = geometryTileFeature.getID();
- return feature;
+void GeometryTile::cancel() {
+ obsolete = true;
+ workRequest.reset();
}
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index 80d6d6031d..4c5d08ee46 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -1,83 +1,78 @@
#pragma once
-#include <mbgl/util/geometry.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/tile_worker.hpp>
+#include <mbgl/text/placement_config.hpp>
+#include <mbgl/util/atomic.hpp>
#include <mbgl/util/feature.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/ptr.hpp>
-#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/optional.hpp>
-#include <mbgl/util/variant.hpp>
-#include <mbgl/util/constants.hpp>
-
-#include <cstdint>
-#include <string>
-#include <vector>
+
+#include <memory>
#include <unordered_map>
-#include <functional>
namespace mbgl {
-enum class FeatureType : uint8_t {
- Unknown = 0,
- Point = 1,
- LineString = 2,
- Polygon = 3
-};
-
-class CanonicalTileID;
+class AsyncRequest;
+class GeometryTileData;
+class FeatureIndex;
-// 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>;
+namespace style {
+class Style;
+}
-class GeometryCoordinates : public std::vector<GeometryCoordinate> {
+class GeometryTile : public Tile {
public:
- using coordinate_type = int16_t;
- using std::vector<GeometryCoordinate>::vector;
-};
+ GeometryTile(const OverscaledTileID&,
+ std::string sourceID,
+ style::Style&,
+ const MapMode);
-class GeometryCollection : public std::vector<GeometryCoordinates> {
-public:
- using coordinate_type = int16_t;
- using std::vector<GeometryCoordinates>::vector;
-};
+ ~GeometryTile();
-class GeometryTileFeature : private util::noncopyable {
-public:
- virtual ~GeometryTileFeature() = default;
- virtual FeatureType getType() const = 0;
- virtual optional<Value> getValue(const std::string& key) const = 0;
- virtual Feature::property_map getProperties() const { return Feature::property_map(); }
- virtual optional<uint64_t> getID() const { return {}; }
- virtual GeometryCollection getGeometries() const = 0;
-};
+ void setError(std::exception_ptr err);
-class GeometryTileLayer : private util::noncopyable {
-public:
- virtual ~GeometryTileLayer() = default;
- virtual std::size_t featureCount() const = 0;
- virtual util::ptr<const GeometryTileFeature> getFeature(std::size_t) const = 0;
- virtual std::string getName() const = 0;
-};
+ void setData(std::unique_ptr<GeometryTileData>,
+ optional<Timestamp> modified_,
+ optional<Timestamp> expires_);
-class GeometryTile : private util::noncopyable {
-public:
- virtual ~GeometryTile() = default;
- virtual util::ptr<GeometryTileLayer> getLayer(const std::string&) const = 0;
-};
+ Bucket* getBucket(const style::Layer&) override;
+
+ bool parsePending() override;
+
+ void redoPlacement(PlacementConfig) override;
+
+ void queryRenderedFeatures(
+ std::unordered_map<std::string, std::vector<Feature>>& result,
+ const GeometryCoordinates& queryGeometry,
+ const TransformState&,
+ const optional<std::vector<std::string>>& layerIDs) override;
+
+ void cancel() override;
-// classifies an array of rings into polygons with outer rings and holes
-std::vector<GeometryCollection> classifyRings(const GeometryCollection&);
+private:
+ void redoPlacement();
-// Truncate polygon to the largest `maxHoles` inner rings by area.
-void limitHoles(GeometryCollection&, uint32_t maxHoles);
+ style::Style& style;
+ Worker& worker;
+ TileWorker tileWorker;
-// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature)
-Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
+ std::unique_ptr<AsyncRequest> workRequest;
-// 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&);
+ // Contains all the Bucket objects for the tile. Buckets are render
+ // objects and they get added by tile parsing operations.
+ std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+
+ std::unique_ptr<FeatureIndex> featureIndex;
+ std::unique_ptr<const GeometryTileData> data;
+
+ // Stores the placement configuration of the text that is currently placed on the screen.
+ PlacementConfig placedConfig;
+
+ // Stores the placement configuration of how the text should be placed. This isn't necessarily
+ // the one that is being displayed.
+ PlacementConfig targetConfig;
+
+ // Used to signal the worker that it should abandon parsing this tile as soon as possible.
+ util::Atomic<bool> obsolete { false };
+};
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile_data.cpp b/src/mbgl/tile/geometry_tile_data.cpp
index 39a379a8ed..6e700aa633 100644
--- a/src/mbgl/tile/geometry_tile_data.cpp
+++ b/src/mbgl/tile/geometry_tile_data.cpp
@@ -1,206 +1,210 @@
#include <mbgl/tile/geometry_tile_data.hpp>
-#include <mbgl/tile/tile_data_observer.hpp>
-#include <mbgl/tile/tile_source.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/style/layer_impl.hpp>
-#include <mbgl/util/worker.hpp>
-#include <mbgl/util/work_request.hpp>
-#include <mbgl/style/style.hpp>
-#include <mbgl/storage/file_source.hpp>
-#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/text/collision_tile.hpp>
-#include <mbgl/map/transform_state.hpp>
+#include <mbgl/tile/tile_id.hpp>
+
+#include <clipper/clipper.hpp>
namespace mbgl {
-GeometryTileData::GeometryTileData(const OverscaledTileID& id_,
- std::string sourceID,
- style::Style& style_,
- const MapMode mode_)
- : TileData(id_),
- style(style_),
- worker(style_.workers),
- tileWorker(id_,
- sourceID,
- *style_.spriteStore,
- *style_.glyphAtlas,
- *style_.glyphStore,
- obsolete,
- mode_) {
-}
+static double signedArea(const GeometryCoordinates& ring) {
+ double sum = 0;
-void GeometryTileData::setError(std::exception_ptr err) {
- observer->onTileError(*this, err);
+ for (std::size_t i = 0, len = ring.size(), j = len - 1; i < len; j = i++) {
+ const GeometryCoordinate& p1 = ring[i];
+ const GeometryCoordinate& p2 = ring[j];
+ sum += (p2.x - p1.x) * (p1.y + p2.y);
+ }
+
+ return sum;
}
-void GeometryTileData::setData(std::unique_ptr<GeometryTile> tile,
- optional<Timestamp> modified_,
- optional<Timestamp> expires_) {
- modified = modified_;
- expires = expires_;
-
- if (!tile) {
- // This is a 404 response. We're treating these as empty tiles.
- workRequest.reset();
- availableData = DataAvailability::All;
- buckets.clear();
- redoPlacement();
- observer->onTileLoaded(*this, true);
- return;
+static ClipperLib::Path toClipperPath(const GeometryCoordinates& ring) {
+ ClipperLib::Path result;
+ result.reserve(ring.size());
+ for (const auto& p : ring) {
+ result.emplace_back(p.x, p.y);
}
+ return result;
+}
- // Mark the tile as pending again if it was complete before to prevent signaling a complete
- // state despite pending parse operations.
- if (availableData == DataAvailability::All) {
- availableData = DataAvailability::Some;
+static GeometryCoordinates fromClipperPath(const ClipperLib::Path& path) {
+ GeometryCoordinates result;
+ result.reserve(path.size());
+ for (const auto& p : path) {
+ using Coordinate = GeometryCoordinates::coordinate_type;
+ assert(p.x >= std::numeric_limits<Coordinate>::min());
+ assert(p.x <= std::numeric_limits<Coordinate>::max());
+ assert(p.y >= std::numeric_limits<Coordinate>::min());
+ assert(p.y <= std::numeric_limits<Coordinate>::max());
+ result.emplace_back(Coordinate(p.x), Coordinate(p.y));
}
+ return result;
+}
- // Kick off a fresh parse of this tile. This happens when the tile is new, or
- // when tile data changed. Replacing the workdRequest will cancel a pending work
- // request in case there is one.
- workRequest.reset();
- workRequest = worker.parseGeometryTile(tileWorker, style.getLayers(), std::move(tile), targetConfig, [this, config = targetConfig] (TileParseResult result) {
- workRequest.reset();
+static void processPolynodeBranch(ClipperLib::PolyNode* polynode, GeometryCollection& rings) {
+ // Exterior ring.
+ rings.push_back(fromClipperPath(polynode->Contour));
+ assert(signedArea(rings.back()) > 0);
- if (result.is<TileParseResultData>()) {
- auto& resultBuckets = result.get<TileParseResultData>();
- availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
+ // Interior rings.
+ for (auto * ring : polynode->Childs) {
+ rings.push_back(fromClipperPath(ring->Contour));
+ assert(signedArea(rings.back()) < 0);
+ }
- // Persist the configuration we just placed so that we can later check whether we need to
- // place again in case the configuration has changed.
- placedConfig = config;
+ // PolyNodes may be nested in the case of a polygon inside a hole.
+ for (auto * ring : polynode->Childs) {
+ for (auto * subRing : ring->Childs) {
+ processPolynodeBranch(subRing, rings);
+ }
+ }
+}
- // Move over all buckets we received in this parse request, potentially overwriting
- // existing buckets in case we got a refresh parse.
- buckets = std::move(resultBuckets.buckets);
+GeometryCollection fixupPolygons(const GeometryCollection& rings) {
+ ClipperLib::Clipper clipper;
+ clipper.StrictlySimple(true);
- if (isComplete()) {
- featureIndex = std::move(resultBuckets.featureIndex);
- geometryTile = std::move(resultBuckets.geometryTile);
- }
+ for (const auto& ring : rings) {
+ clipper.AddPath(toClipperPath(ring), ClipperLib::ptSubject, true);
+ }
- redoPlacement();
- observer->onTileLoaded(*this, true);
- } else {
- availableData = DataAvailability::All;
- observer->onTileError(*this, result.get<std::exception_ptr>());
- }
- });
-}
+ ClipperLib::PolyTree polygons;
+ clipper.Execute(ClipperLib::ctUnion, polygons, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
+ clipper.Clear();
-GeometryTileData::~GeometryTileData() {
- cancel();
+ GeometryCollection result;
+ for (auto * polynode : polygons.Childs) {
+ processPolynodeBranch(polynode, result);
+ }
+ return result;
}
-bool GeometryTileData::parsePending() {
- if (workRequest) {
- // There's already parsing or placement going on.
- return false;
- }
+std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
+ std::vector<GeometryCollection> polygons;
+
+ std::size_t len = rings.size();
- workRequest.reset();
- workRequest = worker.parsePendingGeometryTileLayers(tileWorker, targetConfig, [this, config = targetConfig] (TileParseResult result) {
- workRequest.reset();
+ if (len <= 1) {
+ polygons.push_back(rings);
+ return polygons;
+ }
- if (result.is<TileParseResultData>()) {
- auto& resultBuckets = result.get<TileParseResultData>();
- availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
+ GeometryCollection polygon;
+ int8_t ccw = 0;
- // Move over all buckets we received in this parse request, potentially overwriting
- // existing buckets in case we got a refresh parse.
- for (auto& bucket : resultBuckets.buckets) {
- buckets[bucket.first] = std::move(bucket.second);
- }
+ for (std::size_t i = 0; i < len; i++) {
+ double area = signedArea(rings[i]);
- // Persist the configuration we just placed so that we can later check whether we need to
- // place again in case the configuration has changed.
- placedConfig = config;
+ if (area == 0)
+ continue;
- if (isComplete()) {
- featureIndex = std::move(resultBuckets.featureIndex);
- geometryTile = std::move(resultBuckets.geometryTile);
- }
+ if (ccw == 0)
+ ccw = (area < 0 ? -1 : 1);
- redoPlacement();
- observer->onTileLoaded(*this, false);
- } else {
- availableData = DataAvailability::All;
- observer->onTileError(*this, result.get<std::exception_ptr>());
+ if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) {
+ polygons.push_back(polygon);
+ polygon.clear();
}
- });
-
- return true;
-}
-Bucket* GeometryTileData::getBucket(const style::Layer& layer) {
- const auto it = buckets.find(layer.baseImpl->bucketName());
- if (it == buckets.end()) {
- return nullptr;
+ polygon.push_back(rings[i]);
}
- assert(it->second);
- return it->second.get();
-}
+ if (!polygon.empty())
+ polygons.push_back(polygon);
-void GeometryTileData::redoPlacement(const PlacementConfig newConfig) {
- targetConfig = newConfig;
- redoPlacement();
+ return polygons;
}
-void GeometryTileData::redoPlacement() {
- // Don't start a new placement request when the current one hasn't completed yet, or when
- // we are parsing buckets.
- if (workRequest || targetConfig == placedConfig) {
- return;
+void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
+ if (polygon.size() > 1 + maxHoles) {
+ std::nth_element(polygon.begin() + 1,
+ polygon.begin() + 1 + maxHoles,
+ polygon.end(),
+ [] (const auto& a, const auto& b) {
+ return signedArea(a) > signedArea(b);
+ });
+ polygon.resize(1 + maxHoles);
}
+}
- workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, config = targetConfig](std::unique_ptr<CollisionTile> collisionTile) {
- workRequest.reset();
-
- // Persist the configuration we just placed so that we can later check whether we need to
- // place again in case the configuration has changed.
- placedConfig = config;
+static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
+ const double size = util::EXTENT * std::pow(2, tileID.z);
+ const double x0 = util::EXTENT * tileID.x;
+ const double y0 = util::EXTENT * tileID.y;
+
+ auto tileCoordinatesToLatLng = [&] (const Point<int16_t>& p) {
+ double y2 = 180 - (p.y + y0) * 360 / size;
+ return Point<double>(
+ (p.x + x0) * 360 / size - 180,
+ 360.0 / M_PI * std::atan(std::exp(y2 * M_PI / 180)) - 90.0
+ );
+ };
+
+ GeometryCollection geometries = geometryTileFeature.getGeometries();
+
+ switch (geometryTileFeature.getType()) {
+ case FeatureType::Unknown: {
+ assert(false);
+ return Point<double>(NAN, NAN);
+ }
- for (auto& bucket : buckets) {
- bucket.second->swapRenderData();
+ case FeatureType::Point: {
+ MultiPoint<double> multiPoint;
+ for (const auto& p : geometries.at(0)) {
+ multiPoint.push_back(tileCoordinatesToLatLng(p));
+ }
+ if (multiPoint.size() == 1) {
+ return multiPoint[0];
+ } else {
+ return multiPoint;
+ }
}
- if (featureIndex) {
- featureIndex->setCollisionTile(std::move(collisionTile));
+ case FeatureType::LineString: {
+ MultiLineString<double> multiLineString;
+ for (const auto& g : geometries) {
+ LineString<double> lineString;
+ for (const auto& p : g) {
+ lineString.push_back(tileCoordinatesToLatLng(p));
+ }
+ multiLineString.push_back(std::move(lineString));
+ }
+ if (multiLineString.size() == 1) {
+ return multiLineString[0];
+ } else {
+ return multiLineString;
+ }
}
- // The target configuration could have changed since we started placement. In this case,
- // we're starting another placement run.
- if (placedConfig != targetConfig) {
- redoPlacement();
- } else {
- observer->onNeedsRepaint();
+ case FeatureType::Polygon: {
+ MultiPolygon<double> multiPolygon;
+ for (const auto& pg : classifyRings(geometries)) {
+ Polygon<double> polygon;
+ for (const auto& r : pg) {
+ LinearRing<double> linearRing;
+ for (const auto& p : r) {
+ linearRing.push_back(tileCoordinatesToLatLng(p));
+ }
+ polygon.push_back(std::move(linearRing));
+ }
+ multiPolygon.push_back(std::move(polygon));
+ }
+ if (multiPolygon.size() == 1) {
+ return multiPolygon[0];
+ } else {
+ return multiPolygon;
+ }
}
- });
-}
+ }
-void GeometryTileData::queryRenderedFeatures(
- std::unordered_map<std::string, std::vector<Feature>>& result,
- const GeometryCoordinates& queryGeometry,
- const TransformState& transformState,
- const optional<std::vector<std::string>>& layerIDs) {
-
- if (!featureIndex || !geometryTile) return;
-
- featureIndex->query(result,
- { queryGeometry },
- transformState.getAngle(),
- util::tileSize * id.overscaleFactor(),
- std::pow(2, transformState.getZoom() - id.overscaledZ),
- layerIDs,
- *geometryTile,
- id.canonical,
- style);
+ // Unreachable, but placate GCC.
+ return Point<double>();
}
-void GeometryTileData::cancel() {
- obsolete = true;
- workRequest.reset();
+Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
+ Feature feature { convertGeometry(geometryTileFeature, tileID) };
+ feature.properties = geometryTileFeature.getProperties();
+ feature.id = geometryTileFeature.getID();
+ return feature;
}
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp
index 6c7ff2f3d9..753ba6b8a2 100644
--- a/src/mbgl/tile/geometry_tile_data.hpp
+++ b/src/mbgl/tile/geometry_tile_data.hpp
@@ -1,79 +1,83 @@
#pragma once
-#include <mbgl/tile/tile_data.hpp>
-#include <mbgl/tile/tile_worker.hpp>
-#include <mbgl/text/placement_config.hpp>
-#include <mbgl/util/atomic.hpp>
+#include <mbgl/util/geometry.hpp>
#include <mbgl/util/feature.hpp>
-
-#include <memory>
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/ptr.hpp>
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/constants.hpp>
+
+#include <cstdint>
+#include <string>
+#include <vector>
#include <unordered_map>
+#include <functional>
namespace mbgl {
-class AsyncRequest;
-class GeometryTile;
-class GeometryTileSource;
-class FeatureIndex;
-
-namespace style {
-class Style;
-}
-
-class GeometryTileData : public TileData {
-public:
- GeometryTileData(const OverscaledTileID&,
- std::string sourceID,
- style::Style&,
- const MapMode);
-
- ~GeometryTileData();
-
- void setError(std::exception_ptr err);
-
- void setData(std::unique_ptr<GeometryTile> tile,
- optional<Timestamp> modified_,
- optional<Timestamp> expires_);
-
- Bucket* getBucket(const style::Layer&) override;
-
- bool parsePending() override;
+enum class FeatureType : uint8_t {
+ Unknown = 0,
+ Point = 1,
+ LineString = 2,
+ Polygon = 3
+};
- void redoPlacement(PlacementConfig) override;
+class CanonicalTileID;
- void queryRenderedFeatures(
- std::unordered_map<std::string, std::vector<Feature>>& result,
- const GeometryCoordinates& queryGeometry,
- const TransformState&,
- const optional<std::vector<std::string>>& layerIDs) override;
+// 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>;
- void cancel() override;
+class GeometryCoordinates : public std::vector<GeometryCoordinate> {
+public:
+ using coordinate_type = int16_t;
+ using std::vector<GeometryCoordinate>::vector;
+};
-private:
- void redoPlacement();
+class GeometryCollection : public std::vector<GeometryCoordinates> {
+public:
+ using coordinate_type = int16_t;
+ using std::vector<GeometryCoordinates>::vector;
+};
- style::Style& style;
- Worker& worker;
- TileWorker tileWorker;
+class GeometryTileFeature : private util::noncopyable {
+public:
+ virtual ~GeometryTileFeature() = default;
+ virtual FeatureType getType() const = 0;
+ virtual optional<Value> getValue(const std::string& key) const = 0;
+ virtual Feature::property_map getProperties() const { return Feature::property_map(); }
+ virtual optional<uint64_t> getID() const { return {}; }
+ virtual GeometryCollection getGeometries() const = 0;
+};
- std::unique_ptr<AsyncRequest> workRequest;
+class GeometryTileLayer : private util::noncopyable {
+public:
+ virtual ~GeometryTileLayer() = default;
+ virtual std::size_t featureCount() const = 0;
+ virtual util::ptr<const GeometryTileFeature> getFeature(std::size_t) const = 0;
+ virtual std::string getName() const = 0;
+};
- // Contains all the Bucket objects for the tile. Buckets are render
- // objects and they get added by tile parsing operations.
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+class GeometryTileData : private util::noncopyable {
+public:
+ virtual ~GeometryTileData() = default;
+ virtual util::ptr<GeometryTileLayer> getLayer(const std::string&) const = 0;
+};
- std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<const GeometryTile> geometryTile;
+// classifies an array of rings into polygons with outer rings and holes
+std::vector<GeometryCollection> classifyRings(const GeometryCollection&);
- // Stores the placement configuration of the text that is currently placed on the screen.
- PlacementConfig placedConfig;
+// Truncate polygon to the largest `maxHoles` inner rings by area.
+void limitHoles(GeometryCollection&, uint32_t maxHoles);
- // Stores the placement configuration of how the text should be placed. This isn't necessarily
- // the one that is being displayed.
- PlacementConfig targetConfig;
+// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature)
+Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
- // Used to signal the worker that it should abandon parsing this tile as soon as possible.
- util::Atomic<bool> obsolete { false };
-};
+// 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&);
} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile_data.cpp b/src/mbgl/tile/raster_tile.cpp
index 7737f1fb7d..c3838bc59b 100644
--- a/src/mbgl/tile/raster_tile_data.cpp
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -1,8 +1,8 @@
-#include <mbgl/tile/raster_tile_data.hpp>
+#include <mbgl/tile/raster_tile.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/tile/tile_source_impl.hpp>
#include <mbgl/style/source.hpp>
#include <mbgl/style/update_parameters.hpp>
-#include <mbgl/tile/tile_data_observer.hpp>
-#include <mbgl/tile/tile_source_impl.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/storage/file_source.hpp>
@@ -11,20 +11,20 @@
using namespace mbgl;
-RasterTileData::RasterTileData(const OverscaledTileID& id_,
- const style::UpdateParameters& parameters,
- const Tileset& tileset)
- : TileData(id_),
+RasterTile::RasterTile(const OverscaledTileID& id_,
+ const style::UpdateParameters& parameters,
+ const Tileset& tileset)
+ : Tile(id_),
texturePool(parameters.texturePool),
worker(parameters.worker),
tileSource(*this, id_, parameters, tileset) {
}
-void RasterTileData::setError(std::exception_ptr err) {
+void RasterTile::setError(std::exception_ptr err) {
observer->onTileError(*this, err);
}
-void RasterTileData::setData(std::shared_ptr<const std::string> data,
+void RasterTile::setData(std::shared_ptr<const std::string> data,
optional<Timestamp> modified_,
optional<Timestamp> expires_) {
modified = modified_;
@@ -55,14 +55,14 @@ void RasterTileData::setData(std::shared_ptr<const std::string> data,
});
}
-Bucket* RasterTileData::getBucket(const style::Layer&) {
+Bucket* RasterTile::getBucket(const style::Layer&) {
return bucket.get();
}
-void RasterTileData::setNecessity(Necessity necessity) {
- tileSource.setNecessity(static_cast<TileSource<RasterTileData>::Necessity>(necessity));
+void RasterTile::setNecessity(Necessity necessity) {
+ tileSource.setNecessity(static_cast<TileSource<RasterTile>::Necessity>(necessity));
}
-void RasterTileData::cancel() {
+void RasterTile::cancel() {
workRequest.reset();
}
diff --git a/src/mbgl/tile/raster_tile_data.hpp b/src/mbgl/tile/raster_tile.hpp
index 7c224ad812..eebfbe6b9c 100644
--- a/src/mbgl/tile/raster_tile_data.hpp
+++ b/src/mbgl/tile/raster_tile.hpp
@@ -1,8 +1,8 @@
#pragma once
-#include <mbgl/tile/tile_data.hpp>
-#include <mbgl/renderer/raster_bucket.hpp>
+#include <mbgl/tile/tile.hpp>
#include <mbgl/tile/tile_source.hpp>
+#include <mbgl/renderer/raster_bucket.hpp>
namespace mbgl {
@@ -16,9 +16,9 @@ class Layer;
class UpdateParameters;
}
-class RasterTileData : public TileData {
+class RasterTile : public Tile {
public:
- RasterTileData(const OverscaledTileID&,
+ RasterTile(const OverscaledTileID&,
const style::UpdateParameters&,
const Tileset&);
@@ -37,7 +37,7 @@ private:
gl::TexturePool& texturePool;
Worker& worker;
- TileSource<RasterTileData> tileSource;
+ TileSource<RasterTile> tileSource;
std::unique_ptr<AsyncRequest> workRequest;
// Contains the Bucket object for the tile. Buckets are render
diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp
new file mode 100644
index 0000000000..846cda26cf
--- /dev/null
+++ b/src/mbgl/tile/tile.cpp
@@ -0,0 +1,37 @@
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/renderer/debug_bucket.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+
+static TileObserver nullObserver;
+
+Tile::Tile(const OverscaledTileID& id_)
+ : id(id_), observer(&nullObserver) {
+}
+
+Tile::~Tile() = default;
+
+void Tile::setObserver(TileObserver* observer_) {
+ observer = observer_;
+}
+
+void Tile::setTriedOptional() {
+ triedOptional = true;
+ observer->onNeedsRepaint();
+}
+
+void Tile::dumpDebugLogs() const {
+ Log::Info(Event::General, "Tile::id: %s", util::toString(id).c_str());
+ Log::Info(Event::General, "Tile::renderable: %s", isRenderable() ? "yes" : "no");
+ Log::Info(Event::General, "Tile::complete: %s", isComplete() ? "yes" : "no");
+}
+
+void Tile::queryRenderedFeatures(
+ std::unordered_map<std::string, std::vector<Feature>>&,
+ const GeometryCoordinates&,
+ const TransformState&,
+ const optional<std::vector<std::string>>&) {}
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/tile_data.hpp b/src/mbgl/tile/tile.hpp
index 4eee82ef4c..058e41a024 100644
--- a/src/mbgl/tile/tile_data.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -7,7 +7,7 @@
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/text/placement_config.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <string>
#include <memory>
@@ -19,18 +19,18 @@ namespace mbgl {
class Worker;
class DebugBucket;
class TransformState;
-class TileDataObserver;
+class TileObserver;
namespace style {
class Layer;
}
-class TileData : private util::noncopyable {
+class Tile : private util::noncopyable {
public:
- TileData(const OverscaledTileID&);
- virtual ~TileData();
+ Tile(const OverscaledTileID&);
+ virtual ~Tile();
- void setObserver(TileDataObserver* observer);
+ void setObserver(TileObserver* observer);
enum class Necessity : bool {
Optional = false,
@@ -91,18 +91,18 @@ protected:
// Still waiting for data to load or parse.
None,
- // TileData is partially parsed, some buckets are still waiting for dependencies
+ // Tile is partially parsed, some buckets are still waiting for dependencies
// to arrive, but it is good for rendering. Partial tiles can also be re-parsed,
// but might remain in the same state if dependencies are still missing.
Some,
- // TileData is fully parsed, and all buckets are available if they exist.
+ // Tile is fully parsed, and all buckets are available if they exist.
All,
};
DataAvailability availableData = DataAvailability::None;
- TileDataObserver* observer = nullptr;
+ TileObserver* observer = nullptr;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/tile_cache.cpp b/src/mbgl/tile/tile_cache.cpp
index 619d813fd2..3fafb1259c 100644
--- a/src/mbgl/tile/tile_cache.cpp
+++ b/src/mbgl/tile/tile_cache.cpp
@@ -1,5 +1,5 @@
#include <mbgl/tile/tile_cache.hpp>
-#include <mbgl/tile/tile_data.hpp>
+#include <mbgl/tile/tile.hpp>
#include <cassert>
@@ -17,21 +17,21 @@ void TileCache::setSize(size_t size_) {
assert(orderedKeys.size() <= size);
}
-void TileCache::add(const OverscaledTileID& key, std::unique_ptr<TileData> data) {
- if (!data->isRenderable() || !size) {
+void TileCache::add(const OverscaledTileID& key, std::unique_ptr<Tile> tile) {
+ if (!tile->isRenderable() || !size) {
return;
}
- // insert new or query existing data
- if (tiles.emplace(key, std::move(data)).second) {
- // remove existing data key
+ // insert new or query existing tile
+ if (tiles.emplace(key, std::move(tile)).second) {
+ // remove existing tile key
orderedKeys.remove(key);
}
- // (re-)insert data key as newest
+ // (re-)insert tile key as newest
orderedKeys.push_back(key);
- // purge oldest key/data if necessary
+ // purge oldest key/tile if necessary
if (orderedKeys.size() > size) {
get(orderedKeys.front());
}
@@ -39,19 +39,19 @@ void TileCache::add(const OverscaledTileID& key, std::unique_ptr<TileData> data)
assert(orderedKeys.size() <= size);
}
-std::unique_ptr<TileData> TileCache::get(const OverscaledTileID& key) {
+std::unique_ptr<Tile> TileCache::get(const OverscaledTileID& key) {
- std::unique_ptr<TileData> data;
+ std::unique_ptr<Tile> tile;
auto it = tiles.find(key);
if (it != tiles.end()) {
- data = std::move(it->second);
+ tile = std::move(it->second);
tiles.erase(it);
orderedKeys.remove(key);
- assert(data->isRenderable());
+ assert(tile->isRenderable());
}
- return data;
+ return tile;
}
bool TileCache::has(const OverscaledTileID& key) {
diff --git a/src/mbgl/tile/tile_cache.hpp b/src/mbgl/tile/tile_cache.hpp
index edaa6bd680..80fe98a20c 100644
--- a/src/mbgl/tile/tile_cache.hpp
+++ b/src/mbgl/tile/tile_cache.hpp
@@ -8,7 +8,7 @@
namespace mbgl {
-class TileData;
+class Tile;
class TileCache {
public:
@@ -16,13 +16,13 @@ public:
void setSize(size_t);
size_t getSize() const { return size; };
- void add(const OverscaledTileID& key, std::unique_ptr<TileData> data);
- std::unique_ptr<TileData> get(const OverscaledTileID& key);
+ void add(const OverscaledTileID& key, std::unique_ptr<Tile> data);
+ std::unique_ptr<Tile> get(const OverscaledTileID& key);
bool has(const OverscaledTileID& key);
void clear();
private:
- std::map<OverscaledTileID, std::unique_ptr<TileData>> tiles;
+ std::map<OverscaledTileID, std::unique_ptr<Tile>> tiles;
std::list<OverscaledTileID> orderedKeys;
size_t size;
diff --git a/src/mbgl/tile/tile_data.cpp b/src/mbgl/tile/tile_data.cpp
deleted file mode 100644
index 7046d2e7db..0000000000
--- a/src/mbgl/tile/tile_data.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <mbgl/tile/tile_data.hpp>
-#include <mbgl/tile/tile_data_observer.hpp>
-#include <mbgl/renderer/debug_bucket.hpp>
-#include <mbgl/util/string.hpp>
-
-namespace mbgl {
-
-static TileDataObserver nullObserver;
-
-TileData::TileData(const OverscaledTileID& id_)
- : id(id_), observer(&nullObserver) {
-}
-
-TileData::~TileData() = default;
-
-void TileData::setObserver(TileDataObserver* observer_) {
- observer = observer_;
-}
-
-void TileData::setTriedOptional() {
- triedOptional = true;
- observer->onNeedsRepaint();
-}
-
-void TileData::dumpDebugLogs() const {
- Log::Info(Event::General, "TileData::id: %s", util::toString(id).c_str());
- Log::Info(Event::General, "TileData::renderable: %s", isRenderable() ? "yes" : "no");
- Log::Info(Event::General, "TileData::complete: %s", isComplete() ? "yes" : "no");
-}
-
-void TileData::queryRenderedFeatures(
- std::unordered_map<std::string, std::vector<Feature>>&,
- const GeometryCoordinates&,
- const TransformState&,
- const optional<std::vector<std::string>>&) {}
-
-} // namespace mbgl
diff --git a/src/mbgl/tile/tile_data_observer.hpp b/src/mbgl/tile/tile_data_observer.hpp
deleted file mode 100644
index b950fc0b72..0000000000
--- a/src/mbgl/tile/tile_data_observer.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <exception>
-
-namespace mbgl {
-
-class TileData;
-
-class TileDataObserver {
-public:
- virtual ~TileDataObserver() = default;
-
- virtual void onTileLoaded(TileData&, bool /*isNewTile*/) {}
- virtual void onTileError(TileData&, std::exception_ptr) {}
- virtual void onNeedsRepaint() {}
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/tile/tile_observer.hpp b/src/mbgl/tile/tile_observer.hpp
new file mode 100644
index 0000000000..96ded11fbb
--- /dev/null
+++ b/src/mbgl/tile/tile_observer.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <exception>
+
+namespace mbgl {
+
+class Tile;
+
+class TileObserver {
+public:
+ virtual ~TileObserver() = default;
+
+ virtual void onTileLoaded(Tile&, bool /*isNewTile*/) {}
+ virtual void onTileError(Tile&, std::exception_ptr) {}
+ virtual void onNeedsRepaint() {}
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/tile_source.hpp b/src/mbgl/tile/tile_source.hpp
index f1a0a1c922..b4aff4492f 100644
--- a/src/mbgl/tile/tile_source.hpp
+++ b/src/mbgl/tile/tile_source.hpp
@@ -58,7 +58,7 @@ private:
void loadedData(const Response&);
void loadRequired();
- T& tileData;
+ T& tile;
Necessity necessity;
Resource resource;
FileSource& fileSource;
diff --git a/src/mbgl/tile/tile_source_impl.hpp b/src/mbgl/tile/tile_source_impl.hpp
index 625a0e2020..51591aa534 100644
--- a/src/mbgl/tile/tile_source_impl.hpp
+++ b/src/mbgl/tile/tile_source_impl.hpp
@@ -10,11 +10,11 @@
namespace mbgl {
template <typename T>
-TileSource<T>::TileSource(T& tileData_,
+TileSource<T>::TileSource(T& tile_,
const OverscaledTileID& id,
const style::UpdateParameters& parameters,
const Tileset& tileset)
- : tileData(tileData_),
+ : tile(tile_),
necessity(Necessity::Optional),
resource(Resource::tile(
tileset.tiles.at(0),
@@ -51,7 +51,7 @@ void TileSource<T>::loadOptional() {
request = fileSource.request(resource, [this](Response res) {
request.reset();
- tileData.setTriedOptional();
+ tile.setTriedOptional();
if (res.error && res.error->reason == Response::Error::Reason::NotFound) {
// When the optional request could not be satisfied, don't treat it as an error.
@@ -86,16 +86,16 @@ void TileSource<T>::makeOptional() {
template <typename T>
void TileSource<T>::loadedData(const Response& res) {
if (res.error && res.error->reason != Response::Error::Reason::NotFound) {
- tileData.setError(std::make_exception_ptr(std::runtime_error(res.error->message)));
+ tile.setError(std::make_exception_ptr(std::runtime_error(res.error->message)));
} else if (res.notModified) {
resource.priorExpires = res.expires;
- // Do not notify the TileData object; when we get this message, it already has the current
+ // Do not notify the tile; when we get this message, it already has the current
// version of the data.
} else {
resource.priorModified = res.modified;
resource.priorExpires = res.expires;
resource.priorEtag = res.etag;
- tileData.setData(res.noContent ? nullptr : res.data, res.modified, res.expires);
+ tile.setData(res.noContent ? nullptr : res.data, res.modified, res.expires);
}
}
diff --git a/src/mbgl/tile/tile_worker.cpp b/src/mbgl/tile/tile_worker.cpp
index 1890aa7c47..358cfd3ca9 100644
--- a/src/mbgl/tile/tile_worker.cpp
+++ b/src/mbgl/tile/tile_worker.cpp
@@ -1,6 +1,6 @@
#include <mbgl/text/collision_tile.hpp>
#include <mbgl/tile/tile_worker.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/bucket_parameters.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
@@ -40,14 +40,14 @@ TileWorker::~TileWorker() {
}
TileParseResult TileWorker::parseAllLayers(std::vector<std::unique_ptr<Layer>> layers_,
- std::unique_ptr<const GeometryTile> geometryTile_,
+ std::unique_ptr<const GeometryTileData> tileData_,
PlacementConfig config) {
// We're doing a fresh parse of the tile, because the underlying data has changed.
pending.clear();
placementPending.clear();
partialParse = false;
featureIndex = std::make_unique<FeatureIndex>();
- geometryTile = std::move(geometryTile_);
+ tileData = std::move(tileData_);
// Store the layers for use in redoPlacement.
layers = std::move(layers_);
@@ -98,7 +98,7 @@ TileParseResult TileWorker::prepareResult(const PlacementConfig& config) {
if (result.complete) {
featureIndex->setCollisionTile(placeLayers(config));
result.featureIndex = std::move(featureIndex);
- result.geometryTile = std::move(geometryTile);
+ result.tileData = std::move(tileData);
}
return std::move(result);
@@ -147,7 +147,7 @@ void TileWorker::parseLayer(const Layer* layer) {
return;
}
- auto geometryLayer = geometryTile->getLayer(layer->baseImpl->sourceLayer);
+ auto geometryLayer = tileData->getLayer(layer->baseImpl->sourceLayer);
if (!geometryLayer) {
// The layer specified in the bucket does not exist. Do nothing.
if (debug::tileParseWarnings) {
diff --git a/src/mbgl/tile/tile_worker.hpp b/src/mbgl/tile/tile_worker.hpp
index 631a8c929f..b325459682 100644
--- a/src/mbgl/tile/tile_worker.hpp
+++ b/src/mbgl/tile/tile_worker.hpp
@@ -18,7 +18,7 @@
namespace mbgl {
class CollisionTile;
-class GeometryTile;
+class GeometryTileData;
class SpriteStore;
class GlyphAtlas;
class GlyphStore;
@@ -36,7 +36,7 @@ public:
bool complete = false;
std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<const GeometryTile> geometryTile;
+ std::unique_ptr<const GeometryTileData> tileData;
};
using TileParseResult = variant<
@@ -55,7 +55,7 @@ public:
~TileWorker();
TileParseResult parseAllLayers(std::vector<std::unique_ptr<style::Layer>>,
- std::unique_ptr<const GeometryTile> geometryTile,
+ std::unique_ptr<const GeometryTileData> tileData,
PlacementConfig);
TileParseResult parsePendingLayers(PlacementConfig);
@@ -83,7 +83,7 @@ private:
std::vector<std::unique_ptr<style::Layer>> layers;
std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<const GeometryTile> geometryTile;
+ std::unique_ptr<const GeometryTileData> tileData;
// Contains buckets that we couldn't parse so far due to missing resources.
// They will be attempted on subsequent parses.
diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp
index dc4ed04d7f..cd61b52c8e 100644
--- a/src/mbgl/tile/vector_tile.cpp
+++ b/src/mbgl/tile/vector_tile.cpp
@@ -1,6 +1,6 @@
#include <mbgl/tile/vector_tile.hpp>
#include <mbgl/tile/tile_source_impl.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/update_parameters.hpp>
#include <protozero/pbf_reader.hpp>
@@ -44,7 +44,7 @@ public:
std::string getName() const override;
private:
- friend class VectorTile;
+ friend class VectorTileData;
friend class VectorTileFeature;
std::string name;
@@ -56,9 +56,9 @@ private:
std::vector<protozero::pbf_reader> features;
};
-class VectorTile : public GeometryTile {
+class VectorTileData : public GeometryTileData {
public:
- VectorTile(std::shared_ptr<const std::string> data);
+ VectorTileData(std::shared_ptr<const std::string> data);
util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
@@ -68,22 +68,22 @@ private:
mutable std::map<std::string, util::ptr<GeometryTileLayer>> layers;
};
-VectorTileData::VectorTileData(const OverscaledTileID& id_,
- std::string sourceID,
- const style::UpdateParameters& parameters,
- const Tileset& tileset)
- : GeometryTileData(id_, sourceID, parameters.style, parameters.mode),
+VectorTile::VectorTile(const OverscaledTileID& id_,
+ std::string sourceID,
+ const style::UpdateParameters& parameters,
+ const Tileset& tileset)
+ : GeometryTile(id_, sourceID, parameters.style, parameters.mode),
tileSource(*this, id_, parameters, tileset) {
}
-void VectorTileData::setNecessity(Necessity necessity) {
- tileSource.setNecessity(static_cast<TileSource<VectorTileData>::Necessity>(necessity));
+void VectorTile::setNecessity(Necessity necessity) {
+ tileSource.setNecessity(static_cast<TileSource<VectorTile>::Necessity>(necessity));
}
-void VectorTileData::setData(std::shared_ptr<const std::string> data,
- optional<Timestamp> modified,
- optional<Timestamp> expires) {
- GeometryTileData::setData(data ? std::make_unique<VectorTile>(data) : nullptr, modified, expires);
+void VectorTile::setData(std::shared_ptr<const std::string> data_,
+ optional<Timestamp> modified_,
+ optional<Timestamp> expires_) {
+ GeometryTile::setData(data_ ? std::make_unique<VectorTileData>(data_) : nullptr, modified_, expires_);
}
Value parseValue(protozero::pbf_reader data) {
@@ -236,11 +236,11 @@ GeometryCollection VectorTileFeature::getGeometries() const {
return fixupPolygons(lines);
}
-VectorTile::VectorTile(std::shared_ptr<const std::string> data_)
+VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_)
: data(std::move(data_)) {
}
-util::ptr<GeometryTileLayer> VectorTile::getLayer(const std::string& name) const {
+util::ptr<GeometryTileLayer> VectorTileData::getLayer(const std::string& name) const {
if (!parsed) {
parsed = true;
protozero::pbf_reader tile_pbf(*data);
diff --git a/src/mbgl/tile/vector_tile.hpp b/src/mbgl/tile/vector_tile.hpp
index 4815f9276e..a7e808af4e 100644
--- a/src/mbgl/tile/vector_tile.hpp
+++ b/src/mbgl/tile/vector_tile.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile_source.hpp>
namespace mbgl {
@@ -11,12 +11,12 @@ namespace style {
class UpdateParameters;
}
-class VectorTileData : public GeometryTileData {
+class VectorTile : public GeometryTile {
public:
- VectorTileData(const OverscaledTileID&,
- std::string sourceID,
- const style::UpdateParameters&,
- const Tileset&);
+ VectorTile(const OverscaledTileID&,
+ std::string sourceID,
+ const style::UpdateParameters&,
+ const Tileset&);
void setNecessity(Necessity) final;
void setData(std::shared_ptr<const std::string> data,
@@ -24,7 +24,7 @@ public:
optional<Timestamp> expires);
private:
- TileSource<VectorTileData> tileSource;
+ TileSource<VectorTile> tileSource;
};
} // namespace mbgl