Skip to content

Commit

Permalink
Make alwaysInsert toggleable (by style property), also add it for cir…
Browse files Browse the repository at this point in the history
…cular collided labels
  • Loading branch information
maurhofer-ubique committed Jan 24, 2024
1 parent 1deb3ff commit a8154db
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 32 deletions.
77 changes: 57 additions & 20 deletions shared/public/CollisionGrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ struct IndexRange {

class CollisionGrid {
public:
CollisionGrid(const std::vector<float> &vpMatrix, const Vec2I &size, float gridAngle)
CollisionGrid(const std::vector<float> &vpMatrix, const Vec2I &size, float gridAngle, bool alwaysInsert)
: vpMatrix(vpMatrix), size(size),
sinNegGridAngle(std::sin(-gridAngle * M_PI / 180.0)),
cosNegGridAngle(std::cos(-gridAngle * M_PI / 180.0)) {
cosNegGridAngle(std::cos(-gridAngle * M_PI / 180.0)),
alwaysInsert(alwaysInsert) {
cellSize = std::min(size.x, size.y) / (float) numCellsMinDim;
numCellsX = std::ceil(size.x / cellSize) + 2 * numCellsPadding;
numCellsY = std::ceil(size.y / cellSize) + 2 * numCellsPadding;
Expand Down Expand Up @@ -99,39 +100,52 @@ class CollisionGrid {
}
}

bool collision = false;
bool colliding = false;
for (int16_t y = indexRange.yMin; y <= indexRange.yMax; y++) {
for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) {
if (!collision) {
for (const auto &rect : gridRects[y][x]) {
if (CollisionUtil::checkRectCollision(projectedRectangle, rect)) {
collision = true;
if (alwaysInsert) {
colliding = true;
break;
} else {
return 1;
}
}
}
for (const auto &circle : gridCircles[y][x]) {
if (CollisionUtil::checkRectCircleCollision(projectedRectangle, circle)) {
collision = true;
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 (collision) return 1;
return 0;

return colliding ? 1 : 0;
}

/**
* Add a vector of circles (which are then projected with the provided vpMatrix) and receive the feedback, if they have collided
* with the previous content of the grid. Assumed to remain circles in the projected space. Only added, when not colliding!
*/
bool addAndCheckCollisionCircles(const std::vector<CollisionCircleF> &circles) {
uint8_t addAndCheckCollisionCircles(const std::vector<CollisionCircleF> &circles) {
if (circles.empty()) {
// No circles -> no collision
return false;
// No circles -> no colliding
return 0;
}

std::vector<std::tuple<CircleF, IndexRange, size_t, int16_t>> projectedCircles;
Expand All @@ -145,9 +159,10 @@ class CollisionGrid {

if (projectedCircles.empty()) {
// no valid IndexRanges
return true;
return 2;
}

bool colliding = false;
for (const auto &[projectedCircle, indexRange, contentHash, symbolSpacing] : projectedCircles) {

if (contentHash != 0 && symbolSpacing > 0) {
Expand All @@ -156,7 +171,12 @@ class CollisionGrid {
for (const auto &other : equalRects->second) {
// Assume equal symbol spacing for all primitives with matching content
if (CollisionUtil::checkRectCircleCollision(other, projectedCircle, symbolSpacing)) {
return true;
if (alwaysInsert) {
colliding = true;
break;
} else {
return 1;
}
}
}
}
Expand All @@ -165,7 +185,12 @@ class CollisionGrid {
for (const auto &other : equalCircles->second) {
// Assume equal symbol spacing for all primitives with matching content
if (CollisionUtil::checkCircleCollision(projectedCircle, other, symbolSpacing)) {
return true;
if (alwaysInsert) {
colliding = true;
break;
} else {
return 1;
}
}
}
}
Expand All @@ -175,20 +200,29 @@ class CollisionGrid {
for (int16_t x = indexRange.xMin; x <= indexRange.xMax; x++) {
for (const auto &rect : gridRects[y][x]) {
if (CollisionUtil::checkRectCircleCollision(rect, projectedCircle)) {
return true;
if (alwaysInsert) {
colliding = true;
break;
} else {
return 1;
}
}
}
for (const auto &circle : gridCircles[y][x]) {
if (CollisionUtil::checkCircleCollision(projectedCircle, circle)) {
return true;
if (alwaysInsert) {
colliding = true;
break;
} else {
return 1;
}
}
}
}
}
}

// Only insert when none colliding
for (const auto &[projectedCircle, indexRange, contentHash, symbolSpacing] : 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++) {
gridCircles[y][x].push_back(projectedCircle);
Expand All @@ -198,7 +232,8 @@ class CollisionGrid {
spacedCircles[contentHash].push_back(projectedCircle);
}
}
return false;

return colliding ? 1 : 0;
}

private:
Expand Down Expand Up @@ -301,5 +336,7 @@ class CollisionGrid {
std::unordered_map<size_t, std::vector<RectF>> spacedRects;
std::unordered_map<size_t, std::vector<CircleF>> spacedCircles;

bool alwaysInsert = false;

std::vector<float> temp1 = {0, 0, 0, 0}, temp2 = {0, 0, 0, 0};
};
9 changes: 6 additions & 3 deletions shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,12 @@ void Tiled2dMapVectorLayer::update() {
if (now - lastCollitionCheck > 2000 || tilesChanged) {
lastCollitionCheck = now;
bool enforceUpdate = !prevCollisionStillValid.test_and_set();
collisionManager.syncAccess([&vpMatrix, &viewportSize, viewportRotation, enforceUpdate](const auto &manager) {
manager->collisionDetection(*vpMatrix, viewportSize, viewportRotation, enforceUpdate);
});
collisionManager.syncAccess(
[&vpMatrix, &viewportSize, viewportRotation, enforceUpdate, persistingPlacement = mapDescription->persistingSymbolPlacement](
const auto &manager) {
manager->collisionDetection(*vpMatrix, viewportSize, viewportRotation, enforceUpdate,
persistingPlacement);
});
isAnimating = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "Tiled2dMapVectorSourceSymbolCollisionManager.h"
#include "CollisionGrid.h"

void Tiled2dMapVectorSourceSymbolCollisionManager::collisionDetection(const std::vector<float> &vpMatrix, const Vec2I &viewportSize, float viewportRotation, bool enforceRecomputation) {
void Tiled2dMapVectorSourceSymbolCollisionManager::collisionDetection(const std::vector<float> &vpMatrix, const Vec2I &viewportSize, float viewportRotation, bool enforceRecomputation, bool persistingPlacement) {
std::vector<std::string> layers;
std::string currentSource;

Expand All @@ -21,7 +21,7 @@ void Tiled2dMapVectorSourceSymbolCollisionManager::collisionDetection(const std:
}
lastVpMatrix = vpMatrix;

auto collisionGrid = std::make_shared<CollisionGrid>(vpMatrix, viewportSize, viewportRotation);
auto collisionGrid = std::make_shared<CollisionGrid>(vpMatrix, viewportSize, viewportRotation, persistingPlacement);

const auto lambda = [&collisionGrid, &layers](auto manager){
if (auto strongManager = manager.lock()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Tiled2dMapVectorSourceSymbolCollisionManager: public ActorObject {
public:
Tiled2dMapVectorSourceSymbolCollisionManager(const std::unordered_map<std::string, WeakActor<Tiled2dMapVectorSourceSymbolDataManager>> &symbolSourceDataManagers,
std::shared_ptr<VectorMapDescription> mapDescription): symbolSourceDataManagers(symbolSourceDataManagers), mapDescription(mapDescription) {};
void collisionDetection(const std::vector<float> &vpMatrix, const Vec2I &viewportSize, float viewportRotation, bool enforceRecomputation);
void collisionDetection(const std::vector<float> &vpMatrix, const Vec2I &viewportSize, float viewportRotation, bool enforceRecomputation, bool persistingPlacement);
private:
std::unordered_map<std::string, WeakActor<Tiled2dMapVectorSourceSymbolDataManager>> symbolSourceDataManagers;
std::shared_ptr<VectorMapDescription> mapDescription;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -627,10 +627,10 @@ void Tiled2dMapVectorSourceSymbolDataManager::collisionDetection(std::vector<std
const auto objectsIt = symbolGroupsMap.find(layerIdentifier);
if (objectsIt != symbolGroupsMap.end()) {
for (auto &symbolGroup: std::get<1>(objectsIt->second)) {
symbolGroup.syncAccess([&allObjects, zoomIdentifier](auto group){
auto objects = group->getSymbolObjectsForCollision();
allObjects.reserve(allObjects.size() + objects.size());
allObjects.insert(allObjects.end(), std::make_move_iterator(objects.begin()), std::make_move_iterator(objects.end()));
symbolGroup.syncAccess([&allObjects](auto group){
for(auto& o : group->getSymbolObjectsForCollision()) {
allObjects.push_back(o);
}
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,11 +866,13 @@ void Tiled2dMapVectorSymbolObject::collisionDetection(const double zoomIdentifie
std::optional<std::vector<CollisionCircleF>> boundingCircles = getMapAlignedBoundingCircles(zoomIdentifier, textSymbolPlacement != TextSymbolPlacement::POINT, true);
// Collide, if no valid boundingCircles
if (boundingCircles.has_value()) {
willCollide = collisionGrid->addAndCheckCollisionCircles(*boundingCircles);
auto check = collisionGrid->addAndCheckCollisionCircles(*boundingCircles);
willCollide = check == 1;
outside = check == 2;
} else {
willCollide = false;
outside = false;
}
outside = false;
}

if (persistingSymbolPlacement) {
Expand Down

0 comments on commit a8154db

Please sign in to comment.