Skip to content

Commit 1ae5113

Browse files
committed
Make within_segment more robust with a relative tolerance
1 parent 2f6eec8 commit 1ae5113

File tree

3 files changed

+18
-42
lines changed

3 files changed

+18
-42
lines changed

include/geom/intersection_tools.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,6 @@ enum WithinSegmentResult : int {
4141
AT_END = 2,
4242
BETWEEN = 3 };
4343

44-
/**
45-
* Checks whether or not a point is within a line segment
46-
* @param s1 The first point on the segment
47-
* @param s2 The second point on the segment
48-
* @param length The segment length (for optimization if it's already computed)
49-
* @param p The point
50-
* @param tol The tolerance to use
51-
* @return Enum denoting whether or not the point is not within, at s1,
52-
* at s2, or between [s1, s2]
53-
*/
54-
WithinSegmentResult within_segment(const Point & s1,
55-
const Point & s2,
56-
const Real length,
57-
const Point & p,
58-
const Real tol = TOLERANCE);
59-
6044
/**
6145
* Checks whether or not a point is within a line segment
6246
* @param s1 The first point on the segment

src/geom/intersection_tools.C

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,40 +29,33 @@ namespace libMesh::IntersectionTools
2929

3030
WithinSegmentResult within_segment(const Point & s1,
3131
const Point & s2,
32-
const Real length,
3332
const Point & p,
3433
const Real tol)
3534
{
36-
libmesh_assert(!s1.absolute_fuzzy_equals(s2, tol));
37-
libmesh_assert_less(std::abs((s1 - s2).norm() - length), tol);
35+
libmesh_assert(!s1.relative_fuzzy_equals(s2, tol));
3836

37+
// First, check whether or not the points are collinear
38+
const auto l = s1 - s2;
39+
const auto l_norm = l.norm();
3940
const auto diff1 = p - s1;
40-
const auto diff2 = p - s2;
41-
const auto tol_scaled = tol * length;
42-
43-
if (diff1 * diff2 > tol_scaled)
44-
return NOT_WITHIN;
45-
4641
const auto diff1_norm = diff1.norm();
47-
if (diff1_norm < tol_scaled)
48-
return AT_BEGINNING;
49-
50-
const auto diff2_norm = diff2.norm();
51-
if (diff2_norm < tol_scaled)
52-
return AT_END;
42+
if ((std::abs(l * diff1) / (l_norm * diff1_norm)) < ((Real)1 - tol))
43+
return NOT_WITHIN;
5344

54-
// whether or not p is _between_ [s1, s2]
55-
if (std::abs(diff1_norm + diff2_norm - length) < tol_scaled)
45+
// If the points are collinear, make sure that p is
46+
// somewhere between [s1, s2]
47+
const auto diff2_norm = (p - s2).norm();
48+
const auto tol_scaled = tol * l_norm;
49+
if (std::abs(diff1_norm + diff2_norm - l_norm) < tol_scaled)
50+
{
51+
if (diff1_norm < tol_scaled)
52+
return AT_BEGINNING;
53+
if (diff2_norm < tol_scaled)
54+
return AT_END;
5655
return BETWEEN;
57-
return NOT_WITHIN;
58-
}
56+
}
5957

60-
WithinSegmentResult within_segment(const Point & s1,
61-
const Point & s2,
62-
const Point & p,
63-
const Real tol)
64-
{
65-
return within_segment(s1, s2, (s1 - s2).norm(), p, tol);
58+
return NOT_WITHIN;
6659
}
6760

6861
bool collinear(const Point & p1,

tests/geom/intersection_tools_test.C

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ public:
4747
else if (i == segments)
4848
within_result = IntersectionTools::WithinSegmentResult::AT_END;
4949

50-
CPPUNIT_ASSERT_EQUAL(IntersectionTools::within_segment(s1, s2, length, p), within_result);
5150
CPPUNIT_ASSERT_EQUAL(IntersectionTools::within_segment(s1, s2, p), within_result);
5251
}
5352

0 commit comments

Comments
 (0)