Skip to content

Commit 5692629

Browse files
committed
Add IntersectionTools and within_segment
1 parent ac2fdf7 commit 5692629

3 files changed

Lines changed: 194 additions & 0 deletions

File tree

include/geom/intersection_tools.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// The libMesh Finite Element Library.
2+
// Copyright (C) 2002-2022 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3+
4+
// This library is free software; you can redistribute it and/or
5+
// modify it under the terms of the GNU Lesser General Public
6+
// License as published by the Free Software Foundation; either
7+
// version 2.1 of the License, or (at your option) any later version.
8+
9+
// This library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
// Lesser General Public License for more details.
13+
14+
// You should have received a copy of the GNU Lesser General Public
15+
// License along with this library; if not, write to the Free Software
16+
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
18+
19+
20+
#ifndef LIBMESH_INTERSECTIONTOOLS_H
21+
#define LIBMESH_INTERSECTIONTOOLS_H
22+
23+
#include "libmesh/libmesh_common.h"
24+
25+
namespace libMesh
26+
{
27+
28+
class Point;
29+
30+
namespace IntersectionTools
31+
{
32+
33+
/**
34+
* Enum that represents the result of the \p within_segment() methods.
35+
*/
36+
enum WithinSegmentResult : int {
37+
NOT_WITHIN = 0,
38+
AT_BEGINNING = 1,
39+
AT_END = 2,
40+
BETWEEN = 3 };
41+
42+
/**
43+
* Checks whether or not a point is within a line segment
44+
* @param s1 The first point on the segment
45+
* @param s2 The second point on the segment
46+
* @param length The segment length (for optimization if it's already computed)
47+
* @param p The point
48+
* @param tol The tolerance to use
49+
* @return Enum denoting whether or not the point is not within, at s1,
50+
* at s2, or between [s1, s2]
51+
*/
52+
WithinSegmentResult within_segment(const Point & s1,
53+
const Point & s2,
54+
const Real length,
55+
const Point & p,
56+
const Real tol = TOLERANCE);
57+
58+
/**
59+
* Checks whether or not a point is within a line segment
60+
* @param s1 The first point on the segment
61+
* @param s2 The second point on the segment
62+
* @param p The point
63+
* @param tol The tolerance to use
64+
* @return Enum denoting whether or not the point is not within, at s1,
65+
* at s2, or between [s1, s2]
66+
*/
67+
WithinSegmentResult within_segment(const Point & s1,
68+
const Point & s2,
69+
const Point & p,
70+
const Real tol = TOLERANCE);
71+
72+
} // namespace IntersectionTools
73+
} // namespace libMesh
74+
75+
#endif // LIBMESH_INTERSECTIONTOOLS_H

src/geom/intersection_tools.C

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// The libMesh Finite Element Library.
2+
// Copyright (C) 2002-2022 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3+
4+
// This library is free software; you can redistribute it and/or
5+
// modify it under the terms of the GNU Lesser General Public
6+
// License as published by the Free Software Foundation; either
7+
// version 2.1 of the License, or (at your option) any later version.
8+
9+
// This library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
// Lesser General Public License for more details.
13+
14+
// You should have received a copy of the GNU Lesser General Public
15+
// License along with this library; if not, write to the Free Software
16+
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
18+
19+
20+
#include "libmesh/intersection_tools.h"
21+
22+
#include "libmesh/point.h"
23+
24+
namespace libMesh::IntersectionTools
25+
{
26+
27+
WithinSegmentResult within_segment(const Point & s1,
28+
const Point & s2,
29+
const Real length,
30+
const Point & p,
31+
const Real tol)
32+
{
33+
libmesh_assert(!s1.absolute_fuzzy_equals(s2, tol));
34+
libmesh_assert_less(std::abs((s1 - s2).norm() - length), tol);
35+
36+
const auto diff1 = p - s1;
37+
const auto diff2 = p - s2;
38+
const auto tol_scaled = tol * length;
39+
40+
if (diff1 * diff2 > tol_scaled)
41+
return NOT_WITHIN;
42+
43+
const auto diff1_norm = diff1.norm();
44+
if (diff1_norm < tol_scaled)
45+
return AT_BEGINNING;
46+
47+
const auto diff2_norm = diff2.norm();
48+
if (diff2_norm < tol_scaled)
49+
return AT_END;
50+
51+
// whether or not p is _between_ [s1, s2]
52+
if (std::abs(diff1_norm + diff2_norm - length) < tol_scaled)
53+
return BETWEEN;
54+
return NOT_WITHIN;
55+
}
56+
57+
WithinSegmentResult within_segment(const Point & s1,
58+
const Point & s2,
59+
const Point & p,
60+
const Real tol)
61+
{
62+
return within_segment(s1, s2, (s1 - s2).norm(), p, tol);
63+
}
64+
65+
} // namespace libMesh::IntersectionTools
66+
67+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include "libmesh_cppunit.h"
2+
3+
#include <libmesh/intersection_tools.h>
4+
#include <libmesh/point.h>
5+
#include <libmesh/int_range.h>
6+
7+
using namespace libMesh;
8+
9+
class IntersectionToolsTest : public CppUnit::TestCase
10+
{
11+
12+
public:
13+
LIBMESH_CPPUNIT_TEST_SUITE( IntersectionToolsTest );
14+
CPPUNIT_TEST( within_segment );
15+
CPPUNIT_TEST_SUITE_END();
16+
17+
public:
18+
19+
void within_segment()
20+
{
21+
LOG_UNIT_TEST;
22+
23+
const Point s1(1.0, 2.0, 3.0);
24+
const Point s2(2.0, 3.0, 4.0);
25+
const auto length_vec = s2 - s1;
26+
const auto length = length_vec.norm();
27+
const auto s1_to_s2 = length_vec / length;
28+
29+
int segments = 10;
30+
Real dx = (Real)1 / segments * length;
31+
for (const auto i : make_range(-1, segments + 1))
32+
{
33+
const auto p = s1 + Real(i) * dx * s1_to_s2;
34+
IntersectionTools::WithinSegmentResult within_result = IntersectionTools::WithinSegmentResult::NOT_WITHIN;
35+
if (i == 0)
36+
within_result = IntersectionTools::WithinSegmentResult::AT_BEGINNING;
37+
else if (i > 0 && i < segments)
38+
within_result = IntersectionTools::WithinSegmentResult::BETWEEN;
39+
else if (i == segments)
40+
within_result = IntersectionTools::WithinSegmentResult::AT_END;
41+
42+
CPPUNIT_ASSERT_EQUAL(IntersectionTools::within_segment(s1, s2, length, p), within_result);
43+
CPPUNIT_ASSERT_EQUAL(IntersectionTools::within_segment(s1, s2, p), within_result);
44+
}
45+
46+
CPPUNIT_ASSERT_EQUAL(IntersectionTools::within_segment(s1, s2, Point(9.9, 5, 3)),
47+
IntersectionTools::WithinSegmentResult::NOT_WITHIN);
48+
}
49+
50+
};
51+
52+
CPPUNIT_TEST_SUITE_REGISTRATION( IntersectionToolsTest );

0 commit comments

Comments
 (0)