diff options
author | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2020-01-08 10:13:25 +0200 |
---|---|---|
committer | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2020-01-08 12:43:26 +0200 |
commit | 141e4e7935038c0b63fb01b2376e52a40ceba249 (patch) | |
tree | 548ea8d91808d9056bcb2b35d97cb13aa8ded48e /src/mbgl/text | |
parent | a46b1a4e4f43efd72cedb0d788a80b781c5cfa9a (diff) | |
download | qtlocation-mapboxgl-141e4e7935038c0b63fb01b2376e52a40ceba249.tar.gz |
[core] Introduce CollisionBoundaries and use it in CollisionIndex
Diffstat (limited to 'src/mbgl/text')
-rw-r--r-- | src/mbgl/text/collision_index.cpp | 125 | ||||
-rw-r--r-- | src/mbgl/text/collision_index.hpp | 80 | ||||
-rw-r--r-- | src/mbgl/text/placement.cpp | 4 |
3 files changed, 109 insertions, 100 deletions
diff --git a/src/mbgl/text/collision_index.cpp b/src/mbgl/text/collision_index.cpp index cbb1502428..d92fd27003 100644 --- a/src/mbgl/text/collision_index.cpp +++ b/src/mbgl/text/collision_index.cpp @@ -65,66 +65,72 @@ float CollisionIndex::approximateTileDistance(const TileDistance& tileDistance, (incidenceStretch - 1) * lastSegmentTile * std::abs(std::sin(lastSegmentAngle)); } -bool CollisionIndex::isOffscreen(float x1, float y1, float x2, float y2) const { - return x2 < viewportPadding || x1 >= screenRightBoundary || y2 < viewportPadding || y1 >= screenBottomBoundary; +bool CollisionIndex::isOffscreen(const CollisionBoundaries& boundaries) const { + return boundaries[2] < viewportPadding || boundaries[0] >= screenRightBoundary || boundaries[3] < viewportPadding || + boundaries[1] >= screenBottomBoundary; } -bool CollisionIndex::isInsideGrid(float x1, float y1, float x2, float y2) const { - return x2 >= 0 && x1 < gridRightBoundary && y2 >= 0 && y1 < gridBottomBoundary; +bool CollisionIndex::isInsideGrid(const CollisionBoundaries& boundaries) const { + return boundaries[2] >= 0 && boundaries[0] < gridRightBoundary && boundaries[3] >= 0 && + boundaries[1] < gridBottomBoundary; } - -CollisionTileBoundaries CollisionIndex::projectTileBoundaries(const mat4& posMatrix) const { + +CollisionBoundaries CollisionIndex::projectTileBoundaries(const mat4& posMatrix) const { Point<float> topLeft = projectPoint(posMatrix, { 0, 0 }); Point<float> bottomRight = projectPoint(posMatrix, { util::EXTENT, util::EXTENT }); return {{ topLeft.x, topLeft.y, bottomRight.x, bottomRight.y }}; - } // The tile border checks below are only well defined when the tile boundaries are axis-aligned // We are relying on it only being used in MapMode::Tile, where that is always the case -inline bool CollisionIndex::isInsideTile( - float x1, float y1, float x2, float y2, const CollisionTileBoundaries& tileBoundaries) const { - return x1 >= tileBoundaries[0] && y1 >= tileBoundaries[1] && x2 < tileBoundaries[2] && y2 < tileBoundaries[3]; +inline bool CollisionIndex::isInsideTile(const CollisionBoundaries& boundaries, + const CollisionBoundaries& tileBoundaries) const { + return boundaries[0] >= tileBoundaries[0] && boundaries[1] >= tileBoundaries[1] && + boundaries[2] < tileBoundaries[2] && boundaries[3] < tileBoundaries[3]; } -inline bool CollisionIndex::overlapsTile( - float x1, float y1, float x2, float y2, const CollisionTileBoundaries& tileBoundaries) const { - return x1 < tileBoundaries[2] && x2 > tileBoundaries[0] && y1 < tileBoundaries[3] && y2 > tileBoundaries[1]; +inline bool CollisionIndex::overlapsTile(const CollisionBoundaries& boundaries, + const CollisionBoundaries& tileBoundaries) const { + return boundaries[0] < tileBoundaries[2] && boundaries[2] > tileBoundaries[0] && + boundaries[1] < tileBoundaries[3] && boundaries[3] > tileBoundaries[1]; } bool CollisionIndex::featureIntersectsTileBorders(const CollisionFeature& feature, Point<float> shift, const mat4& posMatrix, const float textPixelRatio, - const CollisionTileBoundaries& tileEdges) const { + const CollisionBoundaries& tileEdges) const { assert(!feature.alongLine); assert(!feature.boxes.empty()); const CollisionBox& box = feature.boxes.front(); const auto projectedPoint = projectAndGetPerspectiveRatio(posMatrix, box.anchor); const float tileToViewport = textPixelRatio * projectedPoint.second; - float px1 = (box.x1 + shift.x) * tileToViewport + projectedPoint.first.x; - float py1 = (box.y1 + shift.y) * tileToViewport + projectedPoint.first.y; - float px2 = (box.x2 + shift.x) * tileToViewport + projectedPoint.first.x; - float py2 = (box.y2 + shift.y) * tileToViewport + projectedPoint.first.y; - - return overlapsTile(px1, py1, px2, py2, tileEdges) && !isInsideTile(px1, py1, px2, py2, tileEdges); + CollisionBoundaries collisionBoundaries{{ + (box.x1 + shift.x) * tileToViewport + projectedPoint.first.x, + (box.y1 + shift.y) * tileToViewport + projectedPoint.first.y, + (box.x2 + shift.x) * tileToViewport + projectedPoint.first.x, + (box.y2 + shift.y) * tileToViewport + projectedPoint.first.y, + }}; + + return overlapsTile(collisionBoundaries, tileEdges) && !isInsideTile(collisionBoundaries, tileEdges); } -std::pair<bool,bool> CollisionIndex::placeFeature(const CollisionFeature& feature, - Point<float> shift, - const mat4& posMatrix, - const mat4& labelPlaneMatrix, - const float textPixelRatio, - const PlacedSymbol& symbol, - const float scale, - const float fontSize, - const bool allowOverlap, - const bool pitchWithMap, - const bool collisionDebug, - const optional<CollisionTileBoundaries>& avoidEdges, - const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, - std::vector<ProjectedCollisionBox>& projectedBoxes) { +std::pair<bool, bool> CollisionIndex::placeFeature( + const CollisionFeature& feature, + Point<float> shift, + const mat4& posMatrix, + const mat4& labelPlaneMatrix, + const float textPixelRatio, + const PlacedSymbol& symbol, + const float scale, + const float fontSize, + const bool allowOverlap, + const bool pitchWithMap, + const bool collisionDebug, + const optional<CollisionBoundaries>& avoidEdges, + const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, + std::vector<ProjectedCollisionBox>& projectedBoxes) { assert(projectedBoxes.empty()); if (!feature.alongLine) { const CollisionBox& box = feature.boxes.front(); @@ -136,31 +142,32 @@ std::pair<bool,bool> CollisionIndex::placeFeature(const CollisionFeature& featur float py2 = (box.y2 + shift.y) * tileToViewport + projectedPoint.first.y; projectedBoxes.emplace_back(px1, py1, px2, py2); - if ((avoidEdges && !isInsideTile(px1, py1, px2, py2, *avoidEdges)) || - !isInsideGrid(px1, py1, px2, py2) || + CollisionBoundaries collisionBoundaries{{px1, py1, px2, py2}}; + if ((avoidEdges && !isInsideTile(collisionBoundaries, *avoidEdges)) || !isInsideGrid(collisionBoundaries) || (!allowOverlap && collisionGrid.hitTest(projectedBoxes.back().box(), collisionGroupPredicate))) { return { false, false }; } - return {true, isOffscreen(px1, py1, px2, py2)}; + return {true, isOffscreen(collisionBoundaries)}; } else { return placeLineFeature(feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug, avoidEdges, collisionGroupPredicate, projectedBoxes); } } -std::pair<bool,bool> CollisionIndex::placeLineFeature(const CollisionFeature& feature, - const mat4& posMatrix, - const mat4& labelPlaneMatrix, - const float textPixelRatio, - const PlacedSymbol& symbol, - const float scale, - const float fontSize, - const bool allowOverlap, - const bool pitchWithMap, - const bool collisionDebug, - const optional<CollisionTileBoundaries>& avoidEdges, - const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, - std::vector<ProjectedCollisionBox>& projectedBoxes) { +std::pair<bool, bool> CollisionIndex::placeLineFeature( + const CollisionFeature& feature, + const mat4& posMatrix, + const mat4& labelPlaneMatrix, + const float textPixelRatio, + const PlacedSymbol& symbol, + const float scale, + const float fontSize, + const bool allowOverlap, + const bool pitchWithMap, + const bool collisionDebug, + const optional<CollisionBoundaries>& avoidEdges, + const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, + std::vector<ProjectedCollisionBox>& projectedBoxes) { assert(feature.alongLine); assert(projectedBoxes.empty()); const auto tileUnitAnchorPoint = symbol.anchorPoint; @@ -249,17 +256,18 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(const CollisionFeature& fe } previousCirclePlaced = true; - float px1 = projectedPoint.x - radius; - float px2 = projectedPoint.x + radius; - float py1 = projectedPoint.y - radius; - float py2 = projectedPoint.y + radius; + + CollisionBoundaries collisionBoundaries{{projectedPoint.x - radius, + projectedPoint.y - radius, + projectedPoint.x + radius, + projectedPoint.y + radius}}; projectedBoxes[i] = ProjectedCollisionBox{projectedPoint.x, projectedPoint.y, radius}; - - entirelyOffscreen &= isOffscreen(px1, py1, px2, py2); - inGrid |= isInsideGrid(px1, py1, px2, py2); - if ((avoidEdges && !isInsideTile(px1, py1, px2, py2, *avoidEdges)) || + entirelyOffscreen &= isOffscreen(collisionBoundaries); + inGrid |= isInsideGrid(collisionBoundaries); + + if ((avoidEdges && !isInsideTile(collisionBoundaries, *avoidEdges)) || (!allowOverlap && collisionGrid.hitTest(projectedBoxes[i].circle(), collisionGroupPredicate))) { if (!collisionDebug) { return {false, false}; @@ -274,7 +282,6 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(const CollisionFeature& fe return {!collisionDetected && firstAndLastGlyph && inGrid, entirelyOffscreen}; } - void CollisionIndex::insertFeature(const CollisionFeature& feature, const std::vector<ProjectedCollisionBox>& projectedBoxes, bool ignorePlacement, uint32_t bucketInstanceId, uint16_t collisionGroupId) { if (feature.alongLine) { for (auto& circle : projectedBoxes) { diff --git a/src/mbgl/text/collision_index.hpp b/src/mbgl/text/collision_index.hpp index b02647037a..707353aedf 100644 --- a/src/mbgl/text/collision_index.hpp +++ b/src/mbgl/text/collision_index.hpp @@ -13,8 +13,8 @@ namespace mbgl { class PlacedSymbol; struct TileDistance; - -using CollisionTileBoundaries = std::array<float,4>; + +using CollisionBoundaries = std::array<float, 4>; // [x1, y1, x2, y2] class CollisionIndex { public: @@ -25,51 +25,53 @@ public: Point<float> shift, const mat4& posMatrix, const float textPixelRatio, - const CollisionTileBoundaries& tileEdges) const; - - std::pair<bool,bool> placeFeature(const CollisionFeature& feature, - Point<float> shift, - const mat4& posMatrix, - const mat4& labelPlaneMatrix, - const float textPixelRatio, - const PlacedSymbol& symbol, - const float scale, - const float fontSize, - const bool allowOverlap, - const bool pitchWithMap, - const bool collisionDebug, - const optional<CollisionTileBoundaries>& avoidEdges, - const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, - std::vector<ProjectedCollisionBox>& /*out*/); + const CollisionBoundaries& tileEdges) const; + + std::pair<bool, bool> placeFeature( + const CollisionFeature& feature, + Point<float> shift, + const mat4& posMatrix, + const mat4& labelPlaneMatrix, + const float textPixelRatio, + const PlacedSymbol& symbol, + const float scale, + const float fontSize, + const bool allowOverlap, + const bool pitchWithMap, + const bool collisionDebug, + const optional<CollisionBoundaries>& avoidEdges, + const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, + std::vector<ProjectedCollisionBox>& /*out*/); void insertFeature(const CollisionFeature& feature, const std::vector<ProjectedCollisionBox>&, bool ignorePlacement, uint32_t bucketInstanceId, uint16_t collisionGroupId); std::unordered_map<uint32_t, std::vector<IndexedSubfeature>> queryRenderedSymbols(const ScreenLineString&) const; - - CollisionTileBoundaries projectTileBoundaries(const mat4& posMatrix) const; + + CollisionBoundaries projectTileBoundaries(const mat4& posMatrix) const; const TransformState& getTransformState() const { return transformState; } private: - bool isOffscreen(float x1, float y1, float x2, float y2) const; - bool isInsideGrid(float x1, float y1, float x2, float y2) const; - bool isInsideTile(float x1, float y1, float x2, float y2, const CollisionTileBoundaries& tileBoundaries) const; - bool overlapsTile(float x1, float y1, float x2, float y2, const CollisionTileBoundaries& tileBoundaries) const; - - std::pair<bool,bool> placeLineFeature(const CollisionFeature& feature, - const mat4& posMatrix, - const mat4& labelPlaneMatrix, - const float textPixelRatio, - const PlacedSymbol& symbol, - const float scale, - const float fontSize, - const bool allowOverlap, - const bool pitchWithMap, - const bool collisionDebug, - const optional<CollisionTileBoundaries>& avoidEdges, - const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, - std::vector<ProjectedCollisionBox>& /*out*/); - + bool isOffscreen(const CollisionBoundaries&) const; + bool isInsideGrid(const CollisionBoundaries&) const; + bool isInsideTile(const CollisionBoundaries& box, const CollisionBoundaries& tileBoundaries) const; + bool overlapsTile(const CollisionBoundaries& box, const CollisionBoundaries& tileBoundaries) const; + + std::pair<bool, bool> placeLineFeature( + const CollisionFeature& feature, + const mat4& posMatrix, + const mat4& labelPlaneMatrix, + const float textPixelRatio, + const PlacedSymbol& symbol, + const float scale, + const float fontSize, + const bool allowOverlap, + const bool pitchWithMap, + const bool collisionDebug, + const optional<CollisionBoundaries>& avoidEdges, + const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate, + std::vector<ProjectedCollisionBox>& /*out*/); + float approximateTileDistance(const TileDistance& tileDistance, const float lastSegmentAngle, const float pixelsToTileUnits, const float cameraToAnchorDistance, const bool pitchWithMap); std::pair<float,float> projectAnchor(const mat4& posMatrix, const Point<float>& point) const; diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 6cf9c93200..9bfb1ca04a 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -174,8 +174,8 @@ void Placement::placeBucket(const SymbolBucket& bucket, auto partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(state.getZoom()); auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom()); - optional<CollisionTileBoundaries> tileBorders; - optional<CollisionTileBoundaries> avoidEdges; + optional<CollisionBoundaries> tileBorders; + optional<CollisionBoundaries> avoidEdges; if (mapMode == MapMode::Tile) tileBorders = collisionIndex.projectTileBoundaries(posMatrix); if (tileBorders && (layout.get<style::SymbolAvoidEdges>() || |