diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2015-10-26 15:45:32 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2015-10-26 16:44:55 +0100 |
commit | 75dec6ffac6f3e79e5a173cd8a3f98d374ed1c09 (patch) | |
tree | dd3e2752cfe2c1ea741ac1b97d38e5e4bc4aa008 /src | |
parent | c0c554e36fd43bfe57ef13fe60f9cd50b5c018fd (diff) | |
download | qtlocation-mapboxgl-75dec6ffac6f3e79e5a173cd8a3f98d374ed1c09.tar.gz |
[core] always reparse with the freshest possible placement config
Fixes an issue where updates to stale tiles would remove labels altogether until the map was rotated.
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/map/live_tile_data.cpp | 64 | ||||
-rw-r--r-- | src/mbgl/map/live_tile_data.hpp | 10 | ||||
-rw-r--r-- | src/mbgl/map/source.cpp | 10 | ||||
-rw-r--r-- | src/mbgl/map/tile_data.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/map/tile_worker.cpp | 24 | ||||
-rw-r--r-- | src/mbgl/map/tile_worker.hpp | 10 | ||||
-rw-r--r-- | src/mbgl/map/vector_tile_data.cpp | 78 | ||||
-rw-r--r-- | src/mbgl/map/vector_tile_data.hpp | 19 | ||||
-rw-r--r-- | src/mbgl/renderer/symbol_bucket.cpp | 24 | ||||
-rw-r--r-- | src/mbgl/text/collision_tile.cpp | 13 | ||||
-rw-r--r-- | src/mbgl/text/collision_tile.hpp | 38 | ||||
-rw-r--r-- | src/mbgl/text/placement_config.hpp | 28 | ||||
-rw-r--r-- | src/mbgl/util/worker.cpp | 24 | ||||
-rw-r--r-- | src/mbgl/util/worker.hpp | 6 |
14 files changed, 226 insertions, 125 deletions
diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp index fb8e6c3605..89b1d6fda4 100644 --- a/src/mbgl/map/live_tile_data.cpp +++ b/src/mbgl/map/live_tile_data.cpp @@ -14,17 +14,12 @@ using namespace mbgl; LiveTileData::LiveTileData(const TileID& id_, std::unique_ptr<AnnotationTile> tile_, - Style& style_, - const SourceInfo& source_, + Style& style, + const SourceInfo& source, std::function<void()> callback) : TileData(id_), - worker(style_.workers), - tileWorker(id_, - source_.source_id, - style_, - style_.layers, - state, - std::make_unique<CollisionTile>(0, 0, false)), + worker(style.workers), + tileWorker(id, source.source_id, style, style.layers, state), tile(std::move(tile_)) { state = State::loaded; @@ -41,25 +36,41 @@ bool LiveTileData::parsePending(std::function<void()> callback) { return false; } - workRequest = worker.parseLiveTile(tileWorker, *tile, [this, callback] (TileParseResult result) { + workRequest.reset(); + workRequest = worker.parseLiveTile(tileWorker, *tile, targetConfig, [this, callback, config = targetConfig] (TileParseResult result) { workRequest.reset(); if (result.is<TileParseResultBuckets>()) { auto& resultBuckets = result.get<TileParseResultBuckets>(); state = resultBuckets.state; + // 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; + // 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); } + // The target configuration could have changed since we started placement. In this case, + // we're starting another placement run. + if (placedConfig != targetConfig) { + redoPlacement(); + } } else { error = result.get<std::string>(); state = State::obsolete; } callback(); + + // The target configuration could have changed since we started placement. In this case, + // we're starting another placement run. + if (!workRequest && placedConfig != targetConfig) { + redoPlacement(); + } }); return true; @@ -87,3 +98,36 @@ void LiveTileData::cancel() { state = State::obsolete; workRequest.reset(); } + +void LiveTileData::redoPlacement(const PlacementConfig newConfig) { + if (newConfig != placedConfig) { + targetConfig = newConfig; + + if (!workRequest) { + // Don't start a new placement request when the current one hasn't completed yet, or + // when we are parsing buckets. + redoPlacement(); + } + } +} + +void LiveTileData::redoPlacement() { + workRequest.reset(); + workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, config = targetConfig] { + 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; + + for (auto& bucket : buckets) { + bucket.second->swapRenderData(); + } + + // The target configuration could have changed since we started placement. In this case, + // we're starting another placement run. + if (placedConfig != targetConfig) { + redoPlacement(); + } + }); +} diff --git a/src/mbgl/map/live_tile_data.hpp b/src/mbgl/map/live_tile_data.hpp index 568892216c..958f1db50a 100644 --- a/src/mbgl/map/live_tile_data.hpp +++ b/src/mbgl/map/live_tile_data.hpp @@ -22,6 +22,9 @@ public: bool parsePending(std::function<void ()> callback) override; + void redoPlacement(PlacementConfig config) override; + void redoPlacement(); + void cancel() override; Bucket* getBucket(const StyleLayer&) override; @@ -34,6 +37,13 @@ private: // 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; + + // 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; }; } diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index c79ef4b3b6..8a7f97d963 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -286,8 +286,7 @@ TileData::State Source::addTile(MapData& data, // If we don't find working tile data, we're just going to load it. if (info.type == SourceType::Vector) { - auto tileData = std::make_shared<VectorTileData>(normalized_id, style, info, - transformState.getAngle(), transformState.getPitch(), data.getCollisionDebug()); + auto tileData = std::make_shared<VectorTileData>(normalized_id, style, info); tileData->request(data.pixelRatio, callback); new_tile.data = tileData; } else if (info.type == SourceType::Raster) { @@ -296,7 +295,7 @@ TileData::State Source::addTile(MapData& data, new_tile.data = tileData; } else if (info.type == SourceType::Annotations) { new_tile.data = std::make_shared<LiveTileData>(normalized_id, - data.getAnnotationManager()->getTile(normalized_id), style, info, callback); + data.getAnnotationManager()->getTile(normalized_id), style, info, callback); } else { throw std::runtime_error("source type not implemented"); } @@ -510,7 +509,8 @@ bool Source::update(MapData& data, updateTilePtrs(); for (auto& tilePtr : tilePtrs) { - tilePtr->data->redoPlacement(transformState.getAngle(), transformState.getPitch(), data.getCollisionDebug()); + tilePtr->data->redoPlacement( + { transformState.getAngle(), transformState.getPitch(), data.getCollisionDebug() }); } updated = data.getAnimationTime(); @@ -560,7 +560,7 @@ void Source::tileLoadingCompleteCallback(const TileID& normalized_id, const Tran return; } - data->redoPlacement(transformState.getAngle(), transformState.getPitch(), collisionDebug); + data->redoPlacement({ transformState.getAngle(), transformState.getPitch(), collisionDebug }); emitTileLoaded(true); } diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/map/tile_data.hpp index 44f0304c8d..d9895ce01a 100644 --- a/src/mbgl/map/tile_data.hpp +++ b/src/mbgl/map/tile_data.hpp @@ -4,6 +4,7 @@ #include <mbgl/util/noncopyable.hpp> #include <mbgl/map/tile_id.hpp> #include <mbgl/renderer/bucket.hpp> +#include <mbgl/text/placement_config.hpp> #include <atomic> #include <string> @@ -76,7 +77,7 @@ public: virtual Bucket* getBucket(const StyleLayer&) = 0; virtual bool parsePending(std::function<void ()>) { return true; } - virtual void redoPlacement(float, float, bool) {} + virtual void redoPlacement(PlacementConfig) {} bool isReady() const { return isReadyState(state); diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/map/tile_worker.cpp index c7836c4ba9..88bbf16a3f 100644 --- a/src/mbgl/map/tile_worker.cpp +++ b/src/mbgl/map/tile_worker.cpp @@ -19,15 +19,13 @@ TileWorker::TileWorker(TileID id_, std::string sourceID_, Style& style_, std::vector<util::ptr<StyleLayer>> layers_, - const std::atomic<TileData::State>& state_, - std::unique_ptr<CollisionTile> collision_) + const std::atomic<TileData::State>& state_) : layers(std::move(layers_)), id(id_), sourceID(sourceID_), parameters(id.z), style(style_), - state(state_), - collisionTile(std::move(collision_)) { + state(state_) { assert(style.sprite); } @@ -35,10 +33,14 @@ TileWorker::~TileWorker() { style.glyphAtlas->removeGlyphs(reinterpret_cast<uintptr_t>(this)); } -TileParseResult TileWorker::parseAllLayers(const GeometryTile& geometryTile) { +TileParseResult TileWorker::parseAllLayers(const GeometryTile& geometryTile, + PlacementConfig config) { // We're doing a fresh parse of the tile, because the underlying data has changed. pending.clear(); + // Reset the collision tile so we have a clean slate; we're placing all features anyway. + collisionTile = std::make_unique<CollisionTile>(config); + // We're storing a list of buckets we've parsed to avoid parsing a bucket twice that is // referenced from more than one layer std::set<StyleBucket*> parsed; @@ -84,12 +86,10 @@ TileParseResult TileWorker::parsePendingLayers() { void TileWorker::redoPlacement( const std::unordered_map<std::string, std::unique_ptr<Bucket>>* buckets, - float angle, - float pitch, - bool collisionDebug) { + PlacementConfig config) { // Reset the collision tile so we have a clean slate; we're placing all features anyway. - collisionTile = std::make_unique<CollisionTile>(angle, pitch, collisionDebug); + collisionTile = std::make_unique<CollisionTile>(config); for (auto i = layers.rbegin(); i != layers.rend(); i++) { const auto it = buckets->find((*i)->id); @@ -268,11 +268,17 @@ void TileWorker::createSymbolBucket(const GeometryTileLayer& layer, bucket->parseFeatures(layer, styleBucket.filter); + assert(style.glyphStore); + assert(style.sprite); const bool needsDependencies = bucket->needsDependencies(*style.glyphStore, *style.sprite); if (needsDependencies) { // We cannot parse this bucket yet. Instead, we're saving it for later. pending.emplace_back(styleBucket, std::move(bucket)); } else { + assert(style.spriteAtlas); + assert(style.glyphAtlas); + assert(style.glyphStore); + assert(collisionTile); bucket->addFeatures(reinterpret_cast<uintptr_t>(this), *style.spriteAtlas, *style.glyphAtlas, *style.glyphStore, *collisionTile); insertBucket(styleBucket.name, std::move(bucket)); diff --git a/src/mbgl/map/tile_worker.hpp b/src/mbgl/map/tile_worker.hpp index f7cfa57ac6..27fc0d37fe 100644 --- a/src/mbgl/map/tile_worker.hpp +++ b/src/mbgl/map/tile_worker.hpp @@ -8,6 +8,7 @@ #include <mbgl/util/ptr.hpp> #include <mbgl/style/filter_expression.hpp> #include <mbgl/style/style_calculation_parameters.hpp> +#include <mbgl/text/placement_config.hpp> #include <string> #include <memory> @@ -42,16 +43,13 @@ public: std::string sourceID, Style&, std::vector<util::ptr<StyleLayer>>, - const std::atomic<TileData::State>&, - std::unique_ptr<CollisionTile>); + const std::atomic<TileData::State>&); ~TileWorker(); - TileParseResult parseAllLayers(const GeometryTile&); + TileParseResult parseAllLayers(const GeometryTile&, PlacementConfig); TileParseResult parsePendingLayers(); void redoPlacement(const std::unordered_map<std::string, std::unique_ptr<Bucket>>*, - float angle, - float pitch, - bool collisionDebug); + PlacementConfig); std::vector<util::ptr<StyleLayer>> layers; diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp index c3115cdb88..3c831250c5 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/map/vector_tile_data.cpp @@ -14,23 +14,15 @@ using namespace mbgl; VectorTileData::VectorTileData(const TileID& id_, Style& style_, - const SourceInfo& source_, - float angle, - float pitch, - bool collisionDebug) + const SourceInfo& source_) : TileData(id_), worker(style_.workers), tileWorker(id_, source_.source_id, style_, style_.layers, - state, - std::make_unique<CollisionTile>(angle, pitch, collisionDebug)), - source(source_), - lastAngle(angle), - currentAngle(angle), - currentPitch(pitch), - currentCollisionDebug(collisionDebug) { + state), + source(source_) { } VectorTileData::~VectorTileData() { @@ -81,7 +73,7 @@ void VectorTileData::parse(std::function<void ()> callback) { // when tile data changed. Replacing the workdRequest will cancel a pending work // request in case there is one. workRequest.reset(); - workRequest = worker.parseVectorTile(tileWorker, data, [this, callback] (TileParseResult result) { + workRequest = worker.parseVectorTile(tileWorker, data, targetConfig, [this, callback, config = targetConfig] (TileParseResult result) { workRequest.reset(); if (state == State::obsolete) { return; @@ -91,11 +83,21 @@ void VectorTileData::parse(std::function<void ()> callback) { auto& resultBuckets = result.get<TileParseResultBuckets>(); state = resultBuckets.state; + // 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; + // 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); } + + // The target configuration could have changed since we started placement. In this case, + // we're starting another placement run. + if (placedConfig != targetConfig) { + redoPlacement(); + } } else { std::stringstream message; message << "Failed to parse [" << std::string(id) << "]: " << result.get<std::string>(); @@ -129,6 +131,12 @@ bool VectorTileData::parsePending(std::function<void()> callback) { for (auto& bucket : resultBuckets.buckets) { buckets[bucket.first] = std::move(bucket.second); } + + // The target configuration could have changed since we started placement. In this case, + // we're starting another placement run. + if (placedConfig != targetConfig) { + redoPlacement(); + } } else { std::stringstream message; message << "Failed to parse [" << std::string(id) << "]: " << result.get<std::string>(); @@ -156,34 +164,36 @@ Bucket* VectorTileData::getBucket(const StyleLayer& layer) { return it->second.get(); } -void VectorTileData::redoPlacement(float angle, float pitch, bool collisionDebug) { - if (angle == currentAngle && pitch == currentPitch && collisionDebug == currentCollisionDebug) - return; - - lastAngle = angle; - lastPitch = pitch; - lastCollisionDebug = collisionDebug; +void VectorTileData::redoPlacement(const PlacementConfig newConfig) { + if (newConfig != placedConfig) { + targetConfig = newConfig; - if (workRequest) { - // Don't start a new placement request when the current one hasn't completed yet, or when - // we are parsing buckets. - return; + if (!workRequest) { + // Don't start a new placement request when the current one hasn't completed yet, or when + // we are parsing buckets. + redoPlacement(); + } } +} - currentAngle = angle; - currentPitch = pitch; - currentCollisionDebug = collisionDebug; - +void VectorTileData::redoPlacement() { workRequest.reset(); - workRequest = worker.redoPlacement(tileWorker, buckets, angle, pitch, collisionDebug, [this] { + workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, config = targetConfig] { workRequest.reset(); - for (const auto& layer : tileWorker.layers) { - auto bucket = getBucket(*layer); - if (bucket) { - bucket->swapRenderData(); - } + + // 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(); + } + + // The target configuration could have changed since we started placement. In this case, + // we're starting another placement run. + if (placedConfig != targetConfig) { + redoPlacement(); } - redoPlacement(lastAngle, lastPitch, lastCollisionDebug); }); } diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index 8497323e52..9faffab83f 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -4,6 +4,7 @@ #include <mbgl/map/tile_data.hpp> #include <mbgl/map/tile_worker.hpp> #include <mbgl/storage/request_holder.hpp> +#include <mbgl/text/placement_config.hpp> #include <atomic> @@ -17,7 +18,7 @@ class Request; class VectorTileData : public TileData { public: VectorTileData( - const TileID&, Style&, const SourceInfo&, float angle_, float pitch_, bool collisionDebug_); + const TileID&, Style&, const SourceInfo&); ~VectorTileData(); Bucket* getBucket(const StyleLayer&) override; @@ -27,7 +28,8 @@ public: void parse(std::function<void()> callback); bool parsePending(std::function<void()> callback) override; - void redoPlacement(float angle, float pitch, bool collisionDebug) override; + void redoPlacement(PlacementConfig config) override; + void redoPlacement(); void cancel() override; @@ -43,12 +45,13 @@ private: const SourceInfo& source; RequestHolder req; std::shared_ptr<const std::string> data; - float lastAngle = 0; - float currentAngle; - float lastPitch = 0; - float currentPitch; - bool lastCollisionDebug = 0; - bool currentCollisionDebug = 0; + + // 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; }; } // namespace mbgl diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index d85dbaf858..281888d9c5 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -382,8 +382,8 @@ void SymbolBucket::placeFeatures(CollisionTile& collisionTile, bool swapImmediat // Don't sort symbols that won't overlap because it isn't necessary and // because it causes more labels to pop in and out when rotating. if (mayOverlap) { - float sin = std::sin(collisionTile.angle); - float cos = std::cos(collisionTile.angle); + const float sin = std::sin(collisionTile.config.angle); + const float cos = std::cos(collisionTile.config.angle); std::sort(symbolInstances.begin(), symbolInstances.end(), [sin, cos](SymbolInstance &a, SymbolInstance &b) { const float aRotated = sin * a.x + cos * a.y; @@ -426,8 +426,9 @@ void SymbolBucket::placeFeatures(CollisionTile& collisionTile, bool swapImmediat collisionTile.insertFeature(symbolInstance.textCollisionFeature, glyphScale); } if (glyphScale < collisionTile.maxScale) { - addSymbols<SymbolRenderData::TextBuffer, TextElementGroup>(renderDataInProgress->text, - symbolInstance.glyphQuads, glyphScale, layout.text.keep_upright, textAlongLine, collisionTile.angle); + addSymbols<SymbolRenderData::TextBuffer, TextElementGroup>( + renderDataInProgress->text, symbolInstance.glyphQuads, glyphScale, + layout.text.keep_upright, textAlongLine, collisionTile.config.angle); } } @@ -436,13 +437,16 @@ void SymbolBucket::placeFeatures(CollisionTile& collisionTile, bool swapImmediat collisionTile.insertFeature(symbolInstance.iconCollisionFeature, iconScale); } if (iconScale < collisionTile.maxScale) { - addSymbols<SymbolRenderData::IconBuffer, IconElementGroup>(renderDataInProgress->icon, - symbolInstance.iconQuads, iconScale, layout.icon.keep_upright, iconAlongLine, collisionTile.angle); + addSymbols<SymbolRenderData::IconBuffer, IconElementGroup>( + renderDataInProgress->icon, symbolInstance.iconQuads, iconScale, + layout.icon.keep_upright, iconAlongLine, collisionTile.config.angle); } } } - if (collisionTile.getDebug()) addToDebugBuffers(collisionTile); + if (collisionTile.config.debug) { + addToDebugBuffers(collisionTile); + } if (swapImmediately) swapRenderData(); } @@ -513,7 +517,7 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float void SymbolBucket::addToDebugBuffers(CollisionTile &collisionTile) { const float yStretch = collisionTile.yStretch; - const float angle = collisionTile.angle; + const float angle = collisionTile.config.angle; float angle_sin = std::sin(-angle); float angle_cos = std::cos(-angle); std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}}; @@ -562,7 +566,9 @@ void SymbolBucket::addToDebugBuffers(CollisionTile &collisionTile) { } void SymbolBucket::swapRenderData() { - renderData = std::move(renderDataInProgress); + if (renderDataInProgress) { + renderData = std::move(renderDataInProgress); + } } void SymbolBucket::drawGlyphs(SDFShader &shader) { diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp index d18860ccf5..ecd615a520 100644 --- a/src/mbgl/text/collision_tile.cpp +++ b/src/mbgl/text/collision_tile.cpp @@ -3,17 +3,16 @@ namespace mbgl { -CollisionTile::CollisionTile(const float angle_, const float pitch, bool debug_) : - angle(angle_), debug(debug_) { +CollisionTile::CollisionTile(PlacementConfig config_) : config(config_) { tree.clear(); - // Compute the transformation matrix. - float angle_sin = std::sin(angle); - float angle_cos = std::cos(angle); - rotationMatrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}}; + // Compute the transformation matrix. + const float angle_sin = std::sin(config.angle); + const float angle_cos = std::cos(config.angle); + rotationMatrix = { { angle_cos, -angle_sin, angle_sin, angle_cos } }; // Stretch boxes in y direction to account for the map tilt. - const float _yStretch = 1.0f / std::cos(pitch); + const float _yStretch = 1.0f / std::cos(config.pitch); // The amount the map is squished depends on the y position. // Sort of account for this by making all boxes a bit bigger. diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp index 3fd1b0a4c8..edd5eb61a0 100644 --- a/src/mbgl/text/collision_tile.hpp +++ b/src/mbgl/text/collision_tile.hpp @@ -2,6 +2,7 @@ #define MBGL_TEXT_COLLISION_TILE #include <mbgl/text/collision_feature.hpp> +#include <mbgl/text/placement_config.hpp> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" @@ -24,39 +25,34 @@ namespace mbgl { - namespace bg = boost::geometry; - namespace bgm = bg::model; - namespace bgi = bg::index; - typedef bgm::point<float, 2, bg::cs::cartesian> CollisionPoint; - typedef bgm::box<CollisionPoint> Box; - typedef std::pair<Box, CollisionBox> CollisionTreeBox; - typedef bgi::rtree<CollisionTreeBox, bgi::linear<16,4>> Tree; +namespace bg = boost::geometry; +namespace bgm = bg::model; +namespace bgi = bg::index; +typedef bgm::point<float, 2, bg::cs::cartesian> CollisionPoint; +typedef bgm::box<CollisionPoint> Box; +typedef std::pair<Box, CollisionBox> CollisionTreeBox; +typedef bgi::rtree<CollisionTreeBox, bgi::linear<16, 4>> Tree; class CollisionTile { +public: + explicit CollisionTile(PlacementConfig); - public: - explicit CollisionTile(float angle_, float pitch_, bool debug_); + float placeFeature(const CollisionFeature& feature); + void insertFeature(CollisionFeature& feature, const float minPlacementScale); - float placeFeature(const CollisionFeature &feature); - void insertFeature(CollisionFeature &feature, const float minPlacementScale); - - bool getDebug() { return debug; } - - const float angle = 0; + const PlacementConfig config; const float minScale = 0.5f; const float maxScale = 2.0f; float yStretch; - private: - - Box getTreeBox(const vec2<float> &anchor, const CollisionBox &box); +private: + Box getTreeBox(const vec2<float>& anchor, const CollisionBox& box); Tree tree; std::array<float, 4> rotationMatrix; - bool debug; - }; -} + +} // namespace mbgl #endif diff --git a/src/mbgl/text/placement_config.hpp b/src/mbgl/text/placement_config.hpp new file mode 100644 index 0000000000..6680f52449 --- /dev/null +++ b/src/mbgl/text/placement_config.hpp @@ -0,0 +1,28 @@ +#ifndef MBGL_TEXT_PLACEMENT_CONFIG +#define MBGL_TEXT_PLACEMENT_CONFIG + +namespace mbgl { + +class PlacementConfig { +public: + inline PlacementConfig(float angle_ = 0, float pitch_ = 0, bool debug_ = false) + : angle(angle_), pitch(pitch_), debug(debug_) { + } + + inline bool operator==(const PlacementConfig& rhs) const { + return angle == rhs.angle && pitch == rhs.pitch && debug == rhs.debug; + } + + inline bool operator!=(const PlacementConfig& rhs) const { + return !operator==(rhs); + } + +public: + float angle; + float pitch; + bool debug; +}; + +} // namespace mbgl + +#endif diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp index 371766f096..4dd6740ec1 100644 --- a/src/mbgl/util/worker.cpp +++ b/src/mbgl/util/worker.cpp @@ -37,10 +37,11 @@ public: void parseVectorTile(TileWorker* worker, const std::shared_ptr<const std::string> data, + PlacementConfig config, std::function<void(TileParseResult)> callback) { try { pbf tilePBF(reinterpret_cast<const unsigned char*>(data->data()), data->size()); - callback(worker->parseAllLayers(VectorTile(tilePBF))); + callback(worker->parseAllLayers(VectorTile(tilePBF), config)); } catch (const std::exception& ex) { callback(TileParseResult(ex.what())); } @@ -57,9 +58,10 @@ public: void parseLiveTile(TileWorker* worker, const AnnotationTile* tile, + PlacementConfig config, std::function<void(TileParseResult)> callback) { try { - callback(worker->parseAllLayers(*tile)); + callback(worker->parseAllLayers(*tile, config)); } catch (const std::exception& ex) { callback(TileParseResult(ex.what())); } @@ -67,11 +69,9 @@ public: void redoPlacement(TileWorker* worker, const std::unordered_map<std::string, std::unique_ptr<Bucket>>* buckets, - float angle, - float pitch, - bool collisionDebug, + PlacementConfig config, std::function<void()> callback) { - worker->redoPlacement(buckets, angle, pitch, collisionDebug); + worker->redoPlacement(buckets, config); callback(); } }; @@ -97,10 +97,11 @@ Worker::parseRasterTile(std::unique_ptr<RasterBucket> bucket, std::unique_ptr<WorkRequest> Worker::parseVectorTile(TileWorker& worker, const std::shared_ptr<const std::string> data, + PlacementConfig config, std::function<void(TileParseResult)> callback) { current = (current + 1) % threads.size(); return threads[current]->invokeWithCallback(&Worker::Impl::parseVectorTile, callback, &worker, - data); + data, config); } std::unique_ptr<WorkRequest> @@ -113,22 +114,21 @@ Worker::parsePendingVectorTileLayers(TileWorker& worker, std::unique_ptr<WorkRequest> Worker::parseLiveTile(TileWorker& worker, const AnnotationTile& tile, + PlacementConfig config, std::function<void(TileParseResult)> callback) { current = (current + 1) % threads.size(); return threads[current]->invokeWithCallback(&Worker::Impl::parseLiveTile, callback, &worker, - &tile); + &tile, config); } std::unique_ptr<WorkRequest> Worker::redoPlacement(TileWorker& worker, const std::unordered_map<std::string, std::unique_ptr<Bucket>>& buckets, - float angle, - float pitch, - bool collisionDebug, + PlacementConfig config, std::function<void()> callback) { current = (current + 1) % threads.size(); return threads[current]->invokeWithCallback(&Worker::Impl::redoPlacement, callback, &worker, - &buckets, angle, pitch, collisionDebug); + &buckets, config); } } // end namespace mbgl diff --git a/src/mbgl/util/worker.hpp b/src/mbgl/util/worker.hpp index 7a92a09a51..3d2665e71c 100644 --- a/src/mbgl/util/worker.hpp +++ b/src/mbgl/util/worker.hpp @@ -37,6 +37,7 @@ public: Request parseVectorTile(TileWorker&, std::shared_ptr<const std::string> data, + PlacementConfig config, std::function<void(TileParseResult)> callback); Request parsePendingVectorTileLayers(TileWorker&, @@ -44,13 +45,12 @@ public: Request parseLiveTile(TileWorker&, const AnnotationTile&, + PlacementConfig config, std::function<void(TileParseResult)> callback); Request redoPlacement(TileWorker&, const std::unordered_map<std::string, std::unique_ptr<Bucket>>&, - float angle, - float pitch, - bool collisionDebug, + PlacementConfig config, std::function<void()> callback); private: |