refactor: remove SegSegResult enum and replace by bool

it was only used to test against ::Proper so no functionality is lost.
Tests are adapted accordingly
This commit is contained in:
Balduin
2026-05-08 10:41:08 +02:00
parent 0a5361dd44
commit 74113b5330
3 changed files with 28 additions and 60 deletions
+13 -14
View File
@@ -37,7 +37,6 @@
using namespace matrix;
using geofence_utils::SegSegResult;
TEST(GeofenceUtilsTest, Orient2d)
{
@@ -57,7 +56,7 @@ TEST(GeofenceUtilsTest, SegmentsSharedEndpointNoIntersection)
Vector2f v1(1.f, 1.f);
Vector2f v2(2.f, 2.f);
EXPECT_EQ(SegSegResult::CollinearOverlap, geofence_utils::segmentsIntersect(p1, p2, v1, v2));
EXPECT_FALSE(geofence_utils::segmentsIntersect(p1, p2, v1, v2));
}
TEST(GeofenceUtilsTest, SegmentsCross)
@@ -69,7 +68,7 @@ TEST(GeofenceUtilsTest, SegmentsCross)
Vector2f v1(-0.0001f, 0.0001f);
Vector2f v2(1.f, 0.0001f);
EXPECT_EQ(SegSegResult::Proper, geofence_utils::segmentsIntersect(p1, p2, v1, v2));
EXPECT_TRUE(geofence_utils::segmentsIntersect(p1, p2, v1, v2));
}
TEST(GeofenceUtilsTest, SegmentsTouching)
@@ -82,17 +81,17 @@ TEST(GeofenceUtilsTest, SegmentsTouching)
Vector2f v1(0.f, 1.0f);
Vector2f v2(1.f, 1.0f);
// Endpoint v1 of segment cd lies on the open segment ab. Symmetric in
// argument order: the convention-laden asymmetry of the old API is gone.
EXPECT_EQ(SegSegResult::Touching, geofence_utils::segmentsIntersect(p1, p2, v1, v2));
EXPECT_EQ(SegSegResult::Touching, geofence_utils::segmentsIntersect(v1, v2, p1, p2));
// Endpoint v1 of segment cd lies on the open segment ab. segmentsIntersect
// only flags proper crossings, so an endpoint touch returns false.
EXPECT_FALSE(geofence_utils::segmentsIntersect(p1, p2, v1, v2));
EXPECT_FALSE(geofence_utils::segmentsIntersect(v1, v2, p1, p2));
// Same, but with vertical line slanted for good measure
p1(0) = -1.0f;
p2(0) = 1.0f;
EXPECT_EQ(SegSegResult::Touching, geofence_utils::segmentsIntersect(p1, p2, v1, v2));
EXPECT_EQ(SegSegResult::Touching, geofence_utils::segmentsIntersect(v1, v2, p1, p2));
EXPECT_FALSE(geofence_utils::segmentsIntersect(p1, p2, v1, v2));
EXPECT_FALSE(geofence_utils::segmentsIntersect(v1, v2, p1, p2));
}
TEST(GeofenceUtilsTest, SegmentsParallel)
@@ -104,11 +103,11 @@ TEST(GeofenceUtilsTest, SegmentsParallel)
Vector2f v2(40.f, 20.f);
// Disjoint, non-collinear: no intersection.
EXPECT_EQ(SegSegResult::None, geofence_utils::segmentsIntersect(p1, p2, v1, v2));
EXPECT_FALSE(geofence_utils::segmentsIntersect(p1, p2, v1, v2));
// A segment with itself is fully collinear-overlapping.
EXPECT_EQ(SegSegResult::CollinearOverlap, geofence_utils::segmentsIntersect(p1, p2, p1, p2));
EXPECT_EQ(SegSegResult::CollinearOverlap, geofence_utils::segmentsIntersect(v1, v2, v1, v2));
// A segment with itself is collinear-overlapping, not a proper crossing.
EXPECT_FALSE(geofence_utils::segmentsIntersect(p1, p2, p1, p2));
EXPECT_FALSE(geofence_utils::segmentsIntersect(v1, v2, v1, v2));
}
TEST(GeofenceUtilsTest, SegmentsCollinearDisjoint)
@@ -117,7 +116,7 @@ TEST(GeofenceUtilsTest, SegmentsCollinearDisjoint)
Vector2f a(0.f, 0.f), b(1.f, 0.f);
Vector2f c(2.f, 0.f), d(3.f, 0.f);
EXPECT_EQ(SegSegResult::None, geofence_utils::segmentsIntersect(a, b, c, d));
EXPECT_FALSE(geofence_utils::segmentsIntersect(a, b, c, d));
}
TEST(GeofenceUtilsTest, SegmentPolygonExclusionOutside)
+6 -30
View File
@@ -78,41 +78,17 @@ bool insideCircle(const matrix::Vector2<double> &center, float radius,
}
// O'Rourke, "Computational Geometry in C" (2nd ed.), section 1.5: SegSegInt.
// Classifies a segment-segment intersection from the four orient2d signs of
// the endpoints. No asymmetric strict/non-strict tolerance convention is
// baked in -- the caller decides which variants count as "intersecting".
SegSegResult segmentsIntersect(const matrix::Vector2f &a, const matrix::Vector2f &b,
const matrix::Vector2f &c, const matrix::Vector2f &d)
// True iff each segment strictly straddles the other's supporting line; this
// excludes endpoint-touching and collinear overlap.
bool segmentsIntersect(const matrix::Vector2f &a, const matrix::Vector2f &b,
const matrix::Vector2f &c, const matrix::Vector2f &d)
{
const int o1 = orient2d(a, b, c);
const int o2 = orient2d(a, b, d);
const int o3 = orient2d(c, d, a);
const int o4 = orient2d(c, d, b);
// Each segment strictly straddles the other's supporting line.
if (o1 && o2 && o3 && o4 && o1 != o2 && o3 != o4) {
return SegSegResult::Proper;
}
// All four points collinear: overlap iff any endpoint of one lies on the other.
if (!o1 && !o2 && !o3 && !o4) {
if (collinearBetween(a, b, c) || collinearBetween(a, b, d) ||
collinearBetween(c, d, a) || collinearBetween(c, d, b)) {
return SegSegResult::CollinearOverlap;
}
return SegSegResult::None;
}
// One endpoint sits on the other segment.
if ((!o1 && collinearBetween(a, b, c)) ||
(!o2 && collinearBetween(a, b, d)) ||
(!o3 && collinearBetween(c, d, a)) ||
(!o4 && collinearBetween(c, d, b))) {
return SegSegResult::Touching;
}
return SegSegResult::None;
return o1 && o2 && o3 && o4 && o1 != o2 && o3 != o4;
}
// Is point P strictly inside the CCW/CW interior wedge of polygon vertex V,
@@ -142,7 +118,7 @@ bool lineSegmentIntersectsPolygon(const matrix::Vector2f &start, const matrix::V
for (int i = 0; i < num_vertices; i++) {
const int prev = (i == 0) ? num_vertices - 1 : i - 1;
if (segmentsIntersect(vertices[prev], vertices[i], start, end) == SegSegResult::Proper) {
if (segmentsIntersect(vertices[prev], vertices[i], start, end)) {
return true;
}
}
+9 -16
View File
@@ -126,23 +126,16 @@ inline bool collinearBetween(const matrix::Vector2f &a,
}
/**
* Result of a 2D segment-segment intersection test. The caller decides which
* variants count as "intersecting" for its purpose -- there is no baked-in
* convention. Reference: O'Rourke, "Computational Geometry in C" (2nd ed.),
* SegSegInt, section 1.5.
* Test for a proper 2D segment-segment intersection: each segment strictly
* straddles the other's supporting line, with no endpoint lying on the other
* segment and no collinear overlap. Returns false for endpoint-touching,
* collinear-overlapping, or disjoint segments.
*
* Reference: O'Rourke, "Computational Geometry in C" (2nd ed.), SegSegInt,
* section 1.5.
*/
enum class SegSegResult {
None, ///< segments are disjoint
Proper, ///< strict interior crossing of both segments
Touching, ///< exactly one endpoint of one segment lies on the other (interior or shared endpoint)
CollinearOverlap, ///< segments are collinear and share more than a point
};
/**
* Classify the intersection of segment ab with segment cd. See SegSegResult.
*/
SegSegResult segmentsIntersect(const matrix::Vector2f &a, const matrix::Vector2f &b,
const matrix::Vector2f &c, const matrix::Vector2f &d);
bool segmentsIntersect(const matrix::Vector2f &a, const matrix::Vector2f &b,
const matrix::Vector2f &c, const matrix::Vector2f &d);
/**
* Check if a line segment and a polygon have non-empty intersection.