LCOV - code coverage report
Current view: top level - elsa/projectors/tests - test_SliceTraversal.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 891 891 100.0 %
Date: 2023-01-26 04:22:16 Functions: 39 39 100.0 %

          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")
     466           6 :         {
     467           1 :             CHECK_EQ(counter, 3);
     468           1 :         }
     469           6 :     }
     470           2 : }
     471             : 
     472             : TEST_CASE("SliceTraversal: Traversing a 2D grid parallel to x-axis, dir [-1, 0]")
     473           2 : {
     474           2 :     IndexVector_t size({{3, 3}});
     475             : 
     476           2 :     BoundingBox aabb(size);
     477             : 
     478           2 :     const RealVector_t rd({{-1, 0}});
     479           2 :     const real_t x = 5.5f;
     480             : 
     481           6 :     for (real_t i = 1; i < 3; ++i) {
     482           4 :         const real_t y = 0.5f + i;
     483           4 :         const RealVector_t ro({{x, y}});
     484           4 :         const RealRay_t ray(ro, rd);
     485             : 
     486             :         // list of points we expect to visit
     487           4 :         std::deque<RealVector_t> visitedVoxels;
     488           4 :         visitedVoxels.emplace_back(RealVector_t{{2.5, y}});
     489           4 :         visitedVoxels.emplace_back(RealVector_t{{1.5, y}});
     490           4 :         visitedVoxels.emplace_back(RealVector_t{{0.5, y}});
     491             : 
     492           4 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     493             : 
     494           4 :         THEN("Exactly 3 voxels are visited")
     495           4 :         {
     496           1 :             CHECK_EQ(counter, 3);
     497           1 :         }
     498           4 :     }
     499           2 : }
     500             : 
     501             : TEST_CASE("SliceTraversal: Traversing a 2D grid parallel to y-axis, dir [0, 1]")
     502           2 : {
     503           2 :     IndexVector_t size({{3, 3}});
     504             : 
     505           2 :     BoundingBox aabb(size);
     506             : 
     507           2 :     const RealVector_t rd({{0, 1}});
     508           2 :     const real_t y = -1.5;
     509             : 
     510           6 :     for (real_t i = 1; i < 3; ++i) {
     511           4 :         const real_t x = 0.5f + i;
     512           4 :         const RealVector_t ro({{x, y}});
     513           4 :         const RealRay_t ray(ro, rd);
     514             : 
     515             :         // list of points we expect to visit
     516           4 :         std::deque<RealVector_t> visitedVoxels;
     517           4 :         visitedVoxels.emplace_back(RealVector_t{{x, 0.5}});
     518           4 :         visitedVoxels.emplace_back(RealVector_t{{x, 1.5}});
     519           4 :         visitedVoxels.emplace_back(RealVector_t{{x, 2.5}});
     520             : 
     521           4 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     522             : 
     523           4 :         THEN("Exactly 3 voxels are visited")
     524           4 :         {
     525           1 :             CHECK_EQ(counter, 3);
     526           1 :         }
     527           4 :     }
     528           2 : }
     529             : 
     530             : TEST_CASE("SliceTraversal: Traversing a 2D grid parallel to y-axis, dir [0, -1]")
     531           2 : {
     532           2 :     IndexVector_t size({{3, 3}});
     533             : 
     534           2 :     BoundingBox aabb(size);
     535             : 
     536           2 :     const RealVector_t rd({{0, -1}});
     537           2 :     const real_t y = 5.5;
     538             : 
     539           6 :     for (real_t i = 1; i < 3; ++i) {
     540           4 :         const real_t x = 0.5f + i;
     541           4 :         const RealVector_t ro({{x, y}});
     542           4 :         const RealRay_t ray(ro, rd);
     543             : 
     544             :         // list of points we expect to visit
     545           4 :         std::deque<RealVector_t> visitedVoxels;
     546           4 :         visitedVoxels.emplace_back(RealVector_t{{x, 2.5}});
     547           4 :         visitedVoxels.emplace_back(RealVector_t{{x, 1.5}});
     548           4 :         visitedVoxels.emplace_back(RealVector_t{{x, 0.5}});
     549             : 
     550           4 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     551             : 
     552           4 :         THEN("Exactly 3 voxels are visited")
     553           4 :         {
     554           1 :             CHECK_EQ(counter, 3);
     555           1 :         }
     556           4 :     }
     557           2 : }
     558             : 
     559             : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [1, 1]")
     560           5 : {
     561           5 :     IndexVector_t size({{3, 3}});
     562             : 
     563           5 :     BoundingBox aabb(size);
     564             : 
     565           5 :     RealVector_t rd({{1, 1}});
     566           5 :     rd.normalize();
     567             : 
     568           5 :     WHEN("Traversing the grid through the center")
     569           5 :     {
     570           1 :         const RealVector_t ro({{-1.5, -1.5}});
     571             : 
     572           1 :         const RealRay_t ray(ro, rd);
     573             : 
     574             :         // list of points we expect to visit
     575           1 :         std::deque<RealVector_t> visitedVoxels;
     576           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
     577           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
     578           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
     579             : 
     580           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     581             : 
     582           1 :         THEN("Exactly two steps are taken")
     583           1 :         {
     584           1 :             CHECK_EQ(counter, 3);
     585           1 :         }
     586           1 :     }
     587             : 
     588           5 :     WHEN("Traversing the grid through the left middle and top middle voxel")
     589           5 :     {
     590           1 :         const RealVector_t ro({{-0.5, 0.5}});
     591             : 
     592           1 :         const RealRay_t ray(ro, rd);
     593             : 
     594             :         // list of points we expect to visit
     595           1 :         std::deque<RealVector_t> visitedVoxels;
     596           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
     597           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
     598             : 
     599           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     600             : 
     601           1 :         THEN("Exactly two steps are taken")
     602           1 :         {
     603           1 :             CHECK_EQ(counter, 2);
     604           1 :         }
     605           1 :     }
     606             : 
     607           5 :     WHEN("Traversing the grid through the right middle and bottom middle voxel")
     608           5 :     {
     609           1 :         Eigen::IOFormat fmtvec(10, 0, ", ", ", ", "", "", "[", "]");
     610             : 
     611           1 :         const RealVector_t ro({{0.5, -0.5}});
     612             : 
     613           1 :         const RealRay_t ray(ro, rd);
     614             : 
     615             :         // list of points we expect to visit
     616           1 :         std::deque<RealVector_t> visitedVoxels;
     617           1 :         visitedVoxels.push_back(RealVector_t{{1.5, 0.5}});
     618           1 :         visitedVoxels.push_back(RealVector_t{{2.5, 1.5}});
     619             : 
     620           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     621             : 
     622           1 :         THEN("Exactly two steps are taken")
     623           1 :         {
     624           1 :             CHECK_EQ(counter, 2);
     625           1 :         }
     626           1 :     }
     627             : 
     628           5 :     WHEN("Traversing the grid through the bottom right corner")
     629           5 :     {
     630           1 :         const RealVector_t ro({{2.5 - 1, 0.5 - 1}});
     631             : 
     632           1 :         const RealRay_t ray(ro, rd);
     633             : 
     634             :         // list of points we expect to visit
     635           1 :         std::deque<RealVector_t> visitedVoxels;
     636           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
     637             : 
     638           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     639             : 
     640           1 :         THEN("Exactly two steps are taken")
     641           1 :         {
     642           1 :             CHECK_EQ(counter, 1);
     643           1 :         }
     644           1 :     }
     645             : 
     646           5 :     WHEN("Traversing the grid through the top left corner")
     647           5 :     {
     648           1 :         const RealVector_t ro({{-0.5, 1.5}});
     649             : 
     650           1 :         const RealRay_t ray(ro, rd);
     651             : 
     652             :         // list of points we expect to visit
     653           1 :         std::deque<RealVector_t> visitedVoxels;
     654           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 2.5}});
     655             : 
     656           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     657             : 
     658           1 :         THEN("Exactly two steps are taken")
     659           1 :         {
     660           1 :             CHECK_EQ(counter, 1);
     661           1 :         }
     662           1 :     }
     663           5 : }
     664             : 
     665             : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [1, -1]")
     666           5 : {
     667           5 :     IndexVector_t size({{3, 3}});
     668             : 
     669           5 :     BoundingBox aabb(size);
     670             : 
     671           5 :     RealVector_t rd({{1, -1}});
     672           5 :     rd.normalize();
     673             : 
     674           5 :     WHEN("Traversing the bottom left corner")
     675           5 :     {
     676           1 :         const RealVector_t ro({{-0.5, 1.5}});
     677             : 
     678           1 :         const RealRay_t ray(ro, rd);
     679             : 
     680             :         // list of points we expect to visit
     681           1 :         std::deque<RealVector_t> visitedVoxels;
     682           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
     683             : 
     684           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     685             : 
     686           1 :         THEN("Exactly one step is taken")
     687           1 :         {
     688           1 :             CHECK_EQ(counter, 1);
     689           1 :         }
     690           1 :     }
     691             : 
     692           5 :     WHEN("Traversing the grid through the left middle and top middle voxel")
     693           5 :     {
     694           1 :         const RealVector_t ro({{-0.5, 2.5}});
     695             : 
     696           1 :         const RealRay_t ray(ro, rd);
     697             : 
     698             :         // list of points we expect to visit
     699           1 :         std::deque<RealVector_t> visitedVoxels;
     700           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
     701           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 0.5}});
     702             : 
     703           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     704             : 
     705           1 :         THEN("Exactly two steps are taken")
     706           1 :         {
     707           1 :             CHECK_EQ(counter, 2);
     708           1 :         }
     709           1 :     }
     710             : 
     711           5 :     WHEN("Traversing the grid through the center diagonally")
     712           5 :     {
     713           1 :         const RealVector_t ro({{-0.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{{0.5, 2.5}});
     720           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
     721           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
     722             : 
     723           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     724             : 
     725           1 :         THEN("Exactly three steps are taken")
     726           1 :         {
     727           1 :             CHECK_EQ(counter, 3);
     728           1 :         }
     729           1 :     }
     730             : 
     731           5 :     WHEN("Traversing the grid through the top middle and right middle voxel")
     732           5 :     {
     733           1 :         const RealVector_t ro({{0.5, 3.5}});
     734             : 
     735           1 :         const RealRay_t ray(ro, rd);
     736             : 
     737             :         // list of points we expect to visit
     738           1 :         std::deque<RealVector_t> visitedVoxels;
     739           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
     740           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 1.5}});
     741             : 
     742           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     743             : 
     744           1 :         THEN("Exactly two steps are taken")
     745           1 :         {
     746           1 :             CHECK_EQ(counter, 2);
     747           1 :         }
     748           1 :     }
     749             : 
     750           5 :     WHEN("Traversing the grid through the top right voxel")
     751           5 :     {
     752           1 :         const RealVector_t ro({{1.5, 3.5}});
     753             : 
     754           1 :         const RealRay_t ray(ro, rd);
     755             : 
     756             :         // list of points we expect to visit
     757           1 :         std::deque<RealVector_t> visitedVoxels;
     758           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
     759             : 
     760           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     761             : 
     762           1 :         THEN("Exactly two steps are taken")
     763           1 :         {
     764           1 :             CHECK_EQ(counter, 1);
     765           1 :         }
     766           1 :     }
     767           5 : }
     768             : 
     769             : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [-1, 1]")
     770           5 : {
     771           5 :     IndexVector_t size({{3, 3}});
     772             : 
     773           5 :     BoundingBox aabb(size);
     774             : 
     775           5 :     RealVector_t rd({{-1, 1}});
     776           5 :     rd.normalize();
     777             : 
     778           5 :     WHEN("Traversing the top right corner")
     779           5 :     {
     780           1 :         const RealVector_t ro({{3.5, 1.5}});
     781             : 
     782           1 :         const RealRay_t ray(ro, rd);
     783             : 
     784             :         // list of points we expect to visit
     785           1 :         std::deque<RealVector_t> visitedVoxels;
     786           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
     787             : 
     788           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     789             : 
     790           1 :         THEN("Exactly one step is taken")
     791           1 :         {
     792           1 :             CHECK_EQ(counter, 1);
     793           1 :         }
     794           1 :     }
     795             : 
     796           5 :     WHEN("Traversing the grid through the top center and right center voxel")
     797           5 :     {
     798           1 :         const RealVector_t ro({{3.5, 0.5}});
     799             : 
     800           1 :         const RealRay_t ray(ro, rd);
     801             : 
     802             :         // list of points we expect to visit
     803           1 :         std::deque<RealVector_t> visitedVoxels;
     804           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 1.5}});
     805           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
     806             : 
     807           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     808             : 
     809           1 :         THEN("Exactly two steps are taken")
     810           1 :         {
     811           1 :             CHECK_EQ(counter, 2);
     812           1 :         }
     813           1 :     }
     814             : 
     815           5 :     WHEN("Traversing the grid through the center diagonally")
     816           5 :     {
     817           1 :         const RealVector_t ro({{3.5, -0.5}});
     818             : 
     819           1 :         const RealRay_t ray(ro, rd);
     820             : 
     821             :         // list of points we expect to visit
     822           1 :         std::deque<RealVector_t> visitedVoxels;
     823           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
     824           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
     825           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 2.5}});
     826             : 
     827           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     828             : 
     829           1 :         THEN("Exactly three steps are taken")
     830           1 :         {
     831           1 :             CHECK_EQ(counter, 3);
     832           1 :         }
     833           1 :     }
     834             : 
     835           5 :     WHEN("Traversing the grid through the left center and bottom center voxel")
     836           5 :     {
     837           1 :         const RealVector_t ro({{2.5, -0.5}});
     838             : 
     839           1 :         const RealRay_t ray(ro, rd);
     840             : 
     841             :         // list of points we expect to visit
     842           1 :         std::deque<RealVector_t> visitedVoxels;
     843           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 0.5}});
     844           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
     845             : 
     846           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     847             : 
     848           1 :         THEN("Exactly two steps are taken")
     849           1 :         {
     850           1 :             CHECK_EQ(counter, 2);
     851           1 :         }
     852           1 :     }
     853             : 
     854           5 :     WHEN("Traversing the grid through the bottom left voxel")
     855           5 :     {
     856           1 :         const RealVector_t ro({{1.5, -0.5}});
     857             : 
     858           1 :         const RealRay_t ray(ro, rd);
     859             : 
     860             :         // list of points we expect to visit
     861           1 :         std::deque<RealVector_t> visitedVoxels;
     862           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
     863             : 
     864           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     865             : 
     866           1 :         THEN("Exactly two steps are taken")
     867           1 :         {
     868           1 :             CHECK_EQ(counter, 1);
     869           1 :         }
     870           1 :     }
     871           5 : }
     872             : 
     873             : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [-1, -1]")
     874           9 : {
     875           9 :     IndexVector_t size({{3, 3}});
     876             : 
     877           9 :     BoundingBox aabb(size);
     878             : 
     879           9 :     RealVector_t rd({{-1, -1}});
     880           9 :     rd.normalize();
     881             : 
     882           9 :     CAPTURE(aabb);
     883             : 
     884           9 :     WHEN("Traversing the grid through the center of the top left corner")
     885           9 :     {
     886           1 :         const RealVector_t ro({{1.5, 3.5}});
     887             : 
     888           1 :         const RealRay_t ray(ro, rd);
     889             : 
     890             :         // list of points we expect to visit
     891           1 :         std::deque<RealVector_t> visitedVoxels;
     892           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 2.5}});
     893             : 
     894           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     895             : 
     896           1 :         THEN("Exactly one step is taken")
     897           1 :         {
     898           1 :             CHECK_EQ(counter, 1);
     899           1 :         }
     900           1 :     }
     901             : 
     902           9 :     WHEN("Traversing the grid through the top left voxel, but not centered")
     903           9 :     {
     904           1 :         const RealVector_t ro({{1.75, 3.5}});
     905             : 
     906           1 :         const RealRay_t ray(ro, rd);
     907             : 
     908             :         // list of points we expect to visit
     909           1 :         std::deque<RealVector_t> visitedVoxels;
     910           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 2.25}});
     911             : 
     912           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     913             : 
     914           1 :         THEN("Exactly two steps are taken")
     915           1 :         {
     916           1 :             CHECK_EQ(counter, 1);
     917           1 :         }
     918           1 :     }
     919             : 
     920           9 :     WHEN("Traversing the grid through the left and top center voxel")
     921           9 :     {
     922           1 :         const RealVector_t ro({{2.5, 3.5}});
     923             : 
     924           1 :         const RealRay_t ray(ro, rd);
     925             : 
     926             :         // list of points we expect to visit
     927           1 :         std::deque<RealVector_t> visitedVoxels;
     928           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 2.5}});
     929           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 1.5}});
     930             : 
     931           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     932             : 
     933           1 :         THEN("Exactly two steps are taken")
     934           1 :         {
     935           1 :             CHECK_EQ(counter, 2);
     936           1 :         }
     937           1 :     }
     938             : 
     939           9 :     WHEN("Traversing the grid through the left and top center voxel but not centered")
     940           9 :     {
     941           1 :         const RealVector_t ro({{2, 3.5}});
     942             : 
     943           1 :         const RealRay_t ray(ro, rd);
     944             : 
     945             :         // list of points we expect to visit
     946           1 :         std::deque<RealVector_t> visitedVoxels;
     947           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 3}});
     948           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 2}});
     949             : 
     950           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     951             : 
     952           1 :         THEN("Exactly two steps are taken")
     953           1 :         {
     954           1 :             CHECK_EQ(counter, 2);
     955           1 :         }
     956           1 :     }
     957             : 
     958           9 :     WHEN("Traversing the grid slightly above the volume center diagonally")
     959           9 :     {
     960           1 :         const RealVector_t ro({{3.25, 3.5}});
     961             : 
     962           1 :         const RealRay_t ray(ro, rd);
     963             : 
     964             :         // list of points we expect to visit
     965           1 :         std::deque<RealVector_t> visitedVoxels;
     966           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 2.75}});
     967           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 1.75}});
     968           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 0.75}});
     969             : 
     970           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     971             : 
     972           1 :         THEN("Exactly three steps are taken")
     973           1 :         {
     974           1 :             CHECK_EQ(counter, 3);
     975           1 :         }
     976           1 :     }
     977             : 
     978           9 :     WHEN("Traversing the grid through the volume center diagonally")
     979           9 :     {
     980           1 :         const RealVector_t ro({{3.5, 3.5}});
     981             : 
     982           1 :         const RealRay_t ray(ro, rd);
     983             : 
     984             :         // list of points we expect to visit
     985           1 :         std::deque<RealVector_t> visitedVoxels;
     986           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 2.5}});
     987           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 1.5}});
     988           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 0.5}});
     989             : 
     990           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
     991             : 
     992           1 :         THEN("Exactly three steps are taken")
     993           1 :         {
     994           1 :             CHECK_EQ(counter, 3);
     995           1 :         }
     996           1 :     }
     997             : 
     998           9 :     WHEN("Traversing the grid slightly below the volume center diagonally")
     999           9 :     {
    1000           1 :         const RealVector_t ro({{3.75, 3.5}});
    1001             : 
    1002           1 :         const RealRay_t ray(ro, rd);
    1003             : 
    1004             :         // list of points we expect to visit
    1005           1 :         std::deque<RealVector_t> visitedVoxels;
    1006           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 2.25}});
    1007           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 1.25}});
    1008           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 0.25}});
    1009             : 
    1010           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
    1011             : 
    1012           1 :         THEN("Exactly three steps are taken")
    1013           1 :         {
    1014           1 :             CHECK_EQ(counter, 3);
    1015           1 :         }
    1016           1 :     }
    1017             : 
    1018           9 :     WHEN("Traversing the grid through the bottom and right center voxel")
    1019           9 :     {
    1020           1 :         const RealVector_t ro({{3.5, 2.5}});
    1021             : 
    1022           1 :         const RealRay_t ray(ro, rd);
    1023             : 
    1024             :         // list of points we expect to visit
    1025           1 :         std::deque<RealVector_t> visitedVoxels;
    1026           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 1.5}});
    1027           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 0.5}});
    1028             : 
    1029           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
    1030             : 
    1031           1 :         THEN("Exactly two steps are taken")
    1032           1 :         {
    1033           1 :             CHECK_EQ(counter, 2);
    1034           1 :         }
    1035           1 :     }
    1036             : 
    1037           9 :     WHEN("Traversing the grid through the bottom left corner")
    1038           9 :     {
    1039           1 :         const RealVector_t ro({{3.5, 1.5}});
    1040             : 
    1041           1 :         const RealRay_t ray(ro, rd);
    1042             : 
    1043             :         // list of points we expect to visit
    1044           1 :         std::deque<RealVector_t> visitedVoxels;
    1045           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 0.5}});
    1046             : 
    1047           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
    1048             : 
    1049           1 :         THEN("Exactly two steps are taken")
    1050           1 :         {
    1051           1 :             CHECK_EQ(counter, 1);
    1052           1 :         }
    1053           1 :     }
    1054           9 : }
    1055             : 
    1056             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 0, 0]")
    1057           4 : {
    1058           4 :     auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
    1059           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1060             : 
    1061           4 :     const RealVector_t ro({{-2.5, 1.5, 1.5}});
    1062           4 :     INFO("ro := ", ro.format(vecfmt));
    1063             : 
    1064           4 :     const RealVector_t rd({{1, 0, 0}});
    1065           4 :     INFO("rd := ", rd.format(vecfmt));
    1066             : 
    1067           4 :     const RealRay_t ray(ro, rd);
    1068             : 
    1069           4 :     checkTransformationBasic(ray, centerOfRotation, expectedRotation);
    1070           4 : }
    1071             : 
    1072             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 1, 0]")
    1073           4 : {
    1074           4 :     auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
    1075           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1076             : 
    1077           4 :     const RealVector_t ro({{-2.5, -2.5, 1.5}});
    1078           4 :     INFO("ro := ", ro.format(vecfmt));
    1079             : 
    1080           4 :     const RealVector_t rd({{1, 1, 0}});
    1081           4 :     INFO("rd := ", rd.format(vecfmt));
    1082             : 
    1083           4 :     const RealRay_t ray(ro, rd);
    1084             : 
    1085           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, 0}}), rd, expectedRotation);
    1086           4 : }
    1087             : 
    1088             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, -1, 0]")
    1089           4 : {
    1090           4 :     auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
    1091           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1092             : 
    1093           4 :     const RealVector_t ro({{-2.5, 5.5, 1.5}});
    1094           4 :     INFO("ro := ", ro.format(vecfmt));
    1095             : 
    1096           4 :     const RealVector_t rd({{1, -1, 0}});
    1097           4 :     INFO("rd := ", rd.format(vecfmt));
    1098             : 
    1099           4 :     const RealRay_t ray(ro, rd);
    1100             : 
    1101           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 4, 0}}), rd, expectedRotation);
    1102           4 : }
    1103             : 
    1104             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 0, 1]")
    1105           4 : {
    1106           4 :     auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
    1107           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1108             : 
    1109           4 :     const RealVector_t ro({{-2.5, 1.5, -2.5}});
    1110           4 :     INFO("ro := ", ro.format(vecfmt));
    1111             : 
    1112           4 :     const RealVector_t rd({{1, 0, 1}});
    1113           4 :     INFO("rd := ", rd.format(vecfmt));
    1114             : 
    1115           4 :     const RealRay_t ray(ro, rd);
    1116             : 
    1117           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, -4}}), rd, expectedRotation);
    1118           4 : }
    1119             : 
    1120             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 0, -1]")
    1121           4 : {
    1122           4 :     auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
    1123           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1124             : 
    1125           4 :     const RealVector_t ro({{-2.5, 1.5, 5.5}});
    1126           4 :     INFO("ro := ", ro.format(vecfmt));
    1127             : 
    1128           4 :     const RealVector_t rd({{1, 0, -1}});
    1129           4 :     INFO("rd := ", rd.format(vecfmt));
    1130             : 
    1131           4 :     const RealRay_t ray(ro, rd);
    1132             : 
    1133           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, 4}}), rd, expectedRotation);
    1134           4 : }
    1135             : 
    1136             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 1, 1]")
    1137           4 : {
    1138           4 :     auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
    1139           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1140             : 
    1141           4 :     const RealVector_t ro({{-2.5, -2.5, -2.5}});
    1142           4 :     INFO("ro := ", ro.format(vecfmt));
    1143             : 
    1144           4 :     const RealVector_t rd({{1, 1, 1}});
    1145           4 :     INFO("rd := ", rd.format(vecfmt));
    1146             : 
    1147           4 :     const RealRay_t ray(ro, rd);
    1148             : 
    1149           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, -4}}), rd, expectedRotation);
    1150           4 : }
    1151             : 
    1152             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [1, 1, -1]")
    1153           4 : {
    1154           4 :     auto expectedRotation = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX()).matrix();
    1155           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1156             : 
    1157           4 :     const RealVector_t ro({{-2.5, -2.5, 5.5}});
    1158           4 :     INFO("ro := ", ro.format(vecfmt));
    1159             : 
    1160           4 :     const RealVector_t rd({{1, 1, -1}});
    1161           4 :     INFO("rd := ", rd.format(vecfmt));
    1162             : 
    1163           4 :     const RealRay_t ray(ro, rd);
    1164             : 
    1165           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, 4}}), rd, expectedRotation);
    1166           4 : }
    1167             : 
    1168             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, 0, 0]")
    1169           4 : {
    1170           4 :     auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
    1171           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1172             : 
    1173           4 :     const RealVector_t ro({{5.5, 1.5, 1.5}});
    1174           4 :     INFO("ro := ", ro.format(vecfmt));
    1175             : 
    1176           4 :     const RealVector_t rd({{-1, 0, 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 [-1, 1, 0]")
    1185           4 : {
    1186           4 :     auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
    1187           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1188             : 
    1189           4 :     const RealVector_t ro({{5.5, -2.5, 1.5}});
    1190           4 :     INFO("ro := ", ro.format(vecfmt));
    1191             : 
    1192           4 :     const RealVector_t rd({{-1, 1, 0}});
    1193           4 :     INFO("rd := ", rd.format(vecfmt));
    1194             : 
    1195           4 :     const RealRay_t ray(ro, rd);
    1196             : 
    1197           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, -4, 0}}),
    1198           4 :                         RealVector_t({{1, 1, 0}}), expectedRotation);
    1199           4 : }
    1200             : 
    1201             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, -1, 0]")
    1202           4 : {
    1203           4 :     auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
    1204           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1205             : 
    1206           4 :     const RealVector_t ro({{5.5, 5.5, 1.5}});
    1207           4 :     INFO("ro := ", ro.format(vecfmt));
    1208             : 
    1209           4 :     const RealVector_t rd({{-1, -1, 0}});
    1210           4 :     INFO("rd := ", rd.format(vecfmt));
    1211             : 
    1212           4 :     const RealRay_t ray(ro, rd);
    1213             : 
    1214           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 4, 0}}),
    1215           4 :                         RealVector_t({{1, -1, 0}}), expectedRotation);
    1216           4 : }
    1217             : 
    1218             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, 0, 1]")
    1219           4 : {
    1220           4 :     auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
    1221           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1222             : 
    1223           4 :     const RealVector_t ro({{5.5, 1.5, -2.5}});
    1224           4 :     INFO("ro := ", ro.format(vecfmt));
    1225             : 
    1226           4 :     const RealVector_t rd({{-1, 0, 1}});
    1227           4 :     INFO("rd := ", rd.format(vecfmt));
    1228             : 
    1229           4 :     const RealRay_t ray(ro, rd);
    1230             : 
    1231           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, 4}}),
    1232           4 :                         RealVector_t({{1, 0, -1}}), expectedRotation);
    1233           4 : }
    1234             : 
    1235             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [-1, 0, -1]")
    1236           4 : {
    1237           4 :     auto expectedRotation = Eigen::AngleAxisf(pi_t, Eigen::Vector3f::UnitY()).matrix();
    1238           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1239             : 
    1240           4 :     const RealVector_t ro({{5.5, 1.5, 5.5}});
    1241           4 :     INFO("ro := ", ro.format(vecfmt));
    1242             : 
    1243           4 :     const RealVector_t rd({{-1, 0, -1}});
    1244           4 :     INFO("rd := ", rd.format(vecfmt));
    1245             : 
    1246           4 :     const RealRay_t ray(ro, rd);
    1247             : 
    1248           4 :     checkTransformation(ray, centerOfRotation, RealVector_t({{-4, 0, -4}}),
    1249           4 :                         RealVector_t({{1, 0, 1}}), expectedRotation);
    1250           4 : }
    1251             : 
    1252             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, 1, 0]")
    1253           4 : {
    1254           4 :     auto expectedRotation = Eigen::AngleAxisf(-0.5 * pi_t, Eigen::Vector3f::UnitZ()).matrix();
    1255           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1256             : 
    1257           4 :     const RealVector_t ro({{1.5, -2.5, 1.5}});
    1258           4 :     INFO("ro := ", ro.format(vecfmt));
    1259             : 
    1260           4 :     const RealVector_t rd({{0, 1, 0}});
    1261           4 :     INFO("rd := ", rd.format(vecfmt));
    1262             : 
    1263           4 :     const RealRay_t ray(ro, rd);
    1264             : 
    1265           4 :     checkTransformationBasic(ray, centerOfRotation, expectedRotation);
    1266           4 : }
    1267             : 
    1268             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, -1, 0]")
    1269           4 : {
    1270           4 :     auto expectedRotation = Eigen::AngleAxisf(0.5 * pi_t, Eigen::Vector3f::UnitZ()).matrix();
    1271           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1272             : 
    1273           4 :     const RealVector_t ro({{1.5, 5.5, 1.5}});
    1274           4 :     INFO("ro := ", ro.format(vecfmt));
    1275             : 
    1276           4 :     const RealVector_t rd({{0, -1, 0}});
    1277           4 :     INFO("rd := ", rd.format(vecfmt));
    1278             : 
    1279           4 :     const RealRay_t ray(ro, rd);
    1280             : 
    1281           4 :     checkTransformationBasic(ray, centerOfRotation, expectedRotation);
    1282           4 : }
    1283             : 
    1284             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, 0, 1]")
    1285           4 : {
    1286           4 :     auto expectedRotation = Eigen::AngleAxisf(0.5 * pi_t, Eigen::Vector3f::UnitY()).matrix();
    1287           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1288             : 
    1289           4 :     const RealVector_t ro({{1.5, 1.5, -2.5}});
    1290           4 :     INFO("ro := ", ro.format(vecfmt));
    1291             : 
    1292           4 :     const RealVector_t rd({{0, 0, 1}});
    1293           4 :     INFO("rd := ", rd.format(vecfmt));
    1294             : 
    1295           4 :     const RealRay_t ray(ro, rd);
    1296             : 
    1297           4 :     checkTransformationBasic(ray, centerOfRotation, expectedRotation);
    1298           4 : }
    1299             : 
    1300             : TEST_CASE("TraversalTransformation: Traversing a 3D grid, dir [0, 0, -1]")
    1301           4 : {
    1302           4 :     auto expectedRotation = Eigen::AngleAxisf(-0.5 * pi_t, Eigen::Vector3f::UnitY()).matrix();
    1303           4 :     const RealVector_t centerOfRotation({{1.5, 1.5, 1.5}});
    1304             : 
    1305           4 :     const RealVector_t ro({{1.5, 1.5, 5.5}});
    1306           4 :     INFO("ro := ", ro.format(vecfmt));
    1307             : 
    1308           4 :     const RealVector_t rd({{0, 0, -1}});
    1309           4 :     INFO("rd := ", rd.format(vecfmt));
    1310             : 
    1311           4 :     const RealRay_t ray(ro, rd);
    1312             : 
    1313           4 :     checkTransformationBasic(ray, centerOfRotation, expectedRotation);
    1314           4 : }
    1315             : 
    1316             : TEST_CASE("SliceTraversal: Traversing a 2D grid diagonally, dir [1, 0, 0]")
    1317           1 : {
    1318           1 :     IndexVector_t size({{3, 3, 3}});
    1319             : 
    1320           1 :     BoundingBox aabb(size);
    1321             : 
    1322           1 :     RealVector_t rd({{1, 0, 0}});
    1323           1 :     rd.normalize();
    1324             : 
    1325           1 :     CAPTURE(aabb);
    1326             : 
    1327           1 :     WHEN("Traversing the grid through the center of the top left corner")
    1328           1 :     {
    1329           1 :         const RealVector_t ro({{-1.5, 0, 0}});
    1330             : 
    1331           1 :         const RealRay_t ray(ro, rd);
    1332             : 
    1333             :         // list of points we expect to visit
    1334           1 :         std::deque<RealVector_t> visitedVoxels;
    1335           1 :         visitedVoxels.emplace_back(RealVector_t{{0.5, 0, 0}});
    1336           1 :         visitedVoxels.emplace_back(RealVector_t{{1.5, 0, 0}});
    1337           1 :         visitedVoxels.emplace_back(RealVector_t{{2.5, 0, 0}});
    1338             : 
    1339           1 :         auto counter = checkTraversal(aabb, ray, visitedVoxels);
    1340             : 
    1341           1 :         THEN("Exactly one step is taken")
    1342           1 :         {
    1343           1 :             CHECK_EQ(counter, 3);
    1344           1 :         }
    1345           1 :     }
    1346           1 : }

Generated by: LCOV version 1.14