@@ -79,54 +79,58 @@ bool CollisionIndex::isInsideTile(float x1, float y1, float x2, float y2, const
7979}
8080
8181
82- std::pair<bool ,bool > CollisionIndex::placeFeature (CollisionFeature& feature,
82+ std::pair<bool ,bool > CollisionIndex::placeFeature (const CollisionFeature& feature,
8383 Point<float > shift,
8484 const mat4& posMatrix,
8585 const mat4& labelPlaneMatrix,
8686 const float textPixelRatio,
87- PlacedSymbol& symbol,
87+ const PlacedSymbol& symbol,
8888 const float scale,
8989 const float fontSize,
9090 const bool allowOverlap,
9191 const bool pitchWithMap,
9292 const bool collisionDebug,
9393 const optional<CollisionTileBoundaries>& avoidEdges,
94- const optional<std::function<bool (const IndexedSubfeature&)>> collisionGroupPredicate) {
94+ const optional<std::function<bool (const IndexedSubfeature&)>> collisionGroupPredicate,
95+ std::vector<ProjectedCollisionBox>& projectedBoxes) {
96+ assert (projectedBoxes.empty ());
9597 if (!feature.alongLine ) {
96- CollisionBox& box = feature.boxes .front ();
98+ const CollisionBox& box = feature.boxes .front ();
9799 const auto projectedPoint = projectAndGetPerspectiveRatio (posMatrix, box.anchor );
98100 const float tileToViewport = textPixelRatio * projectedPoint.second ;
99101 float px1 = (box.x1 + shift.x ) * tileToViewport + projectedPoint.first .x ;
100102 float py1 = (box.y1 + shift.y ) * tileToViewport + projectedPoint.first .y ;
101103 float px2 = (box.x2 + shift.x ) * tileToViewport + projectedPoint.first .x ;
102104 float py2 = (box.y2 + shift.y ) * tileToViewport + projectedPoint.first .y ;
103- box. projected = ProjectedCollisionBox{ px1, py1, px2, py2 } ;
105+ projectedBoxes. emplace_back ( px1, py1, px2, py2) ;
104106
105107 if ((avoidEdges && !isInsideTile (px1, py1, px2, py2, *avoidEdges)) ||
106108 !isInsideGrid (px1, py1, px2, py2) ||
107- (!allowOverlap && collisionGrid.hitTest (box. projected .box (), collisionGroupPredicate))) {
109+ (!allowOverlap && collisionGrid.hitTest (projectedBoxes. back () .box (), collisionGroupPredicate))) {
108110 return { false , false };
109111 }
110112
111113 return {true , isOffscreen (px1, py1, px2, py2)};
112114 } else {
113- return placeLineFeature (feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug, avoidEdges, collisionGroupPredicate);
115+ return placeLineFeature (feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug, avoidEdges, collisionGroupPredicate, projectedBoxes );
114116 }
115117}
116118
117- std::pair<bool ,bool > CollisionIndex::placeLineFeature (CollisionFeature& feature,
119+ std::pair<bool ,bool > CollisionIndex::placeLineFeature (const CollisionFeature& feature,
118120 const mat4& posMatrix,
119121 const mat4& labelPlaneMatrix,
120122 const float textPixelRatio,
121- PlacedSymbol& symbol,
123+ const PlacedSymbol& symbol,
122124 const float scale,
123125 const float fontSize,
124126 const bool allowOverlap,
125127 const bool pitchWithMap,
126128 const bool collisionDebug,
127129 const optional<CollisionTileBoundaries>& avoidEdges,
128- const optional<std::function<bool (const IndexedSubfeature&)>> collisionGroupPredicate) {
130+ const optional<std::function<bool (const IndexedSubfeature&)>> collisionGroupPredicate,
131+ std::vector<ProjectedCollisionBox>& projectedBoxes) {
129132 assert (feature.alongLine );
133+ assert (projectedBoxes.empty ());
130134 const auto tileUnitAnchorPoint = symbol.anchorPoint ;
131135 const auto projectedAnchor = projectAnchor (posMatrix, tileUnitAnchorPoint);
132136
@@ -164,8 +168,9 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
164168 }
165169
166170 bool previousCirclePlaced = false ;
171+ projectedBoxes.resize (feature.boxes .size ());
167172 for (size_t i = 0 ; i < feature.boxes .size (); i++) {
168- CollisionBox& circle = feature.boxes [i];
173+ const CollisionBox& circle = feature.boxes [i];
169174 const float boxSignedDistanceFromAnchor = circle.signedDistanceFromAnchor ;
170175 if (!firstAndLastGlyph ||
171176 (boxSignedDistanceFromAnchor < -firstTileDistance) ||
@@ -182,9 +187,9 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
182187 const float radius = tileUnitRadius * tileToViewport;
183188
184189 if (previousCirclePlaced) {
185- const CollisionBox & previousCircle = feature. boxes [i - 1 ];
186- assert (previousCircle.projected . isCircle ());
187- const auto & previousCenter = previousCircle.projected . circle ().center ;
190+ const ProjectedCollisionBox & previousCircle = projectedBoxes [i - 1 ];
191+ assert (previousCircle.isCircle ());
192+ const auto & previousCenter = previousCircle.circle ().center ;
188193 const float dx = projectedPoint.x - previousCenter.x ;
189194 const float dy = projectedPoint.y - previousCenter.y ;
190195 // The circle edges touch when the distance between their centers is 2x the radius
@@ -217,13 +222,13 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
217222 float py1 = projectedPoint.y - radius;
218223 float py2 = projectedPoint.y + radius;
219224
220- circle. projected = ProjectedCollisionBox{projectedPoint.x , projectedPoint.y , radius};
225+ projectedBoxes[i] = ProjectedCollisionBox{projectedPoint.x , projectedPoint.y , radius};
221226
222227 entirelyOffscreen &= isOffscreen (px1, py1, px2, py2);
223228 inGrid |= isInsideGrid (px1, py1, px2, py2);
224229
225230 if ((avoidEdges && !isInsideTile (px1, py1, px2, py2, *avoidEdges)) ||
226- (!allowOverlap && collisionGrid.hitTest (circle. projected .circle (), collisionGroupPredicate))) {
231+ (!allowOverlap && collisionGrid.hitTest (projectedBoxes[i] .circle (), collisionGroupPredicate))) {
227232 if (!collisionDebug) {
228233 return {false , false };
229234 } else {
@@ -238,38 +243,38 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
238243}
239244
240245
241- void CollisionIndex::insertFeature (CollisionFeature& feature, bool ignorePlacement, uint32_t bucketInstanceId, uint16_t collisionGroupId) {
246+ void CollisionIndex::insertFeature (const CollisionFeature& feature, const std::vector<ProjectedCollisionBox>& projectedBoxes , bool ignorePlacement, uint32_t bucketInstanceId, uint16_t collisionGroupId) {
242247 if (feature.alongLine ) {
243- for (auto & circle : feature. boxes ) {
244- if (!circle.projected . isCircle ()) {
248+ for (auto & circle : projectedBoxes ) {
249+ if (!circle.isCircle ()) {
245250 continue ;
246251 }
247252
248253 if (ignorePlacement) {
249254 ignoredGrid.insert (
250255 IndexedSubfeature (feature.indexedFeature , bucketInstanceId, collisionGroupId),
251- circle.projected . circle ()
256+ circle.circle ()
252257 );
253258 } else {
254259 collisionGrid.insert (
255260 IndexedSubfeature (feature.indexedFeature , bucketInstanceId, collisionGroupId),
256- circle.projected . circle ()
261+ circle.circle ()
257262 );
258263 }
259264 }
260265 } else {
261- assert (feature. boxes .size () == 1 );
262- auto & box = feature. boxes [0 ];
263- assert (box.projected . isBox ());
266+ assert (projectedBoxes .size () == 1 );
267+ auto & box = projectedBoxes [0 ];
268+ assert (box.isBox ());
264269 if (ignorePlacement) {
265270 ignoredGrid.insert (
266271 IndexedSubfeature (feature.indexedFeature , bucketInstanceId, collisionGroupId),
267- box.projected . box ()
272+ box.box ()
268273 );
269274 } else {
270275 collisionGrid.insert (
271276 IndexedSubfeature (feature.indexedFeature , bucketInstanceId, collisionGroupId),
272- box.projected . box ()
277+ box.box ()
273278 );
274279 }
275280 }
0 commit comments