diff options
author | Chris Loer <chris.loer@gmail.com> | 2017-10-26 11:36:25 -0700 |
---|---|---|
committer | Chris Loer <chris.loer@mapbox.com> | 2017-10-26 12:38:46 -0700 |
commit | 57b81bb1176535062c158e21141978ac0edf8bf1 (patch) | |
tree | f8278c899f5df19a416f4d2377bf1d2c957d2466 | |
parent | 7633ff78618eb448ab50d36fe8f25f976863b1bc (diff) | |
download | qtlocation-mapboxgl-57b81bb1176535062c158e21141978ac0edf8bf1.tar.gz |
Stop doing collision detection in background.
Remove CollisionTile.
"Placement" in background is now just "layout for symbol buckets" (as opposed to layout for non-symbol buckets, which finishes in "redoLayout").
-rw-r--r-- | cmake/core-files.cmake | 2 | ||||
-rw-r--r-- | src/mbgl/geometry/feature_index.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/geometry/feature_index.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 100 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_layout.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/text/collision_feature.hpp | 6 | ||||
-rw-r--r-- | src/mbgl/text/collision_tile.cpp | 267 | ||||
-rw-r--r-- | src/mbgl/text/collision_tile.hpp | 71 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 36 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.hpp | 10 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_worker.cpp | 31 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_worker.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/tile/tile.hpp | 2 |
14 files changed, 35 insertions, 516 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 75d05317ef..157c305564 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -469,8 +469,6 @@ set(MBGL_CORE_FILES src/mbgl/text/collision_feature.hpp src/mbgl/text/collision_index.cpp src/mbgl/text/collision_index.hpp - src/mbgl/text/collision_tile.cpp - src/mbgl/text/collision_tile.hpp src/mbgl/text/cross_tile_symbol_index.cpp src/mbgl/text/cross_tile_symbol_index.hpp src/mbgl/text/get_anchors.cpp diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index cef531f1fd..447fe508e2 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -2,7 +2,7 @@ #include <mbgl/renderer/render_layer.hpp> #include <mbgl/renderer/query.hpp> #include <mbgl/renderer/layers/render_symbol_layer.hpp> -#include <mbgl/text/collision_tile.hpp> +#include <mbgl/text/collision_index.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/math.hpp> #include <mbgl/math/minmax.hpp> @@ -51,7 +51,7 @@ void FeatureIndex::query( const GeometryTileData& geometryTileData, const CanonicalTileID& tileID, const std::vector<const RenderLayer*>& layers, - const CollisionTile* collisionTile, + const CollisionIndex* collisionIndex, const float additionalQueryRadius) const { // Determine query radius @@ -76,11 +76,11 @@ void FeatureIndex::query( } // Query symbol features, if they've been placed. - if (!collisionTile) { + if (!collisionIndex) { return; } - std::vector<IndexedSubfeature> symbolFeatures = collisionTile->queryRenderedSymbols(queryGeometry, scale); + std::vector<IndexedSubfeature> symbolFeatures;// = collisionIndex->queryRenderedSymbols(queryGeometry, UnwrappedTileID(), scale); // TODO: hook up std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols); for (const auto& symbolFeature : symbolFeatures) { addFeature(result, symbolFeature, queryGeometry, queryOptions, geometryTileData, tileID, layers, bearing, pixelsToTileUnits); diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index 2ae7da33df..f998ab12b8 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -14,7 +14,7 @@ namespace mbgl { class RenderedQueryOptions; class RenderLayer; -class CollisionTile; +class CollisionIndex; class CanonicalTileID; class IndexedSubfeature { @@ -42,7 +42,7 @@ public: const GeometryTileData&, const CanonicalTileID&, const std::vector<const RenderLayer*>&, - const CollisionTile*, + const CollisionIndex*, const float additionalQueryRadius) const; static optional<GeometryCoordinates> translateQueryGeometry( diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 3f4abe59f6..b9f3bb8f8d 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -8,7 +8,6 @@ #include <mbgl/renderer/image_atlas.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> #include <mbgl/text/get_anchors.hpp> -#include <mbgl/text/collision_tile.hpp> #include <mbgl/text/shaping.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/utf.hpp> @@ -392,7 +391,7 @@ bool SymbolLayout::anchorIsTooClose(const std::u16string& text, const float repe return false; } -std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile) { +std::unique_ptr<SymbolBucket> SymbolLayout::place() { auto bucket = std::make_unique<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, symbolInstances); // Calculate which labels can be shown and when they can be shown and @@ -405,94 +404,37 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile) ? SymbolPlacementType::Point : layout.get<SymbolPlacement>(); - const bool mayOverlap = layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() || - layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>(); - const bool keepUpright = layout.get<TextKeepUpright>(); - // Sort symbols by their y position on the canvas so that they lower symbols - // are drawn on top of higher symbols. - // 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) { - 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 int32_t aRotated = sin * a.anchor.point.x + cos * a.anchor.point.y; - const int32_t bRotated = sin * b.anchor.point.x + cos * b.anchor.point.y; - return aRotated != bRotated ? - aRotated < bRotated : - a.index > b.index; - }); - } - // this iterates over the *bucket's* symbol instances so that it can set the placedsymbol index. TODO cleanup for (SymbolInstance &symbolInstance : bucket->symbolInstances) { const bool hasText = symbolInstance.hasText; const bool hasIcon = symbolInstance.hasIcon; - const bool iconWithoutText = layout.get<TextOptional>() || !hasText; - const bool textWithoutIcon = layout.get<IconOptional>() || !hasIcon; - - // Calculate the scales at which the text and icon can be placed without collision. - - float glyphScale = hasText ? - collisionTile.placeFeature(symbolInstance.textCollisionFeature, - layout.get<TextAllowOverlap>(), layout.get<SymbolAvoidEdges>()) : - collisionTile.minScale; - float iconScale = hasIcon ? - collisionTile.placeFeature(symbolInstance.iconCollisionFeature, - layout.get<IconAllowOverlap>(), layout.get<SymbolAvoidEdges>()) : - collisionTile.minScale; - - - // Combine the scales for icons and text. - - if (!iconWithoutText && !textWithoutIcon) { - iconScale = glyphScale = util::max(iconScale, glyphScale); - } else if (!textWithoutIcon && glyphScale) { - glyphScale = util::max(iconScale, glyphScale); - } else if (!iconWithoutText && iconScale) { - iconScale = util::max(iconScale, glyphScale); - } - const auto& feature = features.at(symbolInstance.featureIndex); // Insert final placement into collision tree and add glyphs/icons to buffers if (hasText) { - const float placementZoom = util::max(util::log2(glyphScale) + zoom, 0.0f); - collisionTile.insertFeature(symbolInstance.textCollisionFeature, glyphScale, layout.get<TextIgnorePlacement>()); - if (glyphScale < collisionTile.maxScale) { - - const float labelAngle = std::fmod((symbolInstance.anchor.angle + collisionTile.config.angle) + 2 * M_PI, 2 * M_PI); - const bool inVerticalRange = ( - (labelAngle > M_PI * 1.0 / 4.0 && labelAngle <= M_PI * 3.0 / 4) || - (labelAngle > M_PI * 5.0 / 4.0 && labelAngle <= M_PI * 7.0 / 4)); - const bool useVerticalMode = symbolInstance.writingModes & WritingModeType::Vertical && inVerticalRange; - - const Range<float> sizeData = bucket->textSizeBinder->getVertexSizeData(feature); - bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, - symbolInstance.textOffset, placementZoom, useVerticalMode, symbolInstance.line); - symbolInstance.placedTextIndices.push_back(bucket->text.placedSymbols.size() - 1); - - for (const auto& symbol : symbolInstance.glyphQuads) { - addSymbol( - bucket->text, sizeData, symbol, - keepUpright, textPlacement, symbolInstance.anchor, bucket->text.placedSymbols.back()); - } + const bool useVerticalMode = false; // TODO: Add both versions of glyphs to buckets + const Range<float> sizeData = bucket->textSizeBinder->getVertexSizeData(feature); + bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, + symbolInstance.textOffset, useVerticalMode, symbolInstance.line); + symbolInstance.placedTextIndices.push_back(bucket->text.placedSymbols.size() - 1); + + for (const auto& symbol : symbolInstance.glyphQuads) { + addSymbol( + bucket->text, sizeData, symbol, + keepUpright, textPlacement, symbolInstance.anchor, bucket->text.placedSymbols.back()); } } if (hasIcon) { - const float placementZoom = util::max(util::log2(iconScale) + zoom, 0.0f); - collisionTile.insertFeature(symbolInstance.iconCollisionFeature, iconScale, layout.get<IconIgnorePlacement>()); - if (iconScale < collisionTile.maxScale && symbolInstance.iconQuad) { + if (symbolInstance.iconQuad) { const Range<float> sizeData = bucket->iconSizeBinder->getVertexSizeData(feature); bucket->icon.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, - symbolInstance.iconOffset, placementZoom, false, symbolInstance.line); + symbolInstance.iconOffset, false, symbolInstance.line); symbolInstance.placedIconIndices.push_back(bucket->icon.placedSymbols.size() - 1); addSymbol( bucket->icon, sizeData, *symbolInstance.iconQuad, @@ -506,8 +448,8 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile) } } - if (collisionTile.config.debug) { - addToDebugBuffers(collisionTile, *bucket); + if (true) { // TODO: hook up showCollisionBoxes + addToDebugBuffers(*bucket); } return bucket; @@ -572,14 +514,12 @@ void SymbolLayout::addSymbol(Buffer& buffer, placedSymbol.glyphOffsets.push_back(symbol.glyphOffset.x); } -void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket& bucket) { +void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) { if (!hasSymbolInstances()) { return; } - const float yStretch = collisionTile.yStretch; - for (const SymbolInstance &symbolInstance : symbolInstances) { auto populateCollisionBox = [&](const auto& feature) { SymbolBucket::CollisionBuffer& collisionBuffer = feature.alongLine ? @@ -588,10 +528,10 @@ void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket& for (const CollisionBox &box : feature.boxes) { auto& anchor = box.anchor; - Point<float> tl{box.x1, box.y1 * yStretch}; - Point<float> tr{box.x2, box.y1 * yStretch}; - Point<float> bl{box.x1, box.y2 * yStretch}; - Point<float> br{box.x2, box.y2 * yStretch}; + Point<float> tl{box.x1, box.y1}; + Point<float> tr{box.x2, box.y1}; + Point<float> bl{box.x1, box.y2}; + Point<float> br{box.x2, box.y2}; static constexpr std::size_t vertexLength = 4; const std::size_t indexLength = feature.alongLine ? 4 : 8; diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp index 8cd5e7ec05..b9b11f26b9 100644 --- a/src/mbgl/layout/symbol_layout.hpp +++ b/src/mbgl/layout/symbol_layout.hpp @@ -16,7 +16,6 @@ namespace mbgl { class BucketParameters; -class CollisionTile; class SymbolBucket; class Anchor; class RenderLayer; @@ -35,9 +34,9 @@ public: GlyphDependencies&); void prepare(const GlyphMap&, const GlyphPositions&, - const ImageMap&, const ImagePositions&); + const ImageMap&, const ImagePositions&); - std::unique_ptr<SymbolBucket> place(CollisionTile&); + std::unique_ptr<SymbolBucket> place(); bool hasSymbolInstances() const; @@ -57,7 +56,7 @@ private: bool anchorIsTooClose(const std::u16string& text, const float repeatDistance, const Anchor&); std::map<std::u16string, std::vector<Anchor>> compareText; - void addToDebugBuffers(CollisionTile&, SymbolBucket&); + void addToDebugBuffers(SymbolBucket&); // Adds placed items to the buffer. template <typename Buffer> diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index c2292d45f1..f57d2ff7ed 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -19,9 +19,9 @@ namespace mbgl { class PlacedSymbol { public: PlacedSymbol(Point<float> anchorPoint_, uint16_t segment_, float lowerSize_, float upperSize_, - std::array<float, 2> lineOffset_, float placementZoom_, bool useVerticalMode_, GeometryCoordinates line_) : + std::array<float, 2> lineOffset_, bool useVerticalMode_, GeometryCoordinates line_) : anchorPoint(anchorPoint_), segment(segment_), lowerSize(lowerSize_), upperSize(upperSize_), - lineOffset(lineOffset_), placementZoom(placementZoom_), useVerticalMode(useVerticalMode_), line(std::move(line_)) + lineOffset(lineOffset_), useVerticalMode(useVerticalMode_), line(std::move(line_)) { // TODO WIP hook these up writingMode = WritingModeType::None; @@ -33,7 +33,6 @@ public: float lowerSize; float upperSize; std::array<float, 2> lineOffset; - float placementZoom; bool useVerticalMode; GeometryCoordinates line; std::vector<float> tileDistances; diff --git a/src/mbgl/text/collision_feature.hpp b/src/mbgl/text/collision_feature.hpp index edfaa924c9..8094f13a54 100644 --- a/src/mbgl/text/collision_feature.hpp +++ b/src/mbgl/text/collision_feature.hpp @@ -38,12 +38,6 @@ public: float tileUnitDistanceToAnchor; float radius; - - // TODO Placeholders for old collision tiles - float maxScale; - float placementScale; - float adjustedMaxScale(const std::array<float, 4>& , const float) const { return 1; } - }; class CollisionFeature { diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp deleted file mode 100644 index cc9b602f08..0000000000 --- a/src/mbgl/text/collision_tile.cpp +++ /dev/null @@ -1,267 +0,0 @@ -#include <mbgl/text/collision_tile.hpp> -#include <mbgl/geometry/feature_index.hpp> -#include <mbgl/math/log2.hpp> -#include <mbgl/util/constants.hpp> -#include <mbgl/util/math.hpp> -#include <mbgl/math/minmax.hpp> -#include <mbgl/util/intersection_tests.hpp> - -#include <mapbox/geometry/envelope.hpp> -#include <mapbox/geometry/multi_point.hpp> - -#include <cmath> - -namespace mbgl { - -CollisionTile::CollisionTile(PlacementConfig config_) : config(std::move(config_)) { - // 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 } }; - reverseRotationMatrix = { { angle_cos, angle_sin, -angle_sin, angle_cos } }; - - perspectiveRatio = - 1.0f + - 0.5f * (util::division(config.cameraToTileDistance, config.cameraToCenterDistance, 1.0f) - - 1.0f); - - minScale /= perspectiveRatio; - maxScale /= perspectiveRatio; - - // We can only approximate here based on the y position of the tile - // The shaders calculate a more accurate "incidence_stretch" - // at render time to calculate an effective scale for collision - // purposes, but we still want to use the yStretch approximation - // here because we can't adjust the aspect ratio of the collision - // boxes at render time. - yStretch = util::max( - 1.0f, util::division(config.cameraToTileDistance, - config.cameraToCenterDistance * std::cos(config.pitch), 1.0f)); -} - -float CollisionTile::findPlacementScale(const Point<float>& anchor, const CollisionBox& box, const float boxMaxScale, const Point<float>& blockingAnchor, const CollisionBox& blocking) { - float minPlacementScale = minScale; - - // Find the lowest scale at which the two boxes can fit side by side without overlapping. - // Original algorithm: - - const float s1 = util::division(blocking.x1 - box.x2, anchor.x - blockingAnchor.x, - 1.0f); // scale at which new box is to the left of old box - const float s2 = util::division(blocking.x2 - box.x1, anchor.x - blockingAnchor.x, - 1.0f); // scale at which new box is to the right of old box - const float s3 = util::division((blocking.y1 - box.y2) * yStretch, anchor.y - blockingAnchor.y, - 1.0f); // scale at which new box is to the top of old box - const float s4 = util::division((blocking.y2 - box.y1) * yStretch, anchor.y - blockingAnchor.y, - 1.0f); // scale at which new box is to the bottom of old box - - float collisionFreeScale = util::min(util::max(s1, s2), util::max(s3, s4)); - - if (collisionFreeScale > blocking.maxScale) { - // After a box's maxScale the label has shrunk enough that the box is no longer needed to cover it, - // so unblock the new box at the scale that the old box disappears. - collisionFreeScale = blocking.maxScale; - } - - if (collisionFreeScale > boxMaxScale) { - // If the box can only be shown after it is visible, then the box can never be shown. - // But the label can be shown after this box is not visible. - collisionFreeScale = boxMaxScale; - } - - if (collisionFreeScale > minPlacementScale && - collisionFreeScale >= blocking.placementScale) { - // If this collision occurs at a lower scale than previously found collisions - // and the collision occurs while the other label is visible - - // this this is the lowest scale at which the label won't collide with anything - minPlacementScale = collisionFreeScale; - } - - return minPlacementScale; -} - -float CollisionTile::placeFeature(const CollisionFeature& feature, bool allowOverlap, bool avoidEdges) { - static const float infinity = std::numeric_limits<float>::infinity(); - static const std::array<CollisionBox, 4> edges {{ - // left - CollisionBox(Point<float>(0, 0), { 0, 0 }, 0, -infinity, 0, infinity, infinity), - // right - CollisionBox(Point<float>(util::EXTENT, 0), { 0, 0 }, 0, -infinity, 0, infinity, infinity), - // top - CollisionBox(Point<float>(0, 0), { 0, 0 }, -infinity, 0, infinity, 0, infinity), - // bottom - CollisionBox(Point<float>(0, util::EXTENT), { 0, 0 }, -infinity, 0, infinity, 0, infinity) - }}; - - float minPlacementScale = minScale; - - for (auto& box : feature.boxes) { - const auto anchor = util::matrixMultiply(rotationMatrix, box.anchor); - - const float boxMaxScale = box.adjustedMaxScale(rotationMatrix, yStretch); - - if (!allowOverlap) { - for (auto it = tree.qbegin(bgi::intersects(getTreeBox(anchor, box))); it != tree.qend(); ++it) { - const CollisionBox& blocking = std::get<1>(*it); - Point<float> blockingAnchor = util::matrixMultiply(rotationMatrix, blocking.anchor); - - minPlacementScale = util::max(minPlacementScale, findPlacementScale(anchor, box, boxMaxScale, blockingAnchor, blocking)); - if (minPlacementScale >= maxScale) return minPlacementScale; - } - } - - if (avoidEdges) { - const Point<float> rtl = util::matrixMultiply(reverseRotationMatrix, { box.x1, box.y1 }); - const Point<float> rtr = util::matrixMultiply(reverseRotationMatrix, { box.x2, box.y1 }); - const Point<float> rbl = util::matrixMultiply(reverseRotationMatrix, { box.x1, box.y2 }); - const Point<float> rbr = util::matrixMultiply(reverseRotationMatrix, { box.x2, box.y2 }); - CollisionBox rotatedBox(box.anchor, - box.offset, - util::min(rtl.x, rtr.x, rbl.x, rbr.x), - util::min(rtl.y, rtr.y, rbl.y, rbr.y), - util::max(rtl.x, rtr.x, rbl.x, rbr.x), - util::max(rtl.y, rtr.y, rbl.y, rbr.y), - boxMaxScale); - - for (auto& blocking : edges) { - minPlacementScale = util::max(minPlacementScale, findPlacementScale(box.anchor, rotatedBox, boxMaxScale, blocking.anchor, blocking)); - if (minPlacementScale >= maxScale) return minPlacementScale; - } - } - } - - return minPlacementScale; -} - -void CollisionTile::insertFeature(CollisionFeature& feature, float minPlacementScale, bool ignorePlacement) { - for (auto& box : feature.boxes) { - box.placementScale = minPlacementScale; - } - - if (minPlacementScale < maxScale) { - std::vector<CollisionTreeBox> treeBoxes; - for (auto& box : feature.boxes) { - CollisionBox adjustedBox = box; - box.maxScale = box.adjustedMaxScale(rotationMatrix, yStretch); - treeBoxes.emplace_back(getTreeBox(util::matrixMultiply(rotationMatrix, box.anchor), box), std::move(adjustedBox), feature.indexedFeature); - } - if (ignorePlacement) { - ignoredTree.insert(treeBoxes.begin(), treeBoxes.end()); - } else { - tree.insert(treeBoxes.begin(), treeBoxes.end()); - } - } - -} - -// +---------------------------+ As you zoom, the size of the symbol changes -// |(x1,y1) | | relative to the tile e.g. when zooming in, -// | | | the symbol gets smaller relative to the tile. -// | (x1',y1') v | -// | +-------+-------+ | The boxes inserted into the tree represents -// | | | | | the bounds at the integer zoom level (where -// | | | | | the symbol is biggest relative to the tile). -// | | | | | -// |---->+-------+-------+<----| This happens because placement is updated -// | | |(xa,ya)| | once every new integer zoom level e.g. -// | | | | | std::floor(oldZoom) != std::floor(newZoom). -// | | | | | -// | +-------+-------+ | Thus, they don't represent the exact bounds -// | ^ (x2',y2') | of the symbol at the current zoom level. For -// | | | calculating the bounds at current zoom level -// | | (x2,y2)| we must unscale the box using its center as -// +---------------------------+ transform origin. -Box CollisionTile::getTreeBox(const Point<float>& anchor, const CollisionBox& box, const float scale) { - assert(box.x1 <= box.x2 && box.y1 <= box.y2); - return Box{ - // When the 'perspectiveRatio' is high, we're effectively underzooming - // the tile because it's in the distance. - // In order to detect collisions that only happen while underzoomed, - // we have to query a larger portion of the grid. - // This extra work is offset by having a lower 'maxScale' bound - // Note that this adjustment ONLY affects the bounding boxes - // in the grid. It doesn't affect the boxes used for the - // minPlacementScale calculations. - CollisionPoint{ - anchor.x + box.x1 / scale * perspectiveRatio, - anchor.y + box.y1 / scale * yStretch * perspectiveRatio, - }, - CollisionPoint{ - anchor.x + box.x2 / scale * perspectiveRatio, - anchor.y + box.y2 / scale * yStretch * perspectiveRatio - } - }; -} - -std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const GeometryCoordinates& queryGeometry, float scale) const { - std::vector<IndexedSubfeature> result; - if (queryGeometry.empty() || (tree.empty() && ignoredTree.empty())) { - return result; - } - - // Generate a rotated geometry out of the original query geometry. - // Scale has already been handled by the prior conversions. - GeometryCoordinates polygon; - for (const auto& point : queryGeometry) { - auto rotated = util::matrixMultiply(rotationMatrix, convertPoint<float>(point)); - polygon.push_back(convertPoint<int16_t>(rotated)); - } - - // Predicate for ruling out already seen features. - std::unordered_map<std::string, std::unordered_set<std::size_t>> sourceLayerFeatures; - auto seenFeature = [&] (const CollisionTreeBox& treeBox) -> bool { - const IndexedSubfeature& feature = std::get<2>(treeBox); - const auto& seenFeatures = sourceLayerFeatures[feature.sourceLayerName]; - return seenFeatures.find(feature.index) == seenFeatures.end(); - }; - - // "perspectiveRatio" is a tile-based approximation of how much larger symbols will - // be in the distance. It won't line up exactly with the actually rendered symbols - // Being exact would require running the collision detection logic in symbol_sdf.vertex - // in the CPU - const float perspectiveScale = scale / perspectiveRatio; - - // Account for the rounding done when updating symbol shader variables. - const float roundedScale = std::pow(2.0f, std::ceil(util::log2(perspectiveScale) * 10.0f) / 10.0f); - - // Check if feature is rendered (collision free) at current scale. - auto visibleAtScale = [&] (const CollisionTreeBox& treeBox) -> bool { - const CollisionBox& box = std::get<1>(treeBox); - return roundedScale >= box.placementScale && roundedScale <= box.adjustedMaxScale(rotationMatrix, yStretch); - }; - - // Check if query polygon intersects with the feature box at current scale. - auto intersectsAtScale = [&] (const CollisionTreeBox& treeBox) -> bool { - const CollisionBox& collisionBox = std::get<1>(treeBox); - const auto anchor = util::matrixMultiply(rotationMatrix, collisionBox.anchor); - - const int16_t x1 = anchor.x + (collisionBox.x1 / perspectiveScale); - const int16_t y1 = anchor.y + (collisionBox.y1 / perspectiveScale) * yStretch; - const int16_t x2 = anchor.x + (collisionBox.x2 / perspectiveScale); - const int16_t y2 = anchor.y + (collisionBox.y2 / perspectiveScale) * yStretch; - auto bbox = GeometryCoordinates { - { x1, y1 }, { x2, y1 }, { x2, y2 }, { x1, y2 } - }; - return util::polygonIntersectsPolygon(polygon, bbox); - }; - - auto predicates = bgi::satisfies(seenFeature) - && bgi::satisfies(visibleAtScale) - && bgi::satisfies(intersectsAtScale); - - auto queryTree = [&](const auto& tree_) { - for (auto it = tree_.qbegin(predicates); it != tree_.qend(); ++it) { - const IndexedSubfeature& feature = std::get<2>(*it); - auto& seenFeatures = sourceLayerFeatures[feature.sourceLayerName]; - seenFeatures.insert(feature.index); - result.push_back(feature); - } - }; - - queryTree(tree); - queryTree(ignoredTree); - - return result; -} - -} // namespace mbgl diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp deleted file mode 100644 index 9868266aa2..0000000000 --- a/src/mbgl/text/collision_tile.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include <mbgl/text/collision_feature.hpp> -#include <mbgl/text/placement_config.hpp> -#include <mbgl/tile/geometry_tile_data.hpp> - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wshadow" -#ifdef __clang__ -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -#endif -#pragma GCC diagnostic ignored "-Wpragmas" -#pragma GCC diagnostic ignored "-Wdeprecated-register" -#pragma GCC diagnostic ignored "-Wshorten-64-to-32" -#pragma GCC diagnostic ignored "-Wunused-local-typedefs" -#ifndef __clang__ -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#pragma GCC diagnostic ignored "-Wmisleading-indentation" -#endif -#include <boost/geometry.hpp> -#include <boost/geometry/geometries/point.hpp> -#include <boost/geometry/geometries/box.hpp> -#include <boost/geometry/index/rtree.hpp> -#pragma GCC diagnostic pop - -namespace mbgl { - -namespace bg = boost::geometry; -namespace bgm = bg::model; -namespace bgi = bg::index; -using CollisionPoint = bgm::point<float, 2, bg::cs::cartesian>; -using Box = bgm::box<CollisionPoint>; -using CollisionTreeBox = std::tuple<Box, CollisionBox, IndexedSubfeature>; -using Tree = bgi::rtree<CollisionTreeBox, bgi::linear<16, 4>>; - -class IndexedSubfeature; - -class CollisionTile { -public: - explicit CollisionTile(PlacementConfig); - - float placeFeature(const CollisionFeature&, bool allowOverlap, bool avoidEdges); - void insertFeature(CollisionFeature&, float minPlacementScale, bool ignorePlacement); - - std::vector<IndexedSubfeature> queryRenderedSymbols(const GeometryCoordinates&, float scale) const; - - const PlacementConfig config; - - float minScale = 0.5f; - float maxScale = 2.0f; - float yStretch; - - std::array<float, 4> rotationMatrix; - std::array<float, 4> reverseRotationMatrix; - -private: - float findPlacementScale( - const Point<float>& anchor, const CollisionBox& box, const float boxMaxScale, - const Point<float>& blockingAnchor, const CollisionBox& blocking); - Box getTreeBox(const Point<float>& anchor, const CollisionBox& box, const float scale = 1.0); - - Tree tree; - Tree ignoredTree; - - float perspectiveRatio; -}; - -} // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 8c018ce3aa..6afd5b5e2f 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -15,7 +15,6 @@ #include <mbgl/renderer/image_atlas.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/style/filter_evaluator.hpp> #include <mbgl/util/logging.hpp> @@ -57,7 +56,6 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_, parameters.pixelRatio), glyphManager(parameters.glyphManager), imageManager(parameters.imageManager), - lastYStretch(1.0f), mode(parameters.mode) { } @@ -89,25 +87,6 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) { worker.invoke(&GeometryTileWorker::setData, std::move(data_), correlationID); } -void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { - if (requestedConfig == desiredConfig) { - return; - } - - // Mark the tile as pending again if it was complete before to prevent signaling a complete - // state despite pending parse operations. - pending = true; - - ++correlationID; - requestedConfig = desiredConfig; - invokePlacement(); -} - -void GeometryTile::invokePlacement() { - if (requestedConfig) { - worker.invoke(&GeometryTileWorker::setPlacementConfig, *requestedConfig, correlationID); - } -} void GeometryTile::setLayers(const std::vector<Immutable<Layer::Impl>>& layers) { // Mark the tile as pending again if it was complete before to prevent signaling a complete @@ -141,7 +120,6 @@ void GeometryTile::onLayout(LayoutResult result, const uint64_t resultCorrelatio nonSymbolBuckets = std::move(result.nonSymbolBuckets); featureIndex = std::move(result.featureIndex); data = std::move(result.tileData); - collisionTile.reset(); observer->onTileChanged(*this); } @@ -152,16 +130,13 @@ void GeometryTile::onPlacement(PlacementResult result, const uint64_t resultCorr pending = false; } symbolBuckets = std::move(result.symbolBuckets); - collisionTile = std::move(result.collisionTile); if (result.glyphAtlasImage) { glyphAtlasImage = std::move(*result.glyphAtlasImage); } if (result.iconAtlasImage) { iconAtlasImage = std::move(*result.iconAtlasImage); } - if (collisionTile.get()) { - lastYStretch = collisionTile->yStretch; - } + observer->onTileChanged(*this); } @@ -253,7 +228,7 @@ void GeometryTile::queryRenderedFeatures( *data, id.canonical, layers, - collisionTile.get(), + 0, // TODO: hook up to global CollisionIndex additionalRadius); } @@ -293,11 +268,4 @@ void GeometryTile::querySourceFeatures( } } -float GeometryTile::yStretch() const { - // collisionTile gets reset in onLayout but we don't clear the symbolBuckets - // until a new placement result comes along, so keep the yStretch value in - // case we need to render them. - return lastYStretch; -} - } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index 23a68c0a1c..37c697d399 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -5,7 +5,6 @@ #include <mbgl/renderer/image_manager.hpp> #include <mbgl/text/glyph_manager.hpp> #include <mbgl/text/placement_config.hpp> -#include <mbgl/text/collision_tile.hpp> #include <mbgl/util/feature.hpp> #include <mbgl/util/throttler.hpp> #include <mbgl/actor/actor.hpp> @@ -37,7 +36,6 @@ public: void setError(std::exception_ptr); void setData(std::unique_ptr<const GeometryTileData>); - void setPlacementConfig(const PlacementConfig&) override; void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) override; void onGlyphsAvailable(GlyphMap) override; @@ -83,16 +81,13 @@ public: class PlacementResult { public: std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets; - std::unique_ptr<CollisionTile> collisionTile; optional<AlphaImage> glyphAtlasImage; optional<PremultipliedImage> iconAtlasImage; PlacementResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets_, - std::unique_ptr<CollisionTile> collisionTile_, optional<AlphaImage> glyphAtlasImage_, optional<PremultipliedImage> iconAtlasImage_) : symbolBuckets(std::move(symbolBuckets_)), - collisionTile(std::move(collisionTile_)), glyphAtlasImage(std::move(glyphAtlasImage_)), iconAtlasImage(std::move(iconAtlasImage_)) {} }; @@ -100,8 +95,6 @@ public: void onError(std::exception_ptr, uint64_t correlationID); - float yStretch() const override; - protected: const GeometryTileData* getData() { return data.get(); @@ -109,7 +102,6 @@ protected: private: void markObsolete(); - void invokePlacement(); const std::string sourceID; @@ -134,9 +126,7 @@ private: std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets; std::unordered_map<std::string, std::unique_ptr<SymbolLayout>> symbolLayouts; - std::unique_ptr<CollisionTile> collisionTile; - float lastYStretch; const MapMode mode; public: diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 1d3c200c8a..01c5f074e6 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -1,7 +1,6 @@ #include <mbgl/tile/geometry_tile_worker.hpp> #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/tile/geometry_tile.hpp> -#include <mbgl/text/collision_tile.hpp> #include <mbgl/layout/symbol_layout.hpp> #include <mbgl/renderer/bucket_parameters.hpp> #include <mbgl/renderer/group_by_layout.hpp> @@ -116,30 +115,6 @@ void GeometryTileWorker::setLayers(std::vector<Immutable<Layer::Impl>> layers_, } } -void GeometryTileWorker::setPlacementConfig(PlacementConfig placementConfig_, uint64_t correlationID_) { - try { - placementConfig = std::move(placementConfig_); - correlationID = correlationID_; - - switch (state) { - case Idle: - //attemptPlacement(); - coalesce(); - break; - - case Coalescing: - //state = NeedPlacement; - break; - - case NeedPlacement: - case NeedLayout: - break; - } - } catch (...) { - parent.invoke(&GeometryTile::onError, std::current_exception(), correlationID); - } -} - void GeometryTileWorker::symbolDependenciesChanged() { try { switch (state) { @@ -372,7 +347,7 @@ bool GeometryTileWorker::hasPendingSymbolDependencies() const { } void GeometryTileWorker::attemptPlacement() { - if (!data || !layers || !placementConfig || hasPendingSymbolDependencies()) { + if (!data || !layers || hasPendingSymbolDependencies()) { return; } @@ -398,7 +373,6 @@ void GeometryTileWorker::attemptPlacement() { symbolLayoutsNeedPreparation = false; } - auto collisionTile = std::make_unique<CollisionTile>(*placementConfig); std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets; for (auto& symbolLayout : symbolLayouts) { @@ -410,7 +384,7 @@ void GeometryTileWorker::attemptPlacement() { continue; } - std::shared_ptr<Bucket> bucket = symbolLayout->place(*collisionTile); + std::shared_ptr<Bucket> bucket = symbolLayout->place(); for (const auto& pair : symbolLayout->layerPaintProperties) { buckets.emplace(pair.first, bucket); } @@ -418,7 +392,6 @@ void GeometryTileWorker::attemptPlacement() { parent.invoke(&GeometryTile::onPlacement, GeometryTile::PlacementResult { std::move(buckets), - std::move(collisionTile), std::move(glyphAtlasImage), std::move(iconAtlasImage), }, correlationID); diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp index 1425daa7a1..89a51cfad0 100644 --- a/src/mbgl/tile/geometry_tile_worker.hpp +++ b/src/mbgl/tile/geometry_tile_worker.hpp @@ -35,7 +35,6 @@ public: void setLayers(std::vector<Immutable<style::Layer::Impl>>, uint64_t correlationID); void setData(std::unique_ptr<const GeometryTileData>, uint64_t correlationID); - void setPlacementConfig(PlacementConfig, uint64_t correlationID); void onGlyphsAvailable(GlyphMap glyphs); void onImagesAvailable(ImageMap images, uint64_t imageCorrelationID); @@ -75,7 +74,6 @@ private: // Outer optional indicates whether we've received it or not. optional<std::vector<Immutable<style::Layer::Impl>>> layers; optional<std::unique_ptr<const GeometryTileData>> data; - optional<PlacementConfig> placementConfig; bool symbolLayoutsNeedPreparation = false; std::vector<std::unique_ptr<SymbolLayout>> symbolLayouts; diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index 4b725a4a84..0ce814890e 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -108,8 +108,6 @@ public: // Contains the tile ID string for painting debug information. std::unique_ptr<DebugBucket> debugBucket; - - virtual float yStretch() const { return 1.0f; } protected: bool triedOptional = false; |