diff --git a/shared/public/CollisionUtil.h b/shared/public/CollisionUtil.h index 1811f2719..68cc5ee45 100644 --- a/shared/public/CollisionUtil.h +++ b/shared/public/CollisionUtil.h @@ -106,7 +106,7 @@ class CollisionUtil { {} }; - static std::optional getProjectedCircle(const CollisionCircleD &circle, CollisionEnvironment &env) { + static std::optional getProjectedCircle(double x, double y, double radius, CollisionEnvironment &env) { if (env.is3d) { // Earth center env.temp2.x = 0 - env.origin.x; @@ -119,8 +119,8 @@ class CollisionUtil { double earthCenterZ = env.temp1.z / env.temp1.w; double sinX, cosX, sinY, cosY; - lut::sincos(circle.y, sinY, cosY); - lut::sincos(circle.x, sinX, cosX); + lut::sincos(y, sinY, cosY); + lut::sincos(x, sinX, cosX); env.temp2.x = 1.0 * sinY * cosX - env.origin.x; env.temp2.y = 1.0 * cosY - env.origin.y; @@ -143,10 +143,10 @@ class CollisionUtil { double originX = env.temp1.x * env.halfWidth + env.halfWidth; double originY = env.temp1.y * env.halfHeight + env.halfHeight; - return CircleD {originX, originY, circle.radius}; + return CircleD {originX, originY, radius}; } else { - env.temp2.x = circle.x - env.origin.x; - env.temp2.y = circle.y - env.origin.y; + env.temp2.x = x - env.origin.x; + env.temp2.y = y - env.origin.y; env.temp2.z = 0.0; env.temp2.w = 1.0; @@ -155,8 +155,8 @@ class CollisionUtil { double originX = (env.temp1.x / env.temp1.w) * env.halfWidth + env.halfWidth; double originY = (env.temp1.y / env.temp1.w) * env.halfHeight + env.halfHeight; - env.temp2.x = circle.radius; - env.temp2.y = circle.radius; + env.temp2.x = radius; + env.temp2.y = radius; env.temp2.z = 0.0; env.temp2.w = 0.0; @@ -169,6 +169,10 @@ class CollisionUtil { } } + static std::optional getProjectedCircle(const CollisionCircleD &circle, CollisionEnvironment &env) { + return getProjectedCircle(circle.x, circle.y, circle.radius, env); + } + static std::optional getProjectedRectangle(const CollisionRectD &rectangle, CollisionEnvironment &env) { if (env.is3d) { // Earth center @@ -260,4 +264,14 @@ class CollisionUtil { return RectD {originX, originY, std::abs(width), std::abs(height)}; } } + + static bool checkProjectedCirclesCollision(const std::vector &circles, const CircleD &circle2, CollisionEnvironment &env, int32_t addSpacing = 0) { + for (const auto &circle : circles) { + const auto &projectedCircle = getProjectedCircle(circle.x, circle.y, circle.radius, env); + if (projectedCircle && checkCircleCollision(*projectedCircle, circle2, addSpacing)) { + return true; + } + } + return false; + } }; diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolObject.cpp b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolObject.cpp index 447438ef4..5a99646b8 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolObject.cpp +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolObject.cpp @@ -1055,9 +1055,19 @@ std::optional> Tiled2dMapVectorSymbolO } } else { - if ((labelObject && labelObject->boundingBoxCircles.has_value() && CollisionUtil::checkCirclesCollision(*labelObject->boundingBoxCircles, clickHitCircle)) - || (iconBoundingBoxViewportAligned.width != 0 && CollisionUtil::checkRectCircleCollision(iconBoundingBoxViewportAligned, clickHitCircle)) - || (stretchIconBoundingBoxViewportAligned.width != 0 && CollisionUtil::checkRectCircleCollision(stretchIconBoundingBoxViewportAligned, clickHitCircle))) { + const bool labelHit = labelObject && labelObject->boundingBoxCircles.has_value() && + CollisionUtil::checkProjectedCirclesCollision(*labelObject->boundingBoxCircles, clickHitCircle, collisionEnvironment); + if (labelHit) { + return std::make_tuple(Coord(systemIdentifier, coordinate.x, coordinate.y, 0.0), featureContext->getFeatureInfo(stringTable)); + } + + const bool iconHit = iconBoundingBoxViewportAligned.width != 0 && CollisionUtil::checkRectCircleCollision(iconBoundingBoxViewportAligned, clickHitCircle); + if (iconHit) { + return std::make_tuple(Coord(systemIdentifier, coordinate.x, coordinate.y, 0.0), featureContext->getFeatureInfo(stringTable)); + } + + const bool stretchIconHit = stretchIconBoundingBoxViewportAligned.width != 0 && CollisionUtil::checkRectCircleCollision(stretchIconBoundingBoxViewportAligned, clickHitCircle); + if (stretchIconHit) { return std::make_tuple(Coord(systemIdentifier, coordinate.x, coordinate.y, 0.0), featureContext->getFeatureInfo(stringTable)); } }