[core] *TileMonitor => *TileSource

This commit is contained in:
Konstantin Käfer
2016-05-19 15:34:08 +02:00
parent 6998479d05
commit e8d8f52d2e
21 changed files with 309 additions and 240 deletions

View File

@@ -5,6 +5,7 @@
#include <mbgl/annotation/fill_annotation_impl.hpp>
#include <mbgl/annotation/style_sourced_annotation_impl.hpp>
#include <mbgl/style/source.hpp>
#include <mbgl/tile/annotation_tile_source.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
@@ -139,12 +140,12 @@ void AnnotationManager::updateStyle(Style& style) {
}
}
void AnnotationManager::addTileMonitor(AnnotationTileMonitor& monitor) {
void AnnotationManager::addTileSource(AnnotationTileSource& monitor) {
monitors.insert(&monitor);
monitor.update(getTile(monitor.tileID.canonical));
}
void AnnotationManager::removeTileMonitor(AnnotationTileMonitor& monitor) {
void AnnotationManager::removeTileSource(AnnotationTileSource& monitor) {
monitors.erase(&monitor);
}

View File

@@ -15,7 +15,7 @@
namespace mbgl {
class AnnotationTile;
class AnnotationTileMonitor;
class AnnotationTileSource;
class SymbolAnnotationImpl;
class ShapeAnnotationImpl;
@@ -41,8 +41,8 @@ public:
void updateStyle(style::Style&);
void addTileMonitor(AnnotationTileMonitor&);
void removeTileMonitor(AnnotationTileMonitor&);
void addTileSource(AnnotationTileSource&);
void removeTileSource(AnnotationTileSource&);
static const std::string SourceID;
static const std::string PointLayerID;
@@ -65,7 +65,7 @@ private:
SymbolAnnotationMap symbolAnnotations;
ShapeAnnotationMap shapeAnnotations;
std::vector<std::string> obsoleteShapeAnnotationLayers;
std::set<AnnotationTileMonitor*> monitors;
std::set<AnnotationTileSource*> monitors;
SpriteStore spriteStore;
SpriteAtlas spriteAtlas;

View File

@@ -32,23 +32,4 @@ util::ptr<GeometryTileLayer> AnnotationTile::getLayer(const std::string& name) c
return nullptr;
}
AnnotationTileMonitor::AnnotationTileMonitor(const OverscaledTileID& tileID_, AnnotationManager& annotationManager_)
: tileID(tileID_),
annotationManager(annotationManager_) {
}
AnnotationTileMonitor::~AnnotationTileMonitor() {
annotationManager.removeTileMonitor(*this);
}
std::unique_ptr<AsyncRequest> AnnotationTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback_) {
callback = callback_;
annotationManager.addTileMonitor(*this);
return nullptr;
}
void AnnotationTileMonitor::update(std::unique_ptr<GeometryTile> tile) {
callback(nullptr, std::move(tile), {}, {});
}
} // namespace mbgl

View File

@@ -1,10 +1,6 @@
#pragma once
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <map>
#include <unordered_map>
namespace mbgl {
@@ -40,24 +36,7 @@ class AnnotationTile : public GeometryTile {
public:
util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
std::map<std::string, util::ptr<AnnotationTileLayer>> layers;
};
class AnnotationManager;
class AnnotationTileMonitor : public GeometryTileMonitor {
public:
AnnotationTileMonitor(const OverscaledTileID&, AnnotationManager&);
~AnnotationTileMonitor();
void update(std::unique_ptr<GeometryTile>);
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileMonitor::Callback&) override;
OverscaledTileID tileID;
private:
AnnotationManager& annotationManager;
GeometryTileMonitor::Callback callback;
std::unordered_map<std::string, util::ptr<AnnotationTileLayer>> layers;
};
} // namespace mbgl

View File

@@ -1,5 +1,6 @@
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/math/clamp.hpp>
namespace mbgl {

View File

@@ -22,6 +22,10 @@
#include <mbgl/util/string.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/tile/vector_tile_source.hpp>
#include <mbgl/tile/geojson_tile_source.hpp>
#include <mbgl/tile/annotation_tile_source.hpp>
#include <mbgl/tile/vector_tile_data.hpp>
#include <mbgl/tile/raster_tile_data.hpp>
#include <mbgl/style/parser.hpp>
@@ -202,14 +206,14 @@ std::unique_ptr<TileData> Source::createTile(const OverscaledTileID& overscaledT
tileset->tiles.at(0), parameters.texturePool,
parameters.worker, parameters.fileSource, callback);
} else {
std::unique_ptr<GeometryTileMonitor> monitor;
std::unique_ptr<GeometryTileSource> monitor;
if (type == SourceType::Vector) {
monitor = std::make_unique<VectorTileMonitor>(overscaledTileID, parameters.pixelRatio, tileset->tiles.at(0), parameters.fileSource);
monitor = std::make_unique<VectorTileSource>(overscaledTileID, parameters.pixelRatio, tileset->tiles.at(0), parameters.fileSource);
} else if (type == SourceType::Annotations) {
monitor = std::make_unique<AnnotationTileMonitor>(overscaledTileID, parameters.annotationManager);
monitor = std::make_unique<AnnotationTileSource>(overscaledTileID, parameters.annotationManager);
} else if (type == SourceType::GeoJSON) {
monitor = std::make_unique<GeoJSONTileMonitor>(geojsonvt.get(), overscaledTileID);
monitor = std::make_unique<GeoJSONTileSource>(geojsonvt.get(), overscaledTileID);
} else {
Log::Warning(Event::Style, "Source type '%s' is not implemented", SourceTypeClass(type).c_str());
return nullptr;

View File

@@ -0,0 +1,28 @@
#include <mbgl/tile/annotation_tile_source.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/util/async_request.hpp>
namespace mbgl {
AnnotationTileSource::AnnotationTileSource(const OverscaledTileID& tileID_,
AnnotationManager& annotationManager_)
: tileID(tileID_), annotationManager(annotationManager_) {
}
AnnotationTileSource::~AnnotationTileSource() {
annotationManager.removeTileSource(*this);
}
std::unique_ptr<AsyncRequest>
AnnotationTileSource::monitorTile(const GeometryTileSource::Callback& callback_) {
callback = callback_;
annotationManager.addTileSource(*this);
return nullptr;
}
void AnnotationTileSource::update(std::unique_ptr<GeometryTile> tile) {
callback(nullptr, std::move(tile), {}, {});
}
} // namespace mbgl

View File

@@ -0,0 +1,27 @@
#pragma once
#include <mbgl/tile/tile_source.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <memory>
namespace mbgl {
class AnnotationManager;
class AnnotationTileSource : public GeometryTileSource {
public:
AnnotationTileSource(const OverscaledTileID&, AnnotationManager&);
~AnnotationTileSource();
void update(std::unique_ptr<GeometryTile>);
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileSource::Callback&) override;
OverscaledTileID tileID;
private:
AnnotationManager& annotationManager;
GeometryTileSource::Callback callback;
};
} // namespace mbgl

View File

@@ -1,6 +1,4 @@
#include <mbgl/tile/geojson_tile.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mapbox/geojsonvt.hpp>
namespace mbgl {
@@ -45,97 +43,4 @@ util::ptr<GeometryTileLayer> GeoJSONTile::getLayer(const std::string&) const {
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;
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<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));
}
}
// https://github.com/mapbox/geojson-vt-cpp/issues/44
if (featureType == FeatureType::Polygon) {
geometry = fixupPolygons(geometry);
}
Feature::property_map properties { feature.tags.begin(), feature.tags.end() };
features.emplace_back(std::make_shared<GeoJSONTileFeature>(
featureType, std::move(geometry), std::move(properties)));
}
layer = std::make_unique<GeoJSONTileLayer>(std::move(features));
}
return std::make_unique<GeoJSONTile>(layer);
}
GeoJSONTileMonitor::GeoJSONTileMonitor(mapbox::geojsonvt::GeoJSONVT* geojsonvt_,
const OverscaledTileID& 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.canonical.z, tileID.canonical.x, tileID.canonical.y));
callback(nullptr, std::move(tile), {}, {});
}
}
std::unique_ptr<AsyncRequest>
GeoJSONTileMonitor::monitorTile(const GeometryTileMonitor::Callback& cb) {
callback = cb;
update();
return nullptr;
}
} // namespace mbgl

View File

@@ -1,15 +1,6 @@
#pragma once
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <unordered_map>
namespace mapbox {
namespace geojsonvt {
class GeoJSONVT;
} // namespace geojsonvt
} // namespace mapbox
namespace mbgl {
@@ -52,24 +43,4 @@ private:
const std::shared_ptr<GeoJSONTileLayer> layer;
};
class GeoJSONTileMonitor : public GeometryTileMonitor {
public:
GeoJSONTileMonitor(mapbox::geojsonvt::GeoJSONVT*, const OverscaledTileID&);
virtual ~GeoJSONTileMonitor();
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileMonitor::Callback&) override;
void setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT*);
private:
void update();
public:
const OverscaledTileID tileID;
private:
mapbox::geojsonvt::GeoJSONVT* geojsonvt = nullptr;
GeometryTileMonitor::Callback callback;
};
} // namespace mbgl

View File

@@ -0,0 +1,103 @@
#include <mbgl/tile/geojson_tile_source.hpp>
#include <mbgl/tile/geojson_tile.hpp>
#include <mbgl/util/async_request.hpp>
#include <mapbox/geojsonvt.hpp>
namespace mbgl {
GeoJSONTileSource::GeoJSONTileSource(mapbox::geojsonvt::GeoJSONVT* geojsonvt_,
const OverscaledTileID& id)
: tileID(id), geojsonvt(geojsonvt_) {
}
GeoJSONTileSource::~GeoJSONTileSource() = 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 GeoJSONTileSource::setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT* vt) {
// Don't duplicate notifications in case of nil changes.
if (geojsonvt != vt) {
geojsonvt = vt;
update();
}
}
// 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;
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<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));
}
}
// https://github.com/mapbox/geojson-vt-cpp/issues/44
if (featureType == FeatureType::Polygon) {
geometry = fixupPolygons(geometry);
}
Feature::property_map properties{ feature.tags.begin(), feature.tags.end() };
features.emplace_back(std::make_shared<GeoJSONTileFeature>(
featureType, std::move(geometry), std::move(properties)));
}
layer = std::make_unique<GeoJSONTileLayer>(std::move(features));
}
return std::make_unique<GeoJSONTile>(layer);
}
void GeoJSONTileSource::update() {
if (geojsonvt) {
auto tile = convertTile(
geojsonvt->getTile(tileID.canonical.z, tileID.canonical.x, tileID.canonical.y));
callback(nullptr, std::move(tile), {}, {});
}
}
std::unique_ptr<AsyncRequest>
GeoJSONTileSource::monitorTile(const GeometryTileSource::Callback& cb) {
callback = cb;
update();
return nullptr;
}
} // namespace mbgl

View File

@@ -0,0 +1,37 @@
#pragma once
#include <mbgl/tile/tile_source.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <unordered_map>
namespace mapbox {
namespace geojsonvt {
class GeoJSONVT;
} // namespace geojsonvt
} // namespace mapbox
namespace mbgl {
class GeoJSONTileSource : public GeometryTileSource {
public:
GeoJSONTileSource(mapbox::geojsonvt::GeoJSONVT*, const OverscaledTileID&);
virtual ~GeoJSONTileSource();
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileSource::Callback&) override;
void setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT*);
private:
void update();
public:
const OverscaledTileID tileID;
private:
mapbox::geojsonvt::GeoJSONVT* geojsonvt = nullptr;
GeometryTileSource::Callback callback;
};
} // namespace mbgl

View File

@@ -67,27 +67,6 @@ public:
virtual util::ptr<GeometryTileLayer> getLayer(const std::string&) const = 0;
};
class AsyncRequest;
class GeometryTileMonitor : private util::noncopyable {
public:
virtual ~GeometryTileMonitor() = default;
using Callback = std::function<void (std::exception_ptr,
std::unique_ptr<GeometryTile>,
optional<Timestamp> modified,
optional<Timestamp> expires)>;
/*
* Monitor the tile held by this object for changes. When the tile is loaded for the first time,
* or updates, the callback is executed. If an error occurs, the first parameter will be set.
* Otherwise it will be null. If there is no data for the requested tile, the second parameter
* will be null.
*
* To cease monitoring, release the returned Request.
*/
virtual std::unique_ptr<AsyncRequest> monitorTile(const Callback&) = 0;
};
// classifies an array of rings into polygons with outer rings and holes
std::vector<GeometryCollection> classifyRings(const GeometryCollection&);

View File

View File

@@ -0,0 +1,34 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/chrono.hpp>
#include <memory>
#include <functional>
namespace mbgl {
class GeometryTile;
class AsyncRequest;
class GeometryTileSource : private util::noncopyable {
public:
virtual ~GeometryTileSource() = default;
using Callback = std::function<void (std::exception_ptr,
std::unique_ptr<GeometryTile>,
optional<Timestamp> modified,
optional<Timestamp> expires)>;
/*
* Monitor the tile held by this object for changes. When the tile is loaded for the first time,
* or updates, the callback is executed. If an error occurs, the first parameter will be set.
* Otherwise it will be null. If there is no data for the requested tile, the second parameter
* will be null.
*
* To cease monitoring, release the returned Request.
*/
virtual std::unique_ptr<AsyncRequest> monitorTile(const Callback&) = 0;
};
} // namespace mbgl

View File

@@ -220,28 +220,4 @@ std::string VectorTileLayer::getName() const {
return name;
}
VectorTileMonitor::VectorTileMonitor(const OverscaledTileID& tileID_, float pixelRatio_,
const std::string& urlTemplate_, FileSource& fileSource_)
: tileID(tileID_),
pixelRatio(pixelRatio_),
urlTemplate(urlTemplate_),
fileSource(fileSource_) {
}
std::unique_ptr<AsyncRequest> VectorTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback) {
const Resource resource = Resource::tile(urlTemplate, pixelRatio, tileID.canonical.x,
tileID.canonical.y, tileID.canonical.z);
return fileSource.request(resource, [callback, this](Response res) {
if (res.error) {
callback(std::make_exception_ptr(std::runtime_error(res.error->message)), nullptr, res.modified, res.expires);
} else if (res.notModified) {
return;
} else if (res.noContent) {
callback(nullptr, nullptr, res.modified, res.expires);
} else {
callback(nullptr, std::make_unique<VectorTile>(res.data), res.modified, res.expires);
}
});
}
} // namespace mbgl

View File

@@ -66,20 +66,4 @@ private:
mutable std::map<std::string, util::ptr<GeometryTileLayer>> layers;
};
class TileID;
class FileSource;
class VectorTileMonitor : public GeometryTileMonitor {
public:
VectorTileMonitor(const OverscaledTileID&, float pixelRatio, const std::string& urlTemplate, FileSource&);
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileMonitor::Callback&) override;
private:
OverscaledTileID tileID;
float pixelRatio;
std::string urlTemplate;
FileSource& fileSource;
};
} // namespace mbgl

View File

@@ -1,4 +1,5 @@
#include <mbgl/tile/vector_tile_data.hpp>
#include <mbgl/tile/tile_source.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/util/worker.hpp>
@@ -12,7 +13,7 @@
namespace mbgl {
VectorTileData::VectorTileData(const OverscaledTileID& id_,
std::unique_ptr<GeometryTileMonitor> monitor_,
std::unique_ptr<GeometryTileSource> monitor_,
std::string sourceID,
style::Style& style_,
const MapMode mode_,

View File

@@ -12,7 +12,7 @@
namespace mbgl {
class AsyncRequest;
class GeometryTileMonitor;
class GeometryTileSource;
class FeatureIndex;
namespace style {
@@ -22,7 +22,7 @@ class Style;
class VectorTileData : public TileData {
public:
VectorTileData(const OverscaledTileID&,
std::unique_ptr<GeometryTileMonitor> monitor,
std::unique_ptr<GeometryTileSource> monitor,
std::string sourceID,
style::Style&,
const MapMode,
@@ -50,7 +50,7 @@ private:
Worker& worker;
TileWorker tileWorker;
std::unique_ptr<GeometryTileMonitor> monitor;
std::unique_ptr<GeometryTileSource> monitor;
std::unique_ptr<AsyncRequest> tileRequest;
std::unique_ptr<AsyncRequest> workRequest;

View File

@@ -0,0 +1,32 @@
#include <mbgl/tile/vector_tile_source.hpp>
#include <mbgl/tile/vector_tile.hpp>
#include <mbgl/storage/file_source.hpp>
namespace mbgl {
VectorTileSource::VectorTileSource(const OverscaledTileID& tileID_,
float pixelRatio_,
const std::string& urlTemplate_,
FileSource& fileSource_)
: tileID(tileID_), pixelRatio(pixelRatio_), urlTemplate(urlTemplate_), fileSource(fileSource_) {
}
std::unique_ptr<AsyncRequest>
VectorTileSource::monitorTile(const GeometryTileSource::Callback& callback) {
const Resource resource = Resource::tile(urlTemplate, pixelRatio, tileID.canonical.x,
tileID.canonical.y, tileID.canonical.z);
return fileSource.request(resource, [callback, this](Response res) {
if (res.error) {
callback(std::make_exception_ptr(std::runtime_error(res.error->message)), nullptr,
res.modified, res.expires);
} else if (res.notModified) {
return;
} else if (res.noContent) {
callback(nullptr, nullptr, res.modified, res.expires);
} else {
callback(nullptr, std::make_unique<VectorTile>(res.data), res.modified, res.expires);
}
});
}
} // namespace mbgl

View File

@@ -0,0 +1,26 @@
#pragma once
#include <mbgl/tile/tile_source.hpp>
#include <mbgl/tile/tile_id.hpp>
namespace mbgl {
class FileSource;
class VectorTileSource : public GeometryTileSource {
public:
VectorTileSource(const OverscaledTileID&,
float pixelRatio,
const std::string& urlTemplate,
FileSource&);
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileSource::Callback&) override;
private:
OverscaledTileID tileID;
float pixelRatio;
std::string urlTemplate;
FileSource& fileSource;
};
} // namespace mbgl