diff options
Diffstat (limited to 'src/mbgl/text/collision_index.cpp')
-rw-r--r-- | src/mbgl/text/collision_index.cpp | 125 |
1 files changed, 66 insertions, 59 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) { |