mobility: Fix Rectangle::GetClosestSideOrCorner
When the tested position was outside the rectangle at a distance greater than the width/height of the rectangle, it would be incorrectly matched
This commit is contained in:
@@ -52,12 +52,28 @@ Rectangle::IsOnTheBorder(const Vector& position) const
|
||||
Rectangle::Side
|
||||
Rectangle::GetClosestSideOrCorner(const Vector& position) const
|
||||
{
|
||||
std::array<double, 4> distanceFromBorders{
|
||||
std::abs(position.x - this->xMin), // left border
|
||||
std::abs(this->xMax - position.x), // right border
|
||||
std::abs(position.y - this->yMin), // bottom border
|
||||
std::abs(this->yMax - position.y), // top border
|
||||
};
|
||||
std::array<double, 4> distanceFromBorders;
|
||||
|
||||
if (IsInside(position))
|
||||
{
|
||||
distanceFromBorders = {
|
||||
std::abs(position.x - this->xMin), // left border
|
||||
std::abs(this->xMax - position.x), // right border
|
||||
std::abs(position.y - this->yMin), // bottom border
|
||||
std::abs(this->yMax - position.y) // top border
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto yMid = (yMax + yMin) / 2;
|
||||
const auto xMid = (xMax + xMin) / 2;
|
||||
distanceFromBorders = {
|
||||
CalculateDistance(position, Vector(xMin, yMid, position.z)), // left border
|
||||
CalculateDistance(position, Vector(xMax, yMid, position.z)), // right border
|
||||
CalculateDistance(position, Vector(xMid, yMin, position.z)), // bottom border
|
||||
CalculateDistance(position, Vector(xMid, yMax, position.z)) // top border
|
||||
};
|
||||
}
|
||||
uint8_t flags = 0;
|
||||
double minDist = std::numeric_limits<double>::max();
|
||||
for (int i = 0; i < 4; i++)
|
||||
@@ -85,22 +101,12 @@ Rectangle::GetClosestSideOrCorner(const Vector& position) const
|
||||
side = TOPSIDE;
|
||||
break;
|
||||
case 0b0011:
|
||||
// Opposing sides are equally distant, so we need to check the other two
|
||||
// We also need to check if we're inside or outside.
|
||||
// Opposing sides are equally distant, so we choose top
|
||||
side = TOPSIDE;
|
||||
if (!IsInside(position))
|
||||
{
|
||||
side = (distanceFromBorders[0] > distanceFromBorders[1]) ? RIGHTSIDE : LEFTSIDE;
|
||||
}
|
||||
break;
|
||||
case 0b1100:
|
||||
// Opposing sides are equally distant, so we need to check the other two
|
||||
// We also need to check if we're inside or outside.
|
||||
// Opposing sides are equally distant, so choose right
|
||||
side = RIGHTSIDE;
|
||||
if (!IsInside(position))
|
||||
{
|
||||
side = (distanceFromBorders[2] > distanceFromBorders[3]) ? TOPSIDE : BOTTOMSIDE;
|
||||
}
|
||||
break;
|
||||
case 0b0001:
|
||||
case 0b1101:
|
||||
|
||||
@@ -87,22 +87,29 @@ RectangleClosestBorderTestSuite::RectangleClosestBorderTestSuite()
|
||||
// Rectangle in the positive x-plane to check the intersection with.
|
||||
Rectangle rectangle = Rectangle(0.0, 10.0, 0.0, 10.0);
|
||||
|
||||
/* 2 3 4
|
||||
* +----------------------------+ (10,10)
|
||||
* | 11 16 12 |
|
||||
* | |
|
||||
* | |
|
||||
* 1 | 15 18 17 | 5
|
||||
* | |
|
||||
* | |
|
||||
* | 10 14 13 |
|
||||
* +----------------------------+
|
||||
* 9 7
|
||||
* (0,0)
|
||||
/* 23 24
|
||||
* 20
|
||||
* :
|
||||
* :
|
||||
* 2 3 4
|
||||
* +----------------------------+ (10,10)
|
||||
* | 11 16 12 |
|
||||
* | |
|
||||
* | |
|
||||
* 19 .... 1 | 15 18 17 | 5 .... 21
|
||||
* | |
|
||||
* | |
|
||||
* | 10 14 13 |
|
||||
* +----------------------------+
|
||||
* 9 7
|
||||
* (0,0)
|
||||
*
|
||||
*
|
||||
*
|
||||
* 8
|
||||
* 8
|
||||
* :
|
||||
* :
|
||||
* 26 22 25
|
||||
*/
|
||||
// Left side (1 and 15)
|
||||
AddTestCase(new RectangleClosestBorderTestCase(-5, 5, rectangle, Rectangle::LEFTSIDE),
|
||||
@@ -147,6 +154,26 @@ RectangleClosestBorderTestSuite::RectangleClosestBorderTestSuite()
|
||||
// Central position (18)
|
||||
AddTestCase(new RectangleClosestBorderTestCase(5, 5, rectangle, Rectangle::TOPSIDE),
|
||||
TestCase::Duration::QUICK);
|
||||
// For coordinates to left, top, right, bottom (19, 20, 21, 22)
|
||||
AddTestCase(new RectangleClosestBorderTestCase(-30, 5, rectangle, Rectangle::LEFTSIDE),
|
||||
TestCase::Duration::QUICK);
|
||||
AddTestCase(new RectangleClosestBorderTestCase(5, 30, rectangle, Rectangle::TOPSIDE),
|
||||
TestCase::Duration::QUICK);
|
||||
AddTestCase(new RectangleClosestBorderTestCase(30, 5, rectangle, Rectangle::RIGHTSIDE),
|
||||
TestCase::Duration::QUICK);
|
||||
AddTestCase(new RectangleClosestBorderTestCase(5, -30, rectangle, Rectangle::BOTTOMSIDE),
|
||||
TestCase::Duration::QUICK);
|
||||
// For coordinates to left-top, right-top, right-bottom, left-bottom diagonals (23, 24, 25, 26)
|
||||
AddTestCase(new RectangleClosestBorderTestCase(-30, 40, rectangle, Rectangle::TOPLEFTCORNER),
|
||||
TestCase::Duration::QUICK);
|
||||
AddTestCase(new RectangleClosestBorderTestCase(40, 40, rectangle, Rectangle::TOPRIGHTCORNER),
|
||||
TestCase::Duration::QUICK);
|
||||
AddTestCase(
|
||||
new RectangleClosestBorderTestCase(40, -30, rectangle, Rectangle::BOTTOMRIGHTCORNER),
|
||||
TestCase::Duration::QUICK);
|
||||
AddTestCase(
|
||||
new RectangleClosestBorderTestCase(-30, -30, rectangle, Rectangle::BOTTOMLEFTCORNER),
|
||||
TestCase::Duration::QUICK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user