diff --git a/shared/public/CollisionGrid.h b/shared/public/CollisionGrid.h index 8aaf388ec..99f41753b 100644 --- a/shared/public/CollisionGrid.h +++ b/shared/public/CollisionGrid.h @@ -100,42 +100,11 @@ class CollisionGrid { } } - bool colliding = false; - for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) { - for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) { - for (const auto &rect : gridRects[y][x]) { - if (CollisionUtil::checkRectCollision(projectedRectangle, rect)) { - if (alwaysInsert) { - colliding = true; - break; - } else { - return 1; - } - } - } - for (const auto &circle : gridCircles[y][x]) { - if (CollisionUtil::checkRectCircleCollision(projectedRectangle, circle)) { - if (alwaysInsert) { - colliding = true; - break; - } else { - return 1; - } - } - } - } - } - - for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) { - for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) { - gridRects[y][x].push_back(projectedRectangle); - } - } - if (rectangle.contentHash != 0 && rectangle.symbolSpacing > 0) { - spacedRects[rectangle.contentHash].push_back(projectedRectangle); + if (alwaysInsert) { + return checkRectInsertAlways(rectangle, projectedRectangle, indexRange); + } else { + return checkRectInsertOnCollision(rectangle, projectedRectangle, indexRange); } - - return colliding ? 1 : 0; } /** @@ -149,7 +118,7 @@ class CollisionGrid { } std::vector> projectedCircles; - for (const auto &circle : circles) { + for (const auto &circle: circles) { auto projectedCircle = getProjectedCircle(circle); IndexRange indexRange = getIndexRangeForCircle(projectedCircle); if (indexRange.isValid(numCellsX - 1, numCellsY - 1)) { @@ -162,60 +131,106 @@ class CollisionGrid { return 2; } - bool colliding = false; - for (const auto &[projectedCircle, indexRange, contentHash, symbolSpacing] : projectedCircles) { + for (const auto &[projectedCircle, indexRange, contentHash, symbolSpacing]: projectedCircles) { if (contentHash != 0 && symbolSpacing > 0) { const auto &equalRects = spacedRects.find(contentHash); if (equalRects != spacedRects.end()) { - for (const auto &other : equalRects->second) { + for (const auto &other: equalRects->second) { // Assume equal symbol spacing for all primitives with matching content if (CollisionUtil::checkRectCircleCollision(other, projectedCircle, symbolSpacing)) { - if (alwaysInsert) { - colliding = true; - break; - } else { - return 1; - } + return 1; + } } } const auto &equalCircles = spacedCircles.find(contentHash); if (equalCircles != spacedCircles.end()) { - for (const auto &other : equalCircles->second) { + for (const auto &other: equalCircles->second) { // Assume equal symbol spacing for all primitives with matching content if (CollisionUtil::checkCircleCollision(projectedCircle, other, symbolSpacing)) { - if (alwaysInsert) { - colliding = true; - break; - } else { - return 1; - } + return 1; + } + } + } + } + } + + if (alwaysInsert) { + return checkCirclesInsertAlways(circles, projectedCircles); + } else { + return checkCirclesInsertOnCollision(circles, projectedCircles); + } + } + +private: + uint8_t checkRectInsertOnCollision(const CollisionRectF &rectangle, const RectF &projectedRectangle, const IndexRange &indexRange) { + for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) { + for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) { + for (const auto &rect: gridRects[y][x]) { + if (CollisionUtil::checkRectCollision(projectedRectangle, rect)) { + return 1; + } + } + for (const auto &circle: gridCircles[y][x]) { + if (CollisionUtil::checkRectCircleCollision(projectedRectangle, circle)) { + return 1; + } + } + } + } + + for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) { + for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) { + gridRects[y][x].push_back(projectedRectangle); + } + } + if (rectangle.contentHash != 0 && rectangle.symbolSpacing > 0) { + spacedRects[rectangle.contentHash].push_back(projectedRectangle); + } + + return 0; + } + + uint8_t checkRectInsertAlways(const CollisionRectF &rectangle, const RectF &projectedRectangle, const IndexRange &indexRange) { + bool colliding = false; + for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) { + for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) { + if (!colliding) { + for (const auto &rect: gridRects[y][x]) { + if (CollisionUtil::checkRectCollision(projectedRectangle, rect)) { + colliding = true; + } + } + for (const auto &circle: gridCircles[y][x]) { + if (CollisionUtil::checkRectCircleCollision(projectedRectangle, circle)) { + colliding = true; } } } + gridRects[y][x].push_back(projectedRectangle); } + } + + if (rectangle.contentHash != 0 && rectangle.symbolSpacing > 0) { + spacedRects[rectangle.contentHash].push_back(projectedRectangle); + } + + return colliding ? 1 : 0; + } + uint8_t checkCirclesInsertOnCollision(const std::vector &circles, const std::vector> &projectedCircles) { + for (const auto &[projectedCircle, indexRange, contentHash, symbolSpacing] : projectedCircles) { for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) { for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) { for (const auto &rect : gridRects[y][x]) { if (CollisionUtil::checkRectCircleCollision(rect, projectedCircle)) { - if (alwaysInsert) { - colliding = true; - break; - } else { - return 1; - } + return 1; } } for (const auto &circle : gridCircles[y][x]) { if (CollisionUtil::checkCircleCollision(projectedCircle, circle)) { - if (alwaysInsert) { - colliding = true; - break; - } else { - return 1; - } + return 1; } } } @@ -233,10 +248,37 @@ class CollisionGrid { } } + return 0; + } + + uint8_t checkCirclesInsertAlways(const std::vector &circles, const std::vector> &projectedCircles) { + bool colliding = false; + for (const auto &[projectedCircle, indexRange, contentHash, symbolSpacing]: projectedCircles) { + for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) { + for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) { + if (!colliding) { + for (const auto &rect: gridRects[y][x]) { + if (CollisionUtil::checkRectCircleCollision(rect, projectedCircle)) { + colliding = true; + } + } + for (const auto &circle: gridCircles[y][x]) { + if (CollisionUtil::checkCircleCollision(projectedCircle, circle)) { + colliding = true; + } + } + } + gridCircles[y][x].push_back(projectedCircle); + } + } + if (contentHash != 0 && symbolSpacing > 0) { + spacedCircles[contentHash].push_back(projectedCircle); + } + } + return colliding ? 1 : 0; } -private: RectF getProjectedRectangle(const CollisionRectF &rectangle) { temp2[0] = rectangle.x - rectangle.anchorX; // move x to the anchor temp2[1] = rectangle.y - rectangle.anchorY;