Line data Source code
1 :
2 : #include "doctest/doctest.h"
3 :
4 : #include "SliceTraversal.h"
5 : #include "Intersection.h"
6 :
7 : #include <deque>
8 :
9 : using namespace elsa;
10 : using namespace doctest;
11 :
12 : #include "PrettyPrint/Eigen.h"
13 : #include "PrettyPrint/Stl.h"
14 :
15 : TEST_SUITE_BEGIN("projectors");
16 :
17 : Eigen::IOFormat vecfmt(10, 0, ", ", ", ", "", "", "[", "]");
18 : Eigen::IOFormat matfmt(10, 0, ", ", "\n", "\t\t[", "]");
19 :
20 : void checkTransformation(const RealRay_t& ray, const RealVector_t& centerOfRotation,
21 : RealVector_t expectedro, RealVector_t expectedrd,
22 : RealMatrix_t expectedRotation)
23 96 : {
24 96 : TransformToTraversal transformation(ray, centerOfRotation);
25 :
26 96 : const RealVector_t ro = ray.origin();
27 96 : const RealVector_t rd = ray.direction();
28 :
29 96 : THEN("The rotation matrix is the same as the linear part of the transformation")
30 96 : {
31 24 : CHECK_EQ(transformation.rotation(), transformation.linear());
32 24 : }
33 :
34 96 : THEN("The rotation part of the transformation matrix is correct")
35 96 : {
36 24 : const RealMatrix_t matrix = transformation.rotation();
37 :
38 24 : INFO("R :=\n", matrix.format(matfmt));
39 24 : INFO("Expected R :=\n", expectedRotation.format(matfmt));
40 :
41 24 : CHECK_UNARY(matrix.isApprox(expectedRotation));
42 24 : }
43 :
44 96 : THEN("The ray direction is transformed correctly")
45 96 : {
46 24 : const RealVector_t transformed = transformation * Vec(rd);
47 :
48 24 : INFO("R := \n", transformation.linear().format(matfmt));
49 24 : INFO("R * rd := ", transformed.format(vecfmt));
50 :
51 24 : INFO("Expected R * rd := ", expectedrd.format(vecfmt));
52 :
53 24 : CHECK_UNARY(transformed.isApprox(expectedrd));
54 24 : }
55 :
56 96 : THEN("The ray origin is transformed correctly")
57 96 : {
58 24 : const RealVector_t transformed = transformation * Point(ro);
59 :
60 24 : INFO("T :=\n", transformation.transformation().format(matfmt));
61 24 : INFO("T * ro := ", transformed.format(vecfmt));
62 :
63 24 : INFO("Expected T * ro := ", expectedro.format(vecfmt));
64 :
65 24 : CHECK_UNARY(transformed.isApprox(expectedro));
66 24 : }
67 96 : }
68 :
69 : void checkTransformationBasic(const RealRay_t& ray, const RealVector_t& centerOfRotation,
70 : RealMatrix_t rotation)
71 40 : {
72 40 : RealVector_t expectedro = RealVector_t::Zero(ray.dim());
73 40 : expectedro[0] = -4;
74 :
75 40 : RealVector_t expectedrd = RealVector_t::Zero(ray.dim());
76 40 : expectedrd[0] = 1;
77 :
78 40 : checkTransformation(ray, centerOfRotation, expectedro, expectedrd, rotation);
79 40 : }
80 :
81 : TEST_CASE("TraversalTransformation: Test transformation with ray going in +x")
82 4 : {
83 4 : auto rotation0 = Eigen::Rotation2D<real_t>(0).matrix();
84 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
85 :
86 4 : GIVEN("A ray with largest component in +x direction")
87 4 : {
88 4 : const RealVector_t ro({{-2.5, 1.5}});
89 4 : INFO("ro := ", ro.format(vecfmt));
90 :
91 4 : const RealVector_t rd({{1, 0}});
92 4 : INFO("rd := ", rd.format(vecfmt));
93 :
94 4 : const RealRay_t ray(ro, rd);
95 :
96 4 : checkTransformationBasic(ray, centerOfRotation, rotation0);
97 4 : }
98 4 : }
99 :
100 : TEST_CASE("TraversalTransformation: Test transformation with ray going in -x")
101 4 : {
102 4 : auto rotation180 = Eigen::Rotation2D<real_t>(pi_t).matrix();
103 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
104 :
105 4 : GIVEN("A ray with largest component in -x direction")
106 4 : {
107 4 : const RealVector_t ro({{5.5, 1.5}});
108 4 : INFO("ro := ", ro.format(vecfmt));
109 :
110 4 : const RealVector_t rd({{-1, 0}});
111 4 : INFO("rd := ", rd.format(vecfmt));
112 :
113 4 : const RealRay_t ray(ro, rd);
114 :
115 4 : checkTransformationBasic(ray, centerOfRotation, rotation180);
116 4 : }
117 4 : }
118 :
119 : TEST_CASE("TraversalTransformation: Test transformation with ray going in +y")
120 4 : {
121 4 : auto rotation270 = Eigen::Rotation2D<real_t>(3 * pi_t / 2).matrix();
122 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
123 :
124 4 : GIVEN("A ray with largest component in +y direction")
125 4 : {
126 4 : const RealVector_t ro({{1.5, -2.5}});
127 4 : INFO("ro := ", ro.format(vecfmt));
128 :
129 4 : const RealVector_t rd({{0, 1}});
130 4 : INFO("rd := ", rd.format(vecfmt));
131 :
132 4 : const RealRay_t ray(ro, rd);
133 :
134 4 : checkTransformationBasic(ray, centerOfRotation, rotation270);
135 4 : }
136 4 : }
137 :
138 : TEST_CASE("TraversalTransformation: Test transformation with ray going in -y")
139 4 : {
140 4 : auto rotation90 = Eigen::Rotation2D<real_t>(pi_t / 2).matrix();
141 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
142 :
143 4 : GIVEN("A ray with largest component in -y direction")
144 4 : {
145 4 : RealVector_t ro({{1.5, 5.5}});
146 4 : INFO("ro := ", ro.format(vecfmt));
147 :
148 4 : RealVector_t rd({{0, -1}});
149 4 : INFO("rd := ", rd.format(vecfmt));
150 :
151 4 : RealRay_t ray(ro, rd);
152 :
153 4 : checkTransformationBasic(ray, centerOfRotation, rotation90);
154 4 : }
155 4 : }
156 :
157 : TEST_CASE("TraversalTransformation: Test transformation with ray direction [1, 1]")
158 4 : {
159 4 : auto rotation0 = Eigen::Rotation2D<real_t>(0).matrix();
160 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
161 :
162 4 : GIVEN("A ray with equally large positive component")
163 4 : {
164 4 : RealVector_t ro({{-2.5, 1.5}});
165 4 : INFO("ro := ", ro.format(vecfmt));
166 :
167 4 : RealVector_t rd({{1, 1}});
168 4 : INFO("rd := ", rd.format(vecfmt));
169 :
170 4 : RealRay_t ray(ro, rd);
171 :
172 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0}}), RealVector_t({{1, 1}}),
173 4 : rotation0);
174 4 : }
175 4 : }
176 :
177 : TEST_CASE("TraversalTransformation: Test transformation with ray direction [1, -1]")
178 4 : {
179 4 : auto rotation0 = Eigen::Rotation2D<real_t>(0).matrix();
180 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
181 :
182 4 : GIVEN("A ray with equally large component, where only x is positive")
183 4 : {
184 4 : RealVector_t ro({{-2.5, 1.5}});
185 4 : INFO("ro := ", ro.format(vecfmt));
186 :
187 4 : RealVector_t rd({{1, -1}});
188 4 : INFO("rd := ", rd.format(vecfmt));
189 :
190 4 : RealRay_t ray(ro, rd);
191 :
192 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0}}), RealVector_t({{1, -1}}),
193 4 : rotation0);
194 4 : }
195 4 : }
196 :
197 : TEST_CASE("TraversalTransformation: Test transformation with ray direction [-1, 1]")
198 4 : {
199 4 : auto rotation180 = Eigen::Rotation2D<real_t>(pi_t).matrix();
200 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
201 :
202 4 : GIVEN("A ray with equally large component, where x is negative")
203 4 : {
204 4 : RealVector_t ro({{5.5, 1.5}});
205 4 : INFO("ro := ", ro.format(vecfmt));
206 :
207 4 : RealVector_t rd({{-1, 1}});
208 4 : INFO("rd := ", rd.format(vecfmt));
209 :
210 4 : RealRay_t ray(ro, rd);
211 :
212 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0}}), RealVector_t({{1, -1}}),
213 4 : rotation180);
214 4 : }
215 4 : }
216 :
217 : TEST_CASE("TraversalTransformation: Test transformation with ray direction [-1, -1]")
218 4 : {
219 4 : auto rotation180 = Eigen::Rotation2D<real_t>(pi_t).matrix();
220 4 : const RealVector_t centerOfRotation({{1.5, 1.5}});
221 :
222 4 : GIVEN("A ray with equally large negative component")
223 4 : {
224 4 : RealVector_t ro({{5.5, 1.5}});
225 4 : INFO("ro := ", ro.format(vecfmt));
226 :
227 4 : RealVector_t rd({{-1, -1}});
228 4 : INFO("rd := ", rd.format(vecfmt));
229 :
230 4 : RealRay_t ray(ro, rd);
231 :
232 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0}}), RealVector_t({{1, 1}}),
233 4 : rotation180);
234 4 : }
235 4 : }
236 :
237 : void checkBoundingBox(BoundingBox aabb, RealVector_t expectedMin, RealVector_t expectedMax)
238 14 : {
239 14 : CAPTURE(aabb);
240 :
241 14 : THEN("_min is as expected")
242 14 : {
243 7 : INFO("_min := ", aabb._min.format(vecfmt));
244 7 : INFO("expected _min := ", expectedMin.format(vecfmt));
245 7 : CHECK_UNARY(aabb._min.isApprox(expectedMin));
246 7 : }
247 :
248 14 : THEN("_max is as expected")
249 14 : {
250 7 : INFO("_max := ", aabb._max.format(vecfmt));
251 7 : INFO("expected _max := ", expectedMax.format(vecfmt));
252 7 : CHECK_UNARY(aabb._max.isApprox(expectedMax));
253 7 : }
254 14 : }
255 :
256 : TEST_CASE("TraversalTransformation: Transform square bounding box")
257 8 : {
258 8 : BoundingBox aabb(IndexVector_t{{5, 5}});
259 8 : CAPTURE(aabb);
260 :
261 8 : const RealVector_t expectedMin({{-2.5, -2.5}});
262 8 : const RealVector_t expectedMax({{2.5, 2.5}});
263 :
264 8 : GIVEN("A ray through the center of the bounding box point in +x direction")
265 8 : {
266 2 : const RealVector_t ro({{-1.5, 2.5}});
267 2 : const RealVector_t rd({{1, 0}});
268 :
269 2 : const RealRay_t ray(ro, rd);
270 :
271 2 : TransformToTraversal transformation(ray, aabb.center());
272 :
273 2 : WHEN("Transforming the bounding box")
274 2 : {
275 2 : auto rotatedAABB = transformation.toTraversalCoordinates(aabb);
276 2 : checkBoundingBox(rotatedAABB, expectedMin, expectedMax);
277 2 : }
278 2 : }
279 :
280 8 : GIVEN("A ray through the center of the bounding box point in -x direction")
281 8 : {
282 2 : const RealVector_t ro({{6.5, 2.5}});
283 2 : const RealVector_t rd({{-1, 0}});
284 :
285 2 : const RealRay_t ray(ro, rd);
286 :
287 2 : TransformToTraversal transformation(ray, aabb.center());
288 :
289 2 : WHEN("Transforming the bounding box")
290 2 : {
291 2 : auto rotatedAABB = transformation.toTraversalCoordinates(aabb);
292 2 : checkBoundingBox(rotatedAABB, expectedMin, expectedMax);
293 2 : }
294 2 : }
295 :
296 8 : GIVEN("A ray through the center of the bounding box point in +y direction")
297 8 : {
298 2 : const RealVector_t ro({{2.5, -1.5}});
299 2 : const RealVector_t rd({{0, 1}});
300 :
301 2 : const RealRay_t ray(ro, rd);
302 :
303 2 : TransformToTraversal transformation(ray, aabb.center());
304 :
305 2 : WHEN("Transforming the bounding box")
306 2 : {
307 2 : auto rotatedAABB = transformation.toTraversalCoordinates(aabb);
308 2 : checkBoundingBox(rotatedAABB, expectedMin, expectedMax);
309 2 : }
310 2 : }
311 :
312 8 : GIVEN("A ray through the center of the bounding box point in -y direction")
313 8 : {
314 2 : const RealVector_t ro({{2.5, 6.5}});
315 2 : const RealVector_t rd({{0, -1}});
316 :
317 2 : const RealRay_t ray(ro, rd);
318 :
319 2 : TransformToTraversal transformation(ray, aabb.center());
320 :
321 2 : WHEN("Transforming the bounding box")
322 2 : {
323 2 : auto rotatedAABB = transformation.toTraversalCoordinates(aabb);
324 2 : checkBoundingBox(rotatedAABB, expectedMin, expectedMax);
325 2 : }
326 2 : }
327 8 : }
328 :
329 : TEST_CASE("TraversalTransformation: Transform non-square bounding box")
330 6 : {
331 6 : Eigen::IOFormat fmt(4, 0, ", ", "\n", "\t\t[", "]");
332 :
333 6 : BoundingBox aabb(IndexVector_t{{8, 5}});
334 6 : CAPTURE(aabb);
335 :
336 6 : GIVEN("A ray through the center of the bounding box point in +x direction")
337 6 : {
338 2 : const RealVector_t expectedMin({{-4, -2.5}});
339 2 : const RealVector_t expectedMax({{4, 2.5}});
340 :
341 2 : const RealVector_t ro({{-1.5, 2.5}});
342 2 : const RealVector_t rd({{1, 0}});
343 :
344 2 : const RealRay_t ray(ro, rd);
345 :
346 2 : TransformToTraversal transformation(ray, aabb.center());
347 :
348 2 : WHEN("Transforming the bounding box")
349 2 : {
350 2 : auto rotatedAABB = transformation.toTraversalCoordinates(aabb);
351 2 : checkBoundingBox(rotatedAABB, expectedMin, expectedMax);
352 2 : }
353 2 : }
354 :
355 6 : const RealVector_t expectedMin({{-2.5, -4}});
356 6 : const RealVector_t expectedMax({{2.5, 4}});
357 :
358 6 : GIVEN("A ray through the center of the bounding box point in +y direction")
359 6 : {
360 :
361 2 : const RealVector_t ro({{4, -1.5}});
362 2 : const RealVector_t rd({{0, 1}});
363 :
364 2 : const RealRay_t ray(ro, rd);
365 :
366 2 : TransformToTraversal transformation(ray, aabb.center());
367 :
368 2 : WHEN("Transforming the bounding box")
369 2 : {
370 2 : auto rotatedAABB = transformation.toTraversalCoordinates(aabb);
371 2 : checkBoundingBox(rotatedAABB, expectedMin, expectedMax);
372 2 : }
373 2 : }
374 :
375 6 : GIVEN("A ray through the center of the bounding box point in -y direction")
376 6 : {
377 2 : const RealVector_t ro({{4, 6.5}});
378 2 : const RealVector_t rd({{0, -1}});
379 :
380 2 : const RealRay_t ray(ro, rd);
381 :
382 2 : TransformToTraversal transformation(ray, aabb.center());
383 :
384 2 : WHEN("Transforming the bounding box")
385 2 : {
386 2 : auto rotatedAABB = transformation.toTraversalCoordinates(aabb);
387 2 : checkBoundingBox(rotatedAABB, expectedMin, expectedMax);
388 2 : }
389 2 : }
390 6 : }
391 :
392 : index_t checkTraversal(BoundingBox aabb, RealRay_t ray, std::deque<RealVector_t> visitedVoxels)
393 43 : {
394 43 : Eigen::IOFormat fmt(10, 0, ", ", ", ", "", "", "[", "]");
395 :
396 43 : SliceTraversal traversal(aabb, ray);
397 :
398 43 : INFO("rd := ", ray.direction().format(vecfmt));
399 43 : INFO("ro := ", ray.origin().format(vecfmt));
400 :
401 43 : CAPTURE(traversal.startIndex());
402 43 : CAPTURE(traversal.endIndex());
403 43 : CHECK_EQ(traversal.endIndex(), visitedVoxels.size());
404 : // INFO("entryPoint := ", traversal.entryPoint_.format(fmt));
405 : // INFO("exitPoint := ", traversal.exitPoint_.format(fmt));
406 :
407 43 : index_t counter = 0;
408 43 : auto t = traversal.t();
409 43 : auto tdelta = traversal.tDelta();
410 145 : for (auto iter = traversal.begin(); iter != traversal.end(); ++iter) {
411 102 : auto value = *iter;
412 :
413 102 : CAPTURE(counter);
414 102 : REQUIRE_MESSAGE(!visitedVoxels.empty(), "Visiting more voxels than expected");
415 :
416 102 : RealVector_t expected = visitedVoxels.front();
417 102 : RealVector_t point = ray.pointAt(t);
418 :
419 102 : CAPTURE(t);
420 102 : INFO("RealRay_t hit: ", point.format(fmt));
421 102 : INFO("Should hit: ", expected.format(fmt));
422 :
423 102 : CHECK_UNARY(point.isApprox(expected));
424 :
425 : // Pop the first element, as we don't need it anymore
426 102 : visitedVoxels.pop_front();
427 :
428 : // increment counter
429 102 : ++counter;
430 102 : t += tdelta;
431 102 : }
432 :
433 43 : INFO("Voxels left in list: ", visitedVoxels.size());
434 :
435 43 : REQUIRE_MESSAGE(visitedVoxels.empty(), "Voxel list is not empty, so we've visited too few");
436 43 : CHECK_NE(counter, 0);
437 : // CHECK(false);
438 :
439 43 : return counter;
440 43 : }
441 :
442 : TEST_CASE("SliceTraversal: Traversing a 2D grid parallel to x-axis, dir [1, 0]")
443 2 : {
444 :
445 2 : IndexVector_t size({{3, 3}});
446 :
447 2 : BoundingBox aabb(size);
448 :
449 2 : const RealVector_t rd({{1, 0}});
450 2 : const real_t x = -1.5f;
451 :
452 8 : for (real_t i = 0; i < 3; ++i) {
453 6 : const real_t y = 0.5f + i;
454 6 : const RealVector_t ro({{x, y}});
455 6 : const RealRay_t ray(ro, rd);
456 :
457 : // list of points we expect to visit
458 6 : std::deque<RealVector_t> visitedVoxels;
459 6 : visitedVoxels.emplace_back(RealVector_t{{0.5, y}});
460 6 : visitedVoxels.emplace_back(RealVector_t{{1.5, y}});
461 6 : visitedVoxels.emplace_back(RealVector_t{{2.5, y}});
462 :
463 6 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
464 :
465 6 : THEN("Exactly 3 voxels are visited") { CHECK_EQ(counter, 3); }
466 6 : }
467 2 : }
468 :
469 : TEST_CASE("SliceTraversal: Traversing a 2D grid parallel to x-axis, dir [-1, 0]")
470 2 : {
471 2 : IndexVector_t size({{3, 3}});
472 :
473 2 : BoundingBox aabb(size);
474 :
475 2 : const RealVector_t rd({{-1, 0}});
476 2 : const real_t x = 5.5f;
477 :
478 6 : for (real_t i = 1; i < 3; ++i) {
479 4 : const real_t y = 0.5f + i;
480 4 : const RealVector_t ro({{x, y}});
481 4 : const RealRay_t ray(ro, rd);
482 :
483 : // list of points we expect to visit
484 4 : std::deque<RealVector_t> visitedVoxels;
485 4 : visitedVoxels.emplace_back(RealVector_t{{2.5, y}});
486 4 : visitedVoxels.emplace_back(RealVector_t{{1.5, y}});
487 4 : visitedVoxels.emplace_back(RealVector_t{{0.5, y}});
488 :
489 4 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
490 :
491 4 : THEN("Exactly 3 voxels are visited") { CHECK_EQ(counter, 3); }
492 4 : }
493 2 : }
494 :
495 : TEST_CASE("SliceTraversal: Traversing a 2D grid parallel to y-axis, dir [0, 1]")
496 2 : {
497 2 : IndexVector_t size({{3, 3}});
498 :
499 2 : BoundingBox aabb(size);
500 :
501 2 : const RealVector_t rd({{0, 1}});
502 2 : const real_t y = -1.5;
503 :
504 6 : for (real_t i = 1; i < 3; ++i) {
505 4 : const real_t x = 0.5f + i;
506 4 : const RealVector_t ro({{x, y}});
507 4 : const RealRay_t ray(ro, rd);
508 :
509 : // list of points we expect to visit
510 4 : std::deque<RealVector_t> visitedVoxels;
511 4 : visitedVoxels.emplace_back(RealVector_t{{x, 0.5}});
512 4 : visitedVoxels.emplace_back(RealVector_t{{x, 1.5}});
513 4 : visitedVoxels.emplace_back(RealVector_t{{x, 2.5}});
514 :
515 4 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
516 :
517 4 : THEN("Exactly 3 voxels are visited") { CHECK_EQ(counter, 3); }
518 4 : }
519 2 : }
520 :
521 : TEST_CASE("SliceTraversal: Traversing a 2D grid parallel to y-axis, dir [0, -1]")
522 2 : {
523 2 : IndexVector_t size({{3, 3}});
524 :
525 2 : BoundingBox aabb(size);
526 :
527 2 : const RealVector_t rd({{0, -1}});
528 2 : const real_t y = 5.5;
529 :
530 6 : for (real_t i = 1; i < 3; ++i) {
531 4 : const real_t x = 0.5f + i;
532 4 : const RealVector_t ro({{x, y}});
533 4 : const RealRay_t ray(ro, rd);
534 :
535 : // list of points we expect to visit
536 4 : std::deque<RealVector_t> visitedVoxels;
537 4 : visitedVoxels.emplace_back(RealVector_t{{x, 2.5}});
538 4 : visitedVoxels.emplace_back(RealVector_t{{x, 1.5}});
539 4 : visitedVoxels.emplace_back(RealVector_t{{x, 0.5}});
540 :
541 4 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
542 :
543 4 : THEN("Exactly 3 voxels are visited") { CHECK_EQ(counter, 3); }
544 4 : }
545 2 : }
546 :
547 : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [1, 1]")
548 5 : {
549 5 : IndexVector_t size({{3, 3}});
550 :
551 5 : BoundingBox aabb(size);
552 :
553 5 : RealVector_t rd({{1, 1}});
554 5 : rd.normalize();
555 :
556 5 : WHEN("Traversing the grid through the center")
557 5 : {
558 1 : const RealVector_t ro({{-1.5, -1.5}});
559 :
560 1 : const RealRay_t ray(ro, rd);
561 :
562 : // list of points we expect to visit
563 1 : std::deque<RealVector_t> visitedVoxels;
564 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
565 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
566 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
567 :
568 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
569 :
570 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 3); }
571 1 : }
572 :
573 5 : WHEN("Traversing the grid through the left middle and top middle voxel")
574 5 : {
575 1 : const RealVector_t ro({{-0.5, 0.5}});
576 :
577 1 : const RealRay_t ray(ro, rd);
578 :
579 : // list of points we expect to visit
580 1 : std::deque<RealVector_t> visitedVoxels;
581 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
582 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
583 :
584 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
585 :
586 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
587 1 : }
588 :
589 5 : WHEN("Traversing the grid through the right middle and bottom middle voxel")
590 5 : {
591 1 : Eigen::IOFormat fmtvec(10, 0, ", ", ", ", "", "", "[", "]");
592 :
593 1 : const RealVector_t ro({{0.5, -0.5}});
594 :
595 1 : const RealRay_t ray(ro, rd);
596 :
597 : // list of points we expect to visit
598 1 : std::deque<RealVector_t> visitedVoxels;
599 1 : visitedVoxels.push_back(RealVector_t{{1.5, 0.5}});
600 1 : visitedVoxels.push_back(RealVector_t{{2.5, 1.5}});
601 :
602 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
603 :
604 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
605 1 : }
606 :
607 5 : WHEN("Traversing the grid through the bottom right corner")
608 5 : {
609 1 : const RealVector_t ro({{2.5 - 1, 0.5 - 1}});
610 :
611 1 : const RealRay_t ray(ro, rd);
612 :
613 : // list of points we expect to visit
614 1 : std::deque<RealVector_t> visitedVoxels;
615 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
616 :
617 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
618 :
619 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 1); }
620 1 : }
621 :
622 5 : WHEN("Traversing the grid through the top left corner")
623 5 : {
624 1 : const RealVector_t ro({{-0.5, 1.5}});
625 :
626 1 : const RealRay_t ray(ro, rd);
627 :
628 : // list of points we expect to visit
629 1 : std::deque<RealVector_t> visitedVoxels;
630 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 2.5}});
631 :
632 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
633 :
634 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 1); }
635 1 : }
636 5 : }
637 :
638 : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [1, -1]")
639 5 : {
640 5 : IndexVector_t size({{3, 3}});
641 :
642 5 : BoundingBox aabb(size);
643 :
644 5 : RealVector_t rd({{1, -1}});
645 5 : rd.normalize();
646 :
647 5 : WHEN("Traversing the bottom left corner")
648 5 : {
649 1 : const RealVector_t ro({{-0.5, 1.5}});
650 :
651 1 : const RealRay_t ray(ro, rd);
652 :
653 : // list of points we expect to visit
654 1 : std::deque<RealVector_t> visitedVoxels;
655 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
656 :
657 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
658 :
659 1 : THEN("Exactly one step is taken") { CHECK_EQ(counter, 1); }
660 1 : }
661 :
662 5 : WHEN("Traversing the grid through the left middle and top middle voxel")
663 5 : {
664 1 : const RealVector_t ro({{-0.5, 2.5}});
665 :
666 1 : const RealRay_t ray(ro, rd);
667 :
668 : // list of points we expect to visit
669 1 : std::deque<RealVector_t> visitedVoxels;
670 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
671 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 0.5}});
672 :
673 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
674 :
675 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
676 1 : }
677 :
678 5 : WHEN("Traversing the grid through the center diagonally")
679 5 : {
680 1 : const RealVector_t ro({{-0.5, 3.5}});
681 :
682 1 : const RealRay_t ray(ro, rd);
683 :
684 : // list of points we expect to visit
685 1 : std::deque<RealVector_t> visitedVoxels;
686 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 2.5}});
687 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
688 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
689 :
690 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
691 :
692 1 : THEN("Exactly three steps are taken") { CHECK_EQ(counter, 3); }
693 1 : }
694 :
695 5 : WHEN("Traversing the grid through the top middle and right middle voxel")
696 5 : {
697 1 : const RealVector_t ro({{0.5, 3.5}});
698 :
699 1 : const RealRay_t ray(ro, rd);
700 :
701 : // list of points we expect to visit
702 1 : std::deque<RealVector_t> visitedVoxels;
703 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
704 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 1.5}});
705 :
706 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
707 :
708 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
709 1 : }
710 :
711 5 : WHEN("Traversing the grid through the top right voxel")
712 5 : {
713 1 : const RealVector_t ro({{1.5, 3.5}});
714 :
715 1 : const RealRay_t ray(ro, rd);
716 :
717 : // list of points we expect to visit
718 1 : std::deque<RealVector_t> visitedVoxels;
719 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
720 :
721 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
722 :
723 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 1); }
724 1 : }
725 5 : }
726 :
727 : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [-1, 1]")
728 5 : {
729 5 : IndexVector_t size({{3, 3}});
730 :
731 5 : BoundingBox aabb(size);
732 :
733 5 : RealVector_t rd({{-1, 1}});
734 5 : rd.normalize();
735 :
736 5 : WHEN("Traversing the top right corner")
737 5 : {
738 1 : const RealVector_t ro({{3.5, 1.5}});
739 :
740 1 : const RealRay_t ray(ro, rd);
741 :
742 : // list of points we expect to visit
743 1 : std::deque<RealVector_t> visitedVoxels;
744 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
745 :
746 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
747 :
748 1 : THEN("Exactly one step is taken") { CHECK_EQ(counter, 1); }
749 1 : }
750 :
751 5 : WHEN("Traversing the grid through the top center and right center voxel")
752 5 : {
753 1 : const RealVector_t ro({{3.5, 0.5}});
754 :
755 1 : const RealRay_t ray(ro, rd);
756 :
757 : // list of points we expect to visit
758 1 : std::deque<RealVector_t> visitedVoxels;
759 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 1.5}});
760 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
761 :
762 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
763 :
764 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
765 1 : }
766 :
767 5 : WHEN("Traversing the grid through the center diagonally")
768 5 : {
769 1 : const RealVector_t ro({{3.5, -0.5}});
770 :
771 1 : const RealRay_t ray(ro, rd);
772 :
773 : // list of points we expect to visit
774 1 : std::deque<RealVector_t> visitedVoxels;
775 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
776 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
777 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 2.5}});
778 :
779 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
780 :
781 1 : THEN("Exactly three steps are taken") { CHECK_EQ(counter, 3); }
782 1 : }
783 :
784 5 : WHEN("Traversing the grid through the left center and bottom center voxel")
785 5 : {
786 1 : const RealVector_t ro({{2.5, -0.5}});
787 :
788 1 : const RealRay_t ray(ro, rd);
789 :
790 : // list of points we expect to visit
791 1 : std::deque<RealVector_t> visitedVoxels;
792 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 0.5}});
793 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
794 :
795 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
796 :
797 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
798 1 : }
799 :
800 5 : WHEN("Traversing the grid through the bottom left voxel")
801 5 : {
802 1 : const RealVector_t ro({{1.5, -0.5}});
803 :
804 1 : const RealRay_t ray(ro, rd);
805 :
806 : // list of points we expect to visit
807 1 : std::deque<RealVector_t> visitedVoxels;
808 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
809 :
810 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
811 :
812 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 1); }
813 1 : }
814 5 : }
815 :
816 : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [-1, -1]")
817 9 : {
818 9 : IndexVector_t size({{3, 3}});
819 :
820 9 : BoundingBox aabb(size);
821 :
822 9 : RealVector_t rd({{-1, -1}});
823 9 : rd.normalize();
824 :
825 9 : CAPTURE(aabb);
826 :
827 9 : WHEN("Traversing the grid through the center of the top left corner")
828 9 : {
829 1 : const RealVector_t ro({{1.5, 3.5}});
830 :
831 1 : const RealRay_t ray(ro, rd);
832 :
833 : // list of points we expect to visit
834 1 : std::deque<RealVector_t> visitedVoxels;
835 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 2.5}});
836 :
837 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
838 :
839 1 : THEN("Exactly one step is taken") { CHECK_EQ(counter, 1); }
840 1 : }
841 :
842 9 : WHEN("Traversing the grid through the top left voxel, but not centered")
843 9 : {
844 1 : const RealVector_t ro({{1.75, 3.5}});
845 :
846 1 : const RealRay_t ray(ro, rd);
847 :
848 : // list of points we expect to visit
849 1 : std::deque<RealVector_t> visitedVoxels;
850 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 2.25}});
851 :
852 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
853 :
854 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 1); }
855 1 : }
856 :
857 9 : WHEN("Traversing the grid through the left and top center voxel")
858 9 : {
859 1 : const RealVector_t ro({{2.5, 3.5}});
860 :
861 1 : const RealRay_t ray(ro, rd);
862 :
863 : // list of points we expect to visit
864 1 : std::deque<RealVector_t> visitedVoxels;
865 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
866 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
867 :
868 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
869 :
870 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
871 1 : }
872 :
873 9 : WHEN("Traversing the grid through the left and top center voxel but not centered")
874 9 : {
875 1 : const RealVector_t ro({{2, 3.5}});
876 :
877 1 : const RealRay_t ray(ro, rd);
878 :
879 : // list of points we expect to visit
880 1 : std::deque<RealVector_t> visitedVoxels;
881 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 3}});
882 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 2}});
883 :
884 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
885 :
886 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
887 1 : }
888 :
889 9 : WHEN("Traversing the grid slightly above the volume center diagonally")
890 9 : {
891 1 : const RealVector_t ro({{3.25, 3.5}});
892 :
893 1 : const RealRay_t ray(ro, rd);
894 :
895 : // list of points we expect to visit
896 1 : std::deque<RealVector_t> visitedVoxels;
897 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 2.75}});
898 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 1.75}});
899 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 0.75}});
900 :
901 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
902 :
903 1 : THEN("Exactly three steps are taken") { CHECK_EQ(counter, 3); }
904 1 : }
905 :
906 9 : WHEN("Traversing the grid through the volume center diagonally")
907 9 : {
908 1 : const RealVector_t ro({{3.5, 3.5}});
909 :
910 1 : const RealRay_t ray(ro, rd);
911 :
912 : // list of points we expect to visit
913 1 : std::deque<RealVector_t> visitedVoxels;
914 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
915 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
916 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
917 :
918 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
919 :
920 1 : THEN("Exactly three steps are taken") { CHECK_EQ(counter, 3); }
921 1 : }
922 :
923 9 : WHEN("Traversing the grid slightly below the volume center diagonally")
924 9 : {
925 1 : const RealVector_t ro({{3.75, 3.5}});
926 :
927 1 : const RealRay_t ray(ro, rd);
928 :
929 : // list of points we expect to visit
930 1 : std::deque<RealVector_t> visitedVoxels;
931 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 2.25}});
932 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 1.25}});
933 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 0.25}});
934 :
935 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
936 :
937 1 : THEN("Exactly three steps are taken") { CHECK_EQ(counter, 3); }
938 1 : }
939 :
940 9 : WHEN("Traversing the grid through the bottom and right center voxel")
941 9 : {
942 1 : const RealVector_t ro({{3.5, 2.5}});
943 :
944 1 : const RealRay_t ray(ro, rd);
945 :
946 : // list of points we expect to visit
947 1 : std::deque<RealVector_t> visitedVoxels;
948 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 1.5}});
949 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 0.5}});
950 :
951 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
952 :
953 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 2); }
954 1 : }
955 :
956 9 : WHEN("Traversing the grid through the bottom left corner")
957 9 : {
958 1 : const RealVector_t ro({{3.5, 1.5}});
959 :
960 1 : const RealRay_t ray(ro, rd);
961 :
962 : // list of points we expect to visit
963 1 : std::deque<RealVector_t> visitedVoxels;
964 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
965 :
966 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
967 :
968 1 : THEN("Exactly two steps are taken") { CHECK_EQ(counter, 1); }
969 1 : }
970 9 : }
971 :
972 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 0, 0]")
973 4 : {
974 4 : auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
975 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
976 :
977 4 : const RealVector_t ro({{-2.5, 1.5, 1.5}});
978 4 : INFO("ro := ", ro.format(vecfmt));
979 :
980 4 : const RealVector_t rd({{1, 0, 0}});
981 4 : INFO("rd := ", rd.format(vecfmt));
982 :
983 4 : const RealRay_t ray(ro, rd);
984 :
985 4 : checkTransformationBasic(ray, centerOfRotation, expectedRotation);
986 4 : }
987 :
988 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 1, 0]")
989 4 : {
990 4 : auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
991 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
992 :
993 4 : const RealVector_t ro({{-2.5, -2.5, 1.5}});
994 4 : INFO("ro := ", ro.format(vecfmt));
995 :
996 4 : const RealVector_t rd({{1, 1, 0}});
997 4 : INFO("rd := ", rd.format(vecfmt));
998 :
999 4 : const RealRay_t ray(ro, rd);
1000 :
1001 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, 0}}), rd, expectedRotation);
1002 4 : }
1003 :
1004 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, -1, 0]")
1005 4 : {
1006 4 : auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
1007 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1008 :
1009 4 : const RealVector_t ro({{-2.5, 5.5, 1.5}});
1010 4 : INFO("ro := ", ro.format(vecfmt));
1011 :
1012 4 : const RealVector_t rd({{1, -1, 0}});
1013 4 : INFO("rd := ", rd.format(vecfmt));
1014 :
1015 4 : const RealRay_t ray(ro, rd);
1016 :
1017 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 4, 0}}), rd, expectedRotation);
1018 4 : }
1019 :
1020 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 0, 1]")
1021 4 : {
1022 4 : auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
1023 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1024 :
1025 4 : const RealVector_t ro({{-2.5, 1.5, -2.5}});
1026 4 : INFO("ro := ", ro.format(vecfmt));
1027 :
1028 4 : const RealVector_t rd({{1, 0, 1}});
1029 4 : INFO("rd := ", rd.format(vecfmt));
1030 :
1031 4 : const RealRay_t ray(ro, rd);
1032 :
1033 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, -4}}), rd, expectedRotation);
1034 4 : }
1035 :
1036 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 0, -1]")
1037 4 : {
1038 4 : auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
1039 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1040 :
1041 4 : const RealVector_t ro({{-2.5, 1.5, 5.5}});
1042 4 : INFO("ro := ", ro.format(vecfmt));
1043 :
1044 4 : const RealVector_t rd({{1, 0, -1}});
1045 4 : INFO("rd := ", rd.format(vecfmt));
1046 :
1047 4 : const RealRay_t ray(ro, rd);
1048 :
1049 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, 4}}), rd, expectedRotation);
1050 4 : }
1051 :
1052 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 1, 1]")
1053 4 : {
1054 4 : auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
1055 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1056 :
1057 4 : const RealVector_t ro({{-2.5, -2.5, -2.5}});
1058 4 : INFO("ro := ", ro.format(vecfmt));
1059 :
1060 4 : const RealVector_t rd({{1, 1, 1}});
1061 4 : INFO("rd := ", rd.format(vecfmt));
1062 :
1063 4 : const RealRay_t ray(ro, rd);
1064 :
1065 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, -4}}), rd, expectedRotation);
1066 4 : }
1067 :
1068 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 1, -1]")
1069 4 : {
1070 4 : auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
1071 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1072 :
1073 4 : const RealVector_t ro({{-2.5, -2.5, 5.5}});
1074 4 : INFO("ro := ", ro.format(vecfmt));
1075 :
1076 4 : const RealVector_t rd({{1, 1, -1}});
1077 4 : INFO("rd := ", rd.format(vecfmt));
1078 :
1079 4 : const RealRay_t ray(ro, rd);
1080 :
1081 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, 4}}), rd, expectedRotation);
1082 4 : }
1083 :
1084 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, 0, 0]")
1085 4 : {
1086 4 : auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
1087 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1088 :
1089 4 : const RealVector_t ro({{5.5, 1.5, 1.5}});
1090 4 : INFO("ro := ", ro.format(vecfmt));
1091 :
1092 4 : const RealVector_t rd({{-1, 0, 0}});
1093 4 : INFO("rd := ", rd.format(vecfmt));
1094 :
1095 4 : const RealRay_t ray(ro, rd);
1096 :
1097 4 : checkTransformationBasic(ray, centerOfRotation, expectedRotation);
1098 4 : }
1099 :
1100 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, 1, 0]")
1101 4 : {
1102 4 : auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
1103 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1104 :
1105 4 : const RealVector_t ro({{5.5, -2.5, 1.5}});
1106 4 : INFO("ro := ", ro.format(vecfmt));
1107 :
1108 4 : const RealVector_t rd({{-1, 1, 0}});
1109 4 : INFO("rd := ", rd.format(vecfmt));
1110 :
1111 4 : const RealRay_t ray(ro, rd);
1112 :
1113 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, 0}}),
1114 4 : RealVector_t({{1, 1, 0}}), expectedRotation);
1115 4 : }
1116 :
1117 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, -1, 0]")
1118 4 : {
1119 4 : auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
1120 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1121 :
1122 4 : const RealVector_t ro({{5.5, 5.5, 1.5}});
1123 4 : INFO("ro := ", ro.format(vecfmt));
1124 :
1125 4 : const RealVector_t rd({{-1, -1, 0}});
1126 4 : INFO("rd := ", rd.format(vecfmt));
1127 :
1128 4 : const RealRay_t ray(ro, rd);
1129 :
1130 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 4, 0}}),
1131 4 : RealVector_t({{1, -1, 0}}), expectedRotation);
1132 4 : }
1133 :
1134 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, 0, 1]")
1135 4 : {
1136 4 : auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
1137 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1138 :
1139 4 : const RealVector_t ro({{5.5, 1.5, -2.5}});
1140 4 : INFO("ro := ", ro.format(vecfmt));
1141 :
1142 4 : const RealVector_t rd({{-1, 0, 1}});
1143 4 : INFO("rd := ", rd.format(vecfmt));
1144 :
1145 4 : const RealRay_t ray(ro, rd);
1146 :
1147 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, 4}}),
1148 4 : RealVector_t({{1, 0, -1}}), expectedRotation);
1149 4 : }
1150 :
1151 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, 0, -1]")
1152 4 : {
1153 4 : auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
1154 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1155 :
1156 4 : const RealVector_t ro({{5.5, 1.5, 5.5}});
1157 4 : INFO("ro := ", ro.format(vecfmt));
1158 :
1159 4 : const RealVector_t rd({{-1, 0, -1}});
1160 4 : INFO("rd := ", rd.format(vecfmt));
1161 :
1162 4 : const RealRay_t ray(ro, rd);
1163 :
1164 4 : checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, -4}}),
1165 4 : RealVector_t({{1, 0, 1}}), expectedRotation);
1166 4 : }
1167 :
1168 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, 1, 0]")
1169 4 : {
1170 4 : auto expectedRotation = Eigen::AngleAxisf(-0.5 * pi_t, Eigen::Vector3f::UnitZ()).matrix();
1171 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1172 :
1173 4 : const RealVector_t ro({{1.5, -2.5, 1.5}});
1174 4 : INFO("ro := ", ro.format(vecfmt));
1175 :
1176 4 : const RealVector_t rd({{0, 1, 0}});
1177 4 : INFO("rd := ", rd.format(vecfmt));
1178 :
1179 4 : const RealRay_t ray(ro, rd);
1180 :
1181 4 : checkTransformationBasic(ray, centerOfRotation, expectedRotation);
1182 4 : }
1183 :
1184 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, -1, 0]")
1185 4 : {
1186 4 : auto expectedRotation = Eigen::AngleAxisf(0.5 * pi_t, Eigen::Vector3f::UnitZ()).matrix();
1187 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1188 :
1189 4 : const RealVector_t ro({{1.5, 5.5, 1.5}});
1190 4 : INFO("ro := ", ro.format(vecfmt));
1191 :
1192 4 : const RealVector_t rd({{0, -1, 0}});
1193 4 : INFO("rd := ", rd.format(vecfmt));
1194 :
1195 4 : const RealRay_t ray(ro, rd);
1196 :
1197 4 : checkTransformationBasic(ray, centerOfRotation, expectedRotation);
1198 4 : }
1199 :
1200 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, 0, 1]")
1201 4 : {
1202 4 : auto expectedRotation = Eigen::AngleAxisf(0.5 * pi_t, Eigen::Vector3f::UnitY()).matrix();
1203 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1204 :
1205 4 : const RealVector_t ro({{1.5, 1.5, -2.5}});
1206 4 : INFO("ro := ", ro.format(vecfmt));
1207 :
1208 4 : const RealVector_t rd({{0, 0, 1}});
1209 4 : INFO("rd := ", rd.format(vecfmt));
1210 :
1211 4 : const RealRay_t ray(ro, rd);
1212 :
1213 4 : checkTransformationBasic(ray, centerOfRotation, expectedRotation);
1214 4 : }
1215 :
1216 : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, 0, -1]")
1217 4 : {
1218 4 : auto expectedRotation = Eigen::AngleAxisf(-0.5 * pi_t, Eigen::Vector3f::UnitY()).matrix();
1219 4 : const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
1220 :
1221 4 : const RealVector_t ro({{1.5, 1.5, 5.5}});
1222 4 : INFO("ro := ", ro.format(vecfmt));
1223 :
1224 4 : const RealVector_t rd({{0, 0, -1}});
1225 4 : INFO("rd := ", rd.format(vecfmt));
1226 :
1227 4 : const RealRay_t ray(ro, rd);
1228 :
1229 4 : checkTransformationBasic(ray, centerOfRotation, expectedRotation);
1230 4 : }
1231 :
1232 : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [1, 0, 0]")
1233 1 : {
1234 1 : IndexVector_t size({{3, 3, 3}});
1235 :
1236 1 : BoundingBox aabb(size);
1237 :
1238 1 : RealVector_t rd({{1, 0, 0}});
1239 1 : rd.normalize();
1240 :
1241 1 : CAPTURE(aabb);
1242 :
1243 1 : WHEN("Traversing the grid through the center of the top left corner")
1244 1 : {
1245 1 : const RealVector_t ro({{-1.5, 0, 0}});
1246 :
1247 1 : const RealRay_t ray(ro, rd);
1248 :
1249 : // list of points we expect to visit
1250 1 : std::deque<RealVector_t> visitedVoxels;
1251 1 : visitedVoxels.emplace_back(RealVector_t{{0.5, 0, 0}});
1252 1 : visitedVoxels.emplace_back(RealVector_t{{1.5, 0, 0}});
1253 1 : visitedVoxels.emplace_back(RealVector_t{{2.5, 0, 0}});
1254 :
1255 1 : auto counter = checkTraversal(aabb, ray, visitedVoxels);
1256 :
1257 1 : THEN("Exactly one step is taken") { CHECK_EQ(counter, 3); }
1258 1 : }
1259 1 : }
|