summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2020-01-08 10:13:25 +0200
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2020-01-08 12:43:26 +0200
commit141e4e7935038c0b63fb01b2376e52a40ceba249 (patch)
tree548ea8d91808d9056bcb2b35d97cb13aa8ded48e
parenta46b1a4e4f43efd72cedb0d788a80b781c5cfa9a (diff)
downloadqtlocation-mapboxgl-141e4e7935038c0b63fb01b2376e52a40ceba249.tar.gz
[core] Introduce CollisionBoundaries and use it in CollisionIndex
-rw-r--r--src/mbgl/text/collision_index.cpp125
-rw-r--r--src/mbgl/text/collision_index.hpp80
-rw-r--r--src/mbgl/text/placement.cpp4
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>() ||