libMesh
Loading...
Searching...
No Matches
bbox_test.C
Go to the documentation of this file.
1#include <libmesh/bounding_box.h>
2#include <tuple>
3#include <algorithm>
4
5#include "test_comm.h"
6#include "libmesh_cppunit.h"
7
8using namespace libMesh;
9
10class BBoxTest : public CppUnit::TestCase {
11
12public:
14#if LIBMESH_DIM > 2
19#endif
21
22public:
23 void setUp() {}
24
25 void tearDown() {}
26
28 {
29 LOG_UNIT_TEST;
30
31 // Degenerate + Non-degenerate BBox tests: A unit square bounding
32 // box is intersected with the following degenerate (planar)
33 // bounding boxes:
34 // 1.) well inside the unit bbox
35 // 2.) just barely inside the unit bbox
36 // 3.) on the surface of the unit bbox
37 // 4.) just outside the surface of the unit bbox
38 // 5.) well outside the unit bbox
39 // For the "exact" intersection test: Tests 1-3 should return true, the rest false.
40 // For the "fuzzy" intersection test: Tests 1-4 should return true with large enough TOLERANCE, the rest false.
41
42 // The smallest number for which 1 and 1 + epsilon compare unequal.
43 const Real eps = std::numeric_limits<Real>::epsilon();
44
45 // Create unit square non-degenerate BBox for intersection testing.
46 const Point
47 min(0., 0., 0.),
48 max(1., 1., 1.);
49 BoundingBox non_degenerate(min, max);
50
51 // Make (position, expected-exact-intersection, expected-fuzzy-intersection) tuples
52 typedef std::tuple<Real, bool, bool> TestTuple;
53 std::vector<TestTuple> tests =
54 {
55 std::make_tuple(0.5, true, true), // inside
56 std::make_tuple(1.0 - eps, true, true), // barely inside
57 std::make_tuple(1.0, true, true), // on
58 std::make_tuple(1.0 + eps, false, true), // barely outside
59 std::make_tuple(1.5, false, false) // outside
60 };
61
62 for (unsigned int dir = 0; dir < 3; ++dir)
63 for (const auto & t : tests)
64 {
65 // Create degenerate bounding box
66 Point dmin = min, dmax = max;
67 dmin(dir) = dmax(dir) = std::get<0>(t);
68 BoundingBox degenerate(dmin, dmax);
69
70 // std::cout << "degenerate.min() = " << degenerate.min() << std::endl;
71 // std::cout << "degenerate.max() = " << degenerate.max() << std::endl;
72
73 // Exact tests
74 CPPUNIT_ASSERT(non_degenerate.intersects(degenerate) == std::get<1>(t));
75 CPPUNIT_ASSERT(degenerate.intersects(non_degenerate) == std::get<1>(t));
76
77 // Fuzzy tests
78 CPPUNIT_ASSERT(non_degenerate.intersects(degenerate, /*abstol=*/TOLERANCE) == std::get<2>(t));
79 CPPUNIT_ASSERT(degenerate.intersects(non_degenerate, /*abstol=*/TOLERANCE) == std::get<2>(t));
80 }
81 }
82
84 {
85 LOG_UNIT_TEST;
86
87 // Degenerate + Degenerate BBox tests: test intersections of unit
88 // square degenerate (planar) bounding boxes in the x, y, and z
89 // directions in the following cases:
90 // 1.) Comparison BBox right on top of the original BBox.
91 // 2.) Comparison BBox slightly to the "left" of the original BBox.
92 // 3.) Comparison BBox slightly to the "right" of the original BBox.
93 // 4.) Comparison BBox far away from the original BBox.
94
95 // The smallest number for which 1 and 1 + epsilon compare unequal.
96 const Real eps = std::numeric_limits<Real>::epsilon();
97 // To test intersections of degenerate x, y, and z plane BBoxes,
98 // we start with an x-plane and then permute the entries of
99 // these vectors to subsequently test in the y and z directions.
100 std::vector<Real>
101 mins = {0.5, 0, 0},
102 maxs = {.5, 1, 1};
103
104 // Make (position, expected-exact-intersection, expected-fuzzy-intersection) tuples
105 typedef std::tuple<Real, bool, bool> TestTuple;
106 std::vector<TestTuple> tests =
107 {
108 std::make_tuple(0.5, true, true), // on
109 std::make_tuple(0.5 - eps, false, true), // barely left
110 std::make_tuple(0.5 + eps, false, true), // barely right
111 std::make_tuple(1.0, false, false) // off
112 };
113
114 for (unsigned int dir = 0; dir < 3; ++dir)
115 {
116 // Debugging
117 // std::cout << "dir = " << dir
118 // << ", mins = " << mins[0] << ", " << mins[1] << ", " << mins[2]
119 // << ", maxs = " << maxs[0] << ", " << maxs[1] << ", " << maxs[2]
120 // << std::endl;
121
122 const Point
123 min(Point(mins[0], mins[1], mins[2])),
124 max(Point(maxs[0], maxs[1], maxs[2]));
125 BoundingBox initial(min, max);
126
127 // Create each degenerate comparison BoundingBox and make
128 // sure the expected intersection result is found.
129 for (const auto & t : tests)
130 {
131 // Create comparison bbox
132 Point cmin = min, cmax = max;
133 cmin(dir) = cmax(dir) = std::get<0>(t);
134 BoundingBox comparison(cmin, cmax);
135
136 // Exact tests
137 CPPUNIT_ASSERT(initial.intersects(comparison) == std::get<1>(t));
138 CPPUNIT_ASSERT(comparison.intersects(initial) == std::get<1>(t));
139
140 // Fuzzy tests
141 CPPUNIT_ASSERT(initial.intersects(comparison, /*abstol=*/TOLERANCE) == std::get<2>(t));
142 CPPUNIT_ASSERT(comparison.intersects(initial, /*abstol=*/TOLERANCE) == std::get<2>(t));
143 }
144
145 // Go to the next cyclic permutation of mins and maxs by
146 // rotating the last entry off the end and onto the front of
147 // the array.
148 std::rotate(mins.rbegin(), mins.rbegin()+1, mins.rend());
149 std::rotate(maxs.rbegin(), maxs.rbegin()+1, maxs.rend());
150 }
151 }
152
154 {
155 LOG_UNIT_TEST;
156
157 // The smallest number for which 1 and 1 + epsilon compare unequal.
158 const Real eps = std::numeric_limits<Real>::epsilon();
159
160 // Non-degenerate + Non-degenerate BBox tests. These tests
161 // consider two initially unit-sized bounding boxes "stacked" in
162 // the x, y, and z directions with slight perturbations to bring
163 // them into intersection or not.
164 std::vector<Real>
165 mins = {1, 0, 0},
166 maxs = {2, 1, 1};
167
168 // All tests use the same unit bounding box for base comparisons.
169 BoundingBox initial(Point(0.,0.,0.), Point(1.,1.,1.));
170
171 // Make (position, expected-exact-intersection, expected-fuzzy-intersection) tuples
172 typedef std::tuple<Real, bool, bool> TestTuple;
173 std::vector<TestTuple> tests =
174 {
175 std::make_tuple(1., true, true), // on
176 std::make_tuple(1. + eps, false, true), // barely outside
177 std::make_tuple(1. - eps, true, true), // barely inside
178 std::make_tuple(1.5, false, false), // definitely outside
179 std::make_tuple(0.5, true, true) // definitely inside
180 };
181
182 for (unsigned int dir = 0; dir < 3; ++dir)
183 {
184 // Debugging
185 // std::cout << "dir = " << dir
186 // << ", mins = " << mins[0] << ", " << mins[1] << ", " << mins[2]
187 // << ", maxs = " << maxs[0] << ", " << maxs[1] << ", " << maxs[2]
188 // << std::endl;
189
190 const Point
191 min(Point(mins[0], mins[1], mins[2])),
192 max(Point(maxs[0], maxs[1], maxs[2]));
193
194 // Create each degenerate comparison BoundingBox and make
195 // sure the expected intersection result is found.
196 for (const auto & t : tests)
197 {
198 // Create comparison bbox with perturbed minimum coordinate.
199 Point cmin = min, cmax = max;
200 cmin(dir) = std::get<0>(t);
201 BoundingBox comparison(cmin, cmax);
202
203 // std::cout << "cmin = " << cmin << ", cmax = " << cmax << std::endl;
204
205 // Exact tests
206 CPPUNIT_ASSERT(initial.intersects(comparison) == std::get<1>(t));
207 CPPUNIT_ASSERT(comparison.intersects(initial) == std::get<1>(t));
208
209 // Fuzzy tests
210 CPPUNIT_ASSERT(initial.intersects(comparison, /*abstol=*/TOLERANCE) == std::get<2>(t));
211 CPPUNIT_ASSERT(comparison.intersects(initial, /*abstol=*/TOLERANCE) == std::get<2>(t));
212 }
213
214 // Go to the next cyclic permutation of mins and maxs by
215 // rotating the last entry off the end and onto the front of
216 // the array.
217 std::rotate(mins.rbegin(), mins.rbegin()+1, mins.rend());
218 std::rotate(maxs.rbegin(), maxs.rbegin()+1, maxs.rend());
219 }
220 }
221
223 {
224 LOG_UNIT_TEST;
225
226 // A "unit" size bounding box for making distance comparisons.
227 BoundingBox unit(Point(0.,0.,0.), Point(1.,1.,1.));
228
229 // Test points inside the box
230 LIBMESH_ASSERT_FP_EQUAL(-0.5, unit.signed_distance(Point(0.5, 0.5, 0.5)), TOLERANCE * TOLERANCE);
231 LIBMESH_ASSERT_FP_EQUAL(-0.4, unit.signed_distance(Point(0.5, 0.6, 0.5)), TOLERANCE * TOLERANCE);
232 LIBMESH_ASSERT_FP_EQUAL(-0.4, unit.signed_distance(Point(0.4, 0.5, 0.5)), TOLERANCE * TOLERANCE);
233 LIBMESH_ASSERT_FP_EQUAL(-0.1, unit.signed_distance(Point(0.1, 0.1, 0.1)), TOLERANCE * TOLERANCE);
234
235 // Test points on the box
236 LIBMESH_ASSERT_FP_EQUAL(0., unit.signed_distance(Point(1.0, 0.5, 0.5)), TOLERANCE * TOLERANCE);
237 LIBMESH_ASSERT_FP_EQUAL(0., unit.signed_distance(Point(1.0, 0., 0.)), TOLERANCE * TOLERANCE);
238
239 // Test points outside the box
240 LIBMESH_ASSERT_FP_EQUAL(0.5, unit.signed_distance(Point(1.5, 0.5, 0.5)), TOLERANCE * TOLERANCE); // right
241 LIBMESH_ASSERT_FP_EQUAL(0.5, unit.signed_distance(Point(-0.5, 0.5, 0.5)), TOLERANCE * TOLERANCE); // left
242 LIBMESH_ASSERT_FP_EQUAL(0.5, unit.signed_distance(Point(0.5, 0.5, 1.5)), TOLERANCE * TOLERANCE); // above
243 LIBMESH_ASSERT_FP_EQUAL(0.5, unit.signed_distance(Point(0.5, 0.5, -0.5)), TOLERANCE * TOLERANCE); // below
244 LIBMESH_ASSERT_FP_EQUAL(0.5, unit.signed_distance(Point(0.5, -0.5, 0.5)), TOLERANCE * TOLERANCE); // front
245 LIBMESH_ASSERT_FP_EQUAL(0.5, unit.signed_distance(Point(0.5, 1.5, 0.5)), TOLERANCE * TOLERANCE); // back
246
247 // Outside the box, closest to a corner.
248 LIBMESH_ASSERT_FP_EQUAL(std::sqrt(Real(3)), unit.signed_distance(Point(2., 2., 2.)), TOLERANCE * TOLERANCE); // Point along line (0,0,0) -> (1,1,1)
249 LIBMESH_ASSERT_FP_EQUAL(std::sqrt(Real(3)), unit.signed_distance(Point(-1., -1., -1.)), TOLERANCE * TOLERANCE); // Point along line (0,0,0) -> (1,1,1)
250 LIBMESH_ASSERT_FP_EQUAL(std::sqrt(Real(3))/2., unit.signed_distance(Point(1.5, 1.5, -0.5)), TOLERANCE * TOLERANCE); // Point along line (0.5,0.5,0.5) -> (1,1,0)
251 LIBMESH_ASSERT_FP_EQUAL(std::sqrt(Real(3))/2., unit.signed_distance(Point(1.5, -0.5, -0.5)), TOLERANCE * TOLERANCE); // Point along line (0.5,0.5,0.5) -> (1,0,0)
252 }
253};
254
CPPUNIT_TEST_SUITE_REGISTRATION(BBoxTest)
void test_no_degenerate()
Definition bbox_test.C:153
void test_two_degenerate()
Definition bbox_test.C:83
LIBMESH_CPPUNIT_TEST_SUITE(BBoxTest)
CPPUNIT_TEST(test_two_degenerate)
void test_one_degenerate()
Definition bbox_test.C:27
void tearDown()
Definition bbox_test.C:25
CPPUNIT_TEST(test_one_degenerate)
CPPUNIT_TEST(test_signed_distance)
void test_signed_distance()
Definition bbox_test.C:222
void setUp()
Definition bbox_test.C:23
CPPUNIT_TEST(test_no_degenerate)
CPPUNIT_TEST_SUITE_END()
Defines a Cartesian bounding box by the two corner extremum.
bool intersects(const BoundingBox &) const
Real signed_distance(const Point &p) const
Computes the signed distance, d, from a given Point p to this BoundingBox.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The libMesh namespace provides an interface to certain functionality in the library.
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real