LCOV - code coverage report
Current view: top level - elsa/projectors/tests - test_SliceTraversal.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 804 804 100.0 %
Date: 2022-08-25 03:05:39 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") { 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 : }

Generated by: LCOV version 1.14