LCOV - code coverage report
Current view: top level - elsa/projectors/tests - test_TraverseAABB.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 773 773 100.0 %
Date: 2022-08-25 03:05:39 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file test_TraverseAABB.cpp
       3             :  *
       4             :  * @brief Test for TraverseAABB class
       5             :  *
       6             :  * @author David Frank - initial code
       7             :  * @author Maximilian Hornung - modularization, fixes
       8             :  * @author Tobias Lasser - minor fixes
       9             :  */
      10             : 
      11             : #include "doctest/doctest.h"
      12             : 
      13             : #include "TraverseAABB.h"
      14             : #include "Intersection.h"
      15             : 
      16             : using namespace elsa;
      17             : using namespace doctest;
      18             : 
      19             : bool intersect(const RealVector_t& voxel, const RealRay_t& r)
      20        1691 : {
      21             :     // pre-check parallel rays
      22        4689 :     for (index_t i = 0; i < r.dim(); ++i) {
      23        3254 :         real_t tmp = std::abs(r.origin()(i) - voxel(i));
      24             : 
      25        3254 :         if (std::abs(r.direction()(i)) < 0.0000001 && tmp >= 0.0 && tmp < 1.0)
      26         256 :             return true;
      27        3254 :     }
      28             : 
      29             :     // check if ray intersects pixel
      30        1691 :     IndexVector_t ones(voxel.size());
      31        1435 :     ones.setOnes();
      32        1435 :     BoundingBox bb(ones);
      33        1435 :     bb._min += voxel;
      34        1435 :     bb._max += voxel;
      35             : 
      36        1435 :     return Intersection::withRay(bb, r).operator bool();
      37        1691 : }
      38             : 
      39             : TEST_CASE("TraverseAABB: Construction of a 2D traversal object")
      40          28 : {
      41             :     // setup
      42          28 :     size_t dim = 2;
      43          28 :     index_t x = 3;
      44          28 :     index_t y = 3;
      45          28 :     IndexVector_t volumeDims(dim);
      46          28 :     volumeDims << x, y;
      47             : 
      48          28 :     RealVector_t spacing(dim);
      49             : 
      50          28 :     RealVector_t ro(dim);
      51          28 :     RealVector_t rd(dim);
      52             : 
      53          28 :     GIVEN("A 3x3 aabb with standard spacing")
      54          28 :     {
      55          28 :         BoundingBox aabb(volumeDims);
      56             : 
      57             :         //================================
      58             :         //  intersection from straight rays from the bottom
      59             :         //================================
      60          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (0.5, "
      61          28 :              "-0.5) and direction (0, 1)")
      62          28 :         {
      63           1 :             ro << 0.5, -0.5;
      64           1 :             rd << 0.0, 1.0;
      65           1 :             RealRay_t r(ro, rd);
      66             : 
      67           1 :             TraverseAABB traverse(aabb, r);
      68           1 :             CHECK_UNARY(traverse.isInBoundingBox());
      69           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
      70           1 :             {
      71           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
      72           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
      73           1 :             }
      74           1 :         }
      75             : 
      76          28 :         WHEN("A ray with origin = (1.0, -0.5) and direction (0, 1), hits the boundary between 2 "
      77          28 :              "voxels")
      78          28 :         {
      79           1 :             ro << 1.0, -0.5;
      80           1 :             rd << 0.0, 1.0;
      81           1 :             RealRay_t r(ro, rd);
      82             : 
      83           1 :             TraverseAABB traverse(aabb, r);
      84           1 :             CHECK_UNARY(traverse.isInBoundingBox());
      85           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
      86           1 :             {
      87           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 1);
      88           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
      89           1 :             }
      90           1 :         }
      91             : 
      92          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (1.5, "
      93          28 :              "-0.5) and direction (0, 1)")
      94          28 :         {
      95           1 :             ro << 1.5, -0.5;
      96           1 :             rd << 0.0, 1.0;
      97           1 :             RealRay_t r(ro, rd);
      98             : 
      99           1 :             TraverseAABB traverse(aabb, r);
     100           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     101           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     102           1 :             {
     103           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 1);
     104           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     105           1 :             }
     106           1 :         }
     107             : 
     108          28 :         WHEN("A ray with origin = (2.0, -0.5) and direction (0, 1), hits the boundary between 2 "
     109          28 :              "voxels")
     110          28 :         {
     111           1 :             ro << 2.0, -0.5;
     112           1 :             rd << 0.0, 1.0;
     113           1 :             RealRay_t r(ro, rd);
     114             : 
     115           1 :             TraverseAABB traverse(aabb, r);
     116           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     117           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     118           1 :             {
     119           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     120           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     121           1 :             }
     122           1 :         }
     123             : 
     124          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (2.5, "
     125          28 :              "-0.5) and direction (0, 1)")
     126          28 :         {
     127           1 :             ro << 2.5, -0.5;
     128           1 :             rd << 0.0, 1.0;
     129           1 :             RealRay_t r(ro, rd);
     130             : 
     131           1 :             TraverseAABB traverse(aabb, r);
     132           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     133           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     134           1 :             {
     135           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     136           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     137           1 :             }
     138           1 :         }
     139             : 
     140             :         //================================
     141             :         //  intersection from straight rays from the left
     142             :         //================================
     143          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (-0.5, "
     144          28 :              "0.5) and direction (1, 0)")
     145          28 :         {
     146           1 :             ro << -0.5, 0.5;
     147           1 :             rd << 1.0, 0.0;
     148           1 :             RealRay_t r(ro, rd);
     149             : 
     150           1 :             TraverseAABB traverse(aabb, r);
     151           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     152           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     153           1 :             {
     154           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     155           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     156           1 :             }
     157           1 :         }
     158             : 
     159          28 :         WHEN("A ray with origin = (1.0, -0.5) and direction (0, 1), hits the boundary between 2 "
     160          28 :              "voxels")
     161          28 :         {
     162           1 :             ro << -0.5, 1.0;
     163           1 :             rd << 1.0, 0.0;
     164           1 :             RealRay_t r(ro, rd);
     165             : 
     166           1 :             TraverseAABB traverse(aabb, r);
     167           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     168           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     169           1 :             {
     170           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     171           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     172           1 :             }
     173           1 :         }
     174             : 
     175          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (-0.5, "
     176          28 :              "1.5) and direction (1, 0)")
     177          28 :         {
     178           1 :             ro << -0.5, 1.5;
     179           1 :             rd << 1.0, 0.0;
     180           1 :             RealRay_t r(ro, rd);
     181             : 
     182           1 :             TraverseAABB traverse(aabb, r);
     183           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     184           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     185           1 :             {
     186           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     187           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     188           1 :             }
     189           1 :         }
     190             : 
     191          28 :         WHEN("A ray with origin = (2.0, -0.5) and direction (0, 1), hits the boundary between 2 "
     192          28 :              "voxels")
     193          28 :         {
     194           1 :             ro << -0.5, 2.0;
     195           1 :             rd << 1.0, 0.0;
     196           1 :             RealRay_t r(ro, rd);
     197             : 
     198           1 :             TraverseAABB traverse(aabb, r);
     199           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     200           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     201           1 :             {
     202           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     203           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     204           1 :             }
     205           1 :         }
     206             : 
     207          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (-0.5, "
     208          28 :              "2.5) and direction (1, 0)")
     209          28 :         {
     210           1 :             ro << -0.5, 2.5;
     211           1 :             rd << 1.0, 0.0;
     212           1 :             RealRay_t r(ro, rd);
     213             : 
     214           1 :             TraverseAABB traverse(aabb, r);
     215           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     216           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     217           1 :             {
     218           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     219           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     220           1 :             }
     221           1 :         }
     222             : 
     223             :         //================================
     224             :         //  intersection from straight rays from the right
     225             :         //================================
     226          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (3.5, "
     227          28 :              "0.5) and direction (-1, 0)")
     228          28 :         {
     229           1 :             ro << 3.5, 0.5;
     230           1 :             rd << -1.0, 0.0;
     231           1 :             RealRay_t r(ro, rd);
     232             : 
     233           1 :             TraverseAABB traverse(aabb, r);
     234           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     235           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     236           1 :             {
     237           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     238           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     239           1 :             }
     240           1 :         }
     241             : 
     242          28 :         WHEN("A ray with origin = (3.5, 1.0) and direction (-1, 0), hits the boundary between 2 "
     243          28 :              "voxels")
     244          28 :         {
     245           1 :             ro << 3.5, 1.0;
     246           1 :             rd << -1.0, 0.0;
     247           1 :             RealRay_t r(ro, rd);
     248             : 
     249           1 :             TraverseAABB traverse(aabb, r);
     250           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     251           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     252           1 :             {
     253           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     254           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     255           1 :             }
     256           1 :         }
     257             : 
     258          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (3.5, "
     259          28 :              "1.5) and direction (-1, 0)")
     260          28 :         {
     261           1 :             ro << 3.5, 1.5;
     262           1 :             rd << -1.0, 0.0;
     263           1 :             RealRay_t r(ro, rd);
     264             : 
     265           1 :             TraverseAABB traverse(aabb, r);
     266           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     267           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     268           1 :             {
     269           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     270           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     271           1 :             }
     272           1 :         }
     273             : 
     274          28 :         WHEN("A ray with origin = (3.5, 2.0) and direction (-1, 0), hits the boundary between 2 "
     275          28 :              "voxels")
     276          28 :         {
     277           1 :             ro << 3.5, 2.0;
     278           1 :             rd << -1.0, 0.0;
     279           1 :             RealRay_t r(ro, rd);
     280             : 
     281           1 :             TraverseAABB traverse(aabb, r);
     282           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     283           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     284           1 :             {
     285           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     286           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     287           1 :             }
     288           1 :         }
     289             : 
     290          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (3.5, "
     291          28 :              "2.5) and direction (-1, 0)")
     292          28 :         {
     293           1 :             ro << 3.5, 2.5;
     294           1 :             rd << -1.0, 0.0;
     295           1 :             RealRay_t r(ro, rd);
     296             : 
     297           1 :             TraverseAABB traverse(aabb, r);
     298           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     299           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     300           1 :             {
     301           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     302           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     303           1 :             }
     304           1 :         }
     305             : 
     306             :         //================================
     307             :         //  intersection from straight rays from the top
     308             :         //================================
     309          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (0.5, "
     310          28 :              "3.5) and direction (0, -1)")
     311          28 :         {
     312           1 :             ro << 0.5, 3.5;
     313           1 :             rd << 0.0, -1.0;
     314           1 :             RealRay_t r(ro, rd);
     315             : 
     316           1 :             TraverseAABB traverse(aabb, r);
     317           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     318           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     319           1 :             {
     320           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     321           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     322           1 :             }
     323           1 :         }
     324             : 
     325          28 :         WHEN("A ray with origin = (1.0, 3.5) and direction (-1, 0), hits the boundary between 2 "
     326          28 :              "voxels")
     327          28 :         {
     328           1 :             ro << 1.0, 3.5;
     329           1 :             rd << 0.0, -1.0;
     330           1 :             RealRay_t r(ro, rd);
     331             : 
     332           1 :             TraverseAABB traverse(aabb, r);
     333           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     334           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     335           1 :             {
     336           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 1);
     337           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     338           1 :             }
     339           1 :         }
     340             : 
     341          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (1.5, "
     342          28 :              "3.5) and direction (0, -1)")
     343          28 :         {
     344           1 :             ro << 1.5, 3.5;
     345           1 :             rd << 0.0, -1.0;
     346           1 :             RealRay_t r(ro, rd);
     347             : 
     348           1 :             TraverseAABB traverse(aabb, r);
     349           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     350           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     351           1 :             {
     352           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 1);
     353           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     354           1 :             }
     355           1 :         }
     356             : 
     357          28 :         WHEN("A ray with origin = (2.0, 3.5) and direction (-1, 0), hits the boundary between 2 "
     358          28 :              "voxels")
     359          28 :         {
     360           1 :             ro << 2.0, 3.5;
     361           1 :             rd << 0.0, -1.0;
     362           1 :             RealRay_t r(ro, rd);
     363             : 
     364           1 :             TraverseAABB traverse(aabb, r);
     365           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     366           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     367           1 :             {
     368           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     369           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     370           1 :             }
     371           1 :         }
     372             : 
     373          28 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (2.5, "
     374          28 :              "3.5) and direction (0, -1)")
     375          28 :         {
     376           1 :             ro << 2.5, 3.5;
     377           1 :             rd << 0.0, -1.0;
     378           1 :             RealRay_t r(ro, rd);
     379             : 
     380           1 :             TraverseAABB traverse(aabb, r);
     381           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     382           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     383           1 :             {
     384           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     385           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     386           1 :             }
     387           1 :         }
     388             : 
     389             :         //
     390             :         // Some edge cases
     391             :         //
     392          28 :         WHEN("A ray with origin = (-0.5, 0.0) and direction (1, 0) hits the left edge of aabb")
     393          28 :         {
     394           1 :             ro << -0.5, 0.0;
     395           1 :             rd << 1.0, 0.0;
     396           1 :             RealRay_t r(ro, rd);
     397             : 
     398           1 :             TraverseAABB traverse(aabb, r);
     399           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     400           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     401           1 :             {
     402           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     403           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     404           1 :             }
     405           1 :         }
     406             : 
     407          28 :         WHEN("A ray with origin = (3.5, 0.0) and direction (-1, 0) hits the left edge of aabb")
     408          28 :         {
     409           1 :             ro << 3.5, 0.0;
     410           1 :             rd << -1.0, 0.0;
     411           1 :             RealRay_t r(ro, rd);
     412             : 
     413           1 :             TraverseAABB traverse(aabb, r);
     414           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     415           1 :             THEN("The ray intersects the aabb at the top left pixel")
     416           1 :             {
     417           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 2);
     418           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     419           1 :             }
     420           1 :         }
     421             : 
     422          28 :         WHEN("A ray with origin = (-0.5, 3.0) and direction (1, 0) hits the top edge of aabb")
     423          28 :         {
     424           1 :             ro << -0.5, 3.0;
     425           1 :             rd << 1.0, 0.0;
     426           1 :             RealRay_t r(ro, rd);
     427             : 
     428           1 :             TraverseAABB traverse(aabb, r);
     429             : 
     430           1 :             THEN("the the aabb is not hit") { REQUIRE_UNARY_FALSE(traverse.isInBoundingBox()); }
     431           1 :         }
     432             : 
     433          28 :         WHEN("A ray with origin = (3.5, 3.0) and direction (-1, 0) hits the top edge of aabb")
     434          28 :         {
     435           1 :             ro << 3.5, 3.0;
     436           1 :             rd << -1.0, 0.0;
     437           1 :             RealRay_t r(ro, rd);
     438             : 
     439           1 :             TraverseAABB traverse(aabb, r);
     440             : 
     441           1 :             THEN("the the aabb is not hit") { REQUIRE_UNARY_FALSE(traverse.isInBoundingBox()); }
     442           1 :         }
     443             : 
     444          28 :         WHEN("A ray with origin = (0.0, -0.5) and direction (0, 1) hits the bottom edge of aabb)")
     445          28 :         {
     446           1 :             ro << 0.0, -0.5;
     447           1 :             rd << 0.0, 1.0;
     448           1 :             RealRay_t r(ro, rd);
     449             : 
     450           1 :             TraverseAABB traverse(aabb, r);
     451           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     452           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     453           1 :             {
     454           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     455           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     456           1 :             }
     457           1 :         }
     458             : 
     459          28 :         WHEN("A ray with origin = (0.0, 3.5) and direction (0, -1) hits the top edge of aabb)")
     460          28 :         {
     461           1 :             ro << 0.0, 3.5;
     462           1 :             rd << 0.0, -1.0;
     463           1 :             RealRay_t r(ro, rd);
     464             : 
     465           1 :             TraverseAABB traverse(aabb, r);
     466           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     467           1 :             THEN("The ray intersects the aabb at the top left pixel")
     468           1 :             {
     469           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     470           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     471           1 :             }
     472           1 :         }
     473             : 
     474          28 :         WHEN("A ray with origin = (3.0, -0.5) and direction (0, 1) hits the right edge of aabb)")
     475          28 :         {
     476           1 :             ro << 3.0, -0.5;
     477           1 :             rd << 0.0, 1.0;
     478           1 :             RealRay_t r(ro, rd);
     479             : 
     480           1 :             TraverseAABB traverse(aabb, r);
     481             : 
     482           1 :             THEN("the the aabb is not hit") { REQUIRE_UNARY_FALSE(traverse.isInBoundingBox()); }
     483           1 :         }
     484             : 
     485          28 :         WHEN("A ray with origin = (3.0, 3.5) and direction (0, -1) hits the top edge of aabb)")
     486          28 :         {
     487           1 :             ro << 3.0, 3.5;
     488           1 :             rd << 0.0, -1.0;
     489           1 :             RealRay_t r(ro, rd);
     490             : 
     491           1 :             TraverseAABB traverse(aabb, r);
     492             : 
     493           1 :             THEN("the the aabb is not hit") { REQUIRE_UNARY_FALSE(traverse.isInBoundingBox()); }
     494           1 :         }
     495          28 :     }
     496          28 : }
     497             : 
     498             : TEST_CASE("TraverseAABB: Construction of a 3D traversal object")
     499           1 : {
     500             :     // setup
     501           1 :     size_t dim = 3;
     502           1 :     IndexVector_t volumeDims(dim);
     503           1 :     volumeDims << 3, 3, 3;
     504             : 
     505           1 :     RealVector_t spacing(dim);
     506             : 
     507           1 :     RealVector_t ro(dim);
     508           1 :     RealVector_t rd(dim);
     509             : 
     510           1 :     GIVEN("a 3x3x3 aabb with standard spacing")
     511           1 :     {
     512           1 :         BoundingBox aabb(volumeDims);
     513             : 
     514           1 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (0.5, "
     515           1 :              "-0.5, 0.5) and direction = (0, 1, 0)")
     516           1 :         {
     517           1 :             ro << 0.5, -0.5, 0.5;
     518           1 :             rd << 0.0, 1.0, 0.0;
     519           1 :             RealRay_t r(ro, rd);
     520             : 
     521           1 :             TraverseAABB traverse(aabb, r);
     522           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     523             : 
     524           1 :             THEN("The ray intersects the aabb at the voxel (0, 0, 0)")
     525           1 :             {
     526           1 :                 REQUIRE_UNARY(traverse.isInBoundingBox());
     527           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     528           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     529           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(2), 0);
     530           1 :             }
     531           1 :         }
     532           1 :     }
     533           1 : }
     534             : 
     535             : TEST_CASE("TraverseAABB: Traverse a minimal 3D volume of size 1x1x1")
     536           1 : {
     537             :     // setup
     538           1 :     size_t dim = 3;
     539           1 :     index_t x = 1;
     540           1 :     index_t y = 1;
     541           1 :     index_t z = 1;
     542           1 :     IndexVector_t volumeDims(dim);
     543           1 :     volumeDims << x, y, z;
     544             : 
     545           1 :     RealVector_t spacing(dim);
     546           1 :     RealVector_t ro(dim);
     547           1 :     RealVector_t rd(dim);
     548             : 
     549           1 :     GIVEN("A 1x1x1 volume with uniform scaling")
     550           1 :     {
     551           1 :         BoundingBox aabb(volumeDims);
     552           1 :         spacing << 1.0, 1.0, 1.0;
     553             : 
     554           1 :         WHEN("The volume is traversed with a ray with origin = (-0.5, 0.5, 0.5) and a direction = "
     555           1 :              "(0, 1, 0)")
     556           1 :         {
     557           1 :             ro << 0.5, -0.5, 0.5;
     558           1 :             rd << 0.0, 1.0, 0.0;
     559             : 
     560           1 :             RealRay_t r(ro, rd);
     561           1 :             TraverseAABB traverse(aabb, r);
     562           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     563             : 
     564           1 :             traverse.updateTraverse();
     565             : 
     566           1 :             THEN("The algorithms left the volume and the voxel it left the box is (0, 1, 0)")
     567           1 :             {
     568           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     569           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     570           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     571           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(2), 0);
     572           1 :             }
     573           1 :         }
     574           1 :     }
     575           1 : }
     576             : 
     577             : TEST_CASE("TraverseAABB: Traverse a 2D volume and only check that the endpoint is correct")
     578           1 : {
     579             :     // setup
     580           1 :     size_t dim = 2;
     581           1 :     index_t x = 10;
     582           1 :     index_t y = 10;
     583           1 :     IndexVector_t volumeDims(dim);
     584           1 :     volumeDims << x, y;
     585             : 
     586           1 :     RealVector_t spacing(dim);
     587           1 :     RealVector_t ro(dim);
     588           1 :     RealVector_t rd(dim);
     589             : 
     590           1 :     GIVEN("A 10x10 volume with uniform scaling")
     591           1 :     {
     592           1 :         BoundingBox aabb(volumeDims);
     593             : 
     594           1 :         WHEN("The volume is traversed with a ray with origin = (-0.5, 0.5, 0.5) and a direction = "
     595           1 :              "(0, 1, 0)")
     596           1 :         {
     597           1 :             ro << -1, 4.5;
     598           1 :             rd << 1.0, 0;
     599             : 
     600           1 :             RealRay_t r(ro, rd);
     601           1 :             TraverseAABB traverse(aabb, r);
     602           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     603             : 
     604          11 :             while (traverse.isInBoundingBox())
     605          10 :                 traverse.updateTraverse();
     606             : 
     607           1 :             THEN("The endpoint should be (10,4)")
     608           1 :             {
     609           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     610           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 10);
     611           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 4);
     612           1 :             }
     613           1 :         }
     614           1 :     }
     615           1 : }
     616             : 
     617             : TEST_CASE("TraverseAABB: Traverse a 3D Volume diagonally")
     618           2 : {
     619             :     // TODO: run through all 4 diagonals
     620             :     // TODO: make a non cube volume and run through all 4 diagonals
     621             :     // TODO: make non uniform scaling and run through all 4 diagonals
     622             : 
     623           2 :     size_t dim = 3;
     624           2 :     IndexVector_t volumeDims(dim);
     625           2 :     volumeDims << 10, 10, 10;
     626             : 
     627           2 :     RealVector_t spacing(dim);
     628           2 :     RealVector_t ro(dim);
     629           2 :     RealVector_t rd(dim);
     630             : 
     631           2 :     GIVEN("A 10x10 volume with uniform scaling")
     632           2 :     {
     633           2 :         BoundingBox aabb(volumeDims);
     634           2 :         WHEN("Start at (-1, -1, -1) (so bottom left front) and run to (10, 10, 10) (so top right "
     635           2 :              "back)")
     636           2 :         {
     637           2 :             ro << -1.0, -1.0, -1.0;
     638           2 :             rd << 1.0, 1.0, 1.0;
     639           2 :             rd.normalize();
     640             : 
     641           2 :             RealRay_t r(ro, rd);
     642             : 
     643           2 :             TraverseAABB traverse(aabb, r);
     644           2 :             CHECK_UNARY(traverse.isInBoundingBox());
     645             : 
     646           2 :             THEN("You entered at (0, 0, 0)")
     647           2 :             {
     648           1 :                 CHECK_EQ(traverse.getCurrentVoxel()(0), 0);
     649           1 :                 CHECK_EQ(traverse.getCurrentVoxel()(1), 0);
     650           1 :                 CHECK_EQ(traverse.getCurrentVoxel()(2), 0);
     651           1 :             }
     652          58 :             while (traverse.isInBoundingBox())
     653          56 :                 traverse.updateTraverse();
     654             : 
     655           2 :             THEN("You leave the volume at (10, 9, 9)")
     656           2 :             {
     657           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     658           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 10);
     659           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 9);
     660           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(2), 9);
     661           1 :             }
     662           2 :         }
     663           2 :     }
     664           2 : }
     665             : 
     666             : TEST_CASE("TraverseAABB: Check that the first step into the 2D Volume is correct")
     667           4 : {
     668           4 :     size_t dim = 2;
     669           4 :     index_t x = 5;
     670           4 :     index_t y = 5;
     671           4 :     IndexVector_t volumeDims(dim);
     672           4 :     volumeDims << x, y;
     673             : 
     674           4 :     RealVector_t ro(dim);
     675           4 :     RealVector_t rd(dim);
     676             : 
     677           4 :     GIVEN("A 5x5 volume with uniform scaling")
     678           4 :     {
     679           4 :         BoundingBox aabb(volumeDims);
     680             : 
     681           4 :         WHEN("The ray direction has the biggest value on the y axis")
     682           4 :         {
     683           2 :             ro << 0, 0;
     684           2 :             rd << 0.5f, 0.7f;
     685           2 :             rd.normalize();
     686             : 
     687           2 :             RealRay_t r(ro, rd);
     688           2 :             TraverseAABB traverse(aabb, r);
     689           2 :             CHECK_UNARY(traverse.isInBoundingBox());
     690             : 
     691           2 :             THEN("The traversal is initially at (0, 0)")
     692           2 :             {
     693           1 :                 auto voxel = traverse.getCurrentVoxel();
     694           1 :                 CHECK_EQ(voxel(0), 0);
     695           1 :                 CHECK_EQ(voxel(1), 0);
     696           1 :             }
     697             : 
     698           2 :             traverse.updateTraverse();
     699             : 
     700           2 :             THEN("The first step is in y direction")
     701           2 :             {
     702           1 :                 REQUIRE_UNARY(traverse.isInBoundingBox());
     703           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     704           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     705           1 :             }
     706           2 :         }
     707             : 
     708           4 :         WHEN("The ray direction has the biggest value on the x axis")
     709           4 :         {
     710           2 :             ro << 0, 0;
     711           2 :             rd << 0.7f, 0.5f;
     712           2 :             rd.normalize();
     713             : 
     714           2 :             RealRay_t r(ro, rd);
     715           2 :             TraverseAABB traverse(aabb, r);
     716           2 :             CHECK_UNARY(traverse.isInBoundingBox());
     717             : 
     718           2 :             THEN("The traversal is initially at (0, 0)")
     719           2 :             {
     720           1 :                 auto voxel = traverse.getCurrentVoxel();
     721           1 :                 CHECK_EQ(voxel(0), 0);
     722           1 :                 CHECK_EQ(voxel(1), 0);
     723           1 :             }
     724             : 
     725           2 :             traverse.updateTraverse();
     726             : 
     727           2 :             THEN("The first step is in y direction")
     728           2 :             {
     729           1 :                 REQUIRE_UNARY(traverse.isInBoundingBox());
     730           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 1);
     731           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     732           1 :             }
     733           2 :         }
     734           4 :     }
     735           4 : }
     736             : 
     737             : TEST_CASE("TraverseAABB: Traverse_Volume_2D_EachPointIsTested")
     738           1 : {
     739             :     // setup
     740           1 :     size_t dim = 2;
     741           1 :     index_t x = 128;
     742           1 :     index_t y = 128;
     743           1 :     IndexVector_t volumeDims(dim);
     744           1 :     volumeDims << x, y;
     745           1 :     BoundingBox aabb(volumeDims);
     746             : 
     747           1 :     RealVector_t ro(dim);
     748           1 :     ro << -168.274f, -143.397f;
     749           1 :     RealVector_t rd(dim);
     750           1 :     rd << 0.761124909f, 0.648605406f;
     751           1 :     rd.normalize();
     752           1 :     RealRay_t r(ro, rd);
     753             : 
     754           1 :     TraverseAABB traverse(aabb, r);
     755           1 :     CHECK_UNARY(traverse.isInBoundingBox());
     756             : 
     757           1 :     size_t iter = 0;
     758         238 :     while (traverse.isInBoundingBox()) {
     759         237 :         RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     760         237 :         INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     761             : 
     762         237 :         REQUIRE_UNARY(intersect(voxel, r));
     763         237 :         traverse.updateTraverse();
     764         237 :         iter++;
     765         237 :     }
     766           1 : }
     767             : 
     768             : TEST_CASE("TraverseAABB: Traversal through 2D volume should be equal to a ray voxel intersection "
     769             :           "for every voxel along the way")
     770           8 : {
     771             :     // TODO make this a stronger test, for first some "easy" direction (parallel ones)
     772             :     // TODO Then make some harder ones
     773             :     // setup
     774           8 :     size_t dim = 2;
     775           8 :     index_t x = 128;
     776           8 :     index_t y = 128;
     777           8 :     IndexVector_t volumeDims(dim);
     778           8 :     volumeDims << x, y;
     779           8 :     BoundingBox aabb(volumeDims);
     780             : 
     781           8 :     RealVector_t ro(dim);
     782           8 :     RealVector_t rd(dim);
     783             : 
     784           8 :     GIVEN("a point at the bottom left of the volume and a ray with leading dimension x")
     785           8 :     {
     786           1 :         ro << -168.274f, -143.397f;
     787             : 
     788           1 :         rd << 0.761124909f, 0.648605406f;
     789           1 :         rd.normalize();
     790             : 
     791           1 :         RealRay_t r(ro, rd);
     792             : 
     793           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     794           1 :         {
     795           1 :             TraverseAABB traverse(aabb, r);
     796           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     797             : 
     798           1 :             size_t iter = 0;
     799         238 :             while (traverse.isInBoundingBox()) {
     800         237 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     801         237 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     802             : 
     803         237 :                 REQUIRE_UNARY(intersect(voxel, r));
     804         237 :                 traverse.updateTraverse();
     805         237 :                 iter++;
     806         237 :             }
     807           1 :         }
     808           1 :     }
     809             : 
     810           8 :     GIVEN("a point at the bottom left of the volume and a ray with leading dimension y")
     811           8 :     {
     812           1 :         ro << 0, 0;
     813             : 
     814           1 :         rd << 0.648605406f, 0.761124909f;
     815           1 :         rd.normalize();
     816             : 
     817           1 :         RealRay_t r(ro, rd);
     818             : 
     819           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     820           1 :         {
     821           1 :             TraverseAABB traverse(aabb, r);
     822           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     823             : 
     824           1 :             size_t iter = 0;
     825         238 :             while (traverse.isInBoundingBox()) {
     826         237 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     827         237 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     828             : 
     829         237 :                 REQUIRE_UNARY(intersect(voxel, r));
     830         237 :                 traverse.updateTraverse();
     831         237 :                 iter++;
     832         237 :             }
     833           1 :         }
     834           1 :     }
     835             : 
     836           8 :     GIVEN("a ray going through the border of voxel column 0 and 1")
     837           8 :     {
     838           1 :         ro << 1, -0.5f;
     839             : 
     840           1 :         rd << 0, 1;
     841           1 :         rd.normalize();
     842             : 
     843           1 :         RealRay_t r(ro, rd);
     844             : 
     845           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     846           1 :         {
     847           1 :             TraverseAABB traverse(aabb, r);
     848           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     849             : 
     850           1 :             size_t iter = 0;
     851         129 :             while (traverse.isInBoundingBox()) {
     852         128 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     853         128 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     854             : 
     855         128 :                 REQUIRE_UNARY(intersect(voxel, r));
     856         128 :                 traverse.updateTraverse();
     857         128 :                 iter++;
     858         128 :             }
     859           1 :         }
     860           1 :     }
     861             : 
     862           8 :     GIVEN("a ray going through the border of voxel row 0 and 1")
     863           8 :     {
     864           1 :         ro << -0.5f, 1;
     865             : 
     866           1 :         rd << 1, 0;
     867           1 :         rd.normalize();
     868             : 
     869           1 :         RealRay_t r(ro, rd);
     870             : 
     871           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     872           1 :         {
     873           1 :             TraverseAABB traverse(aabb, r);
     874           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     875             : 
     876           1 :             size_t iter = 0;
     877         129 :             while (traverse.isInBoundingBox()) {
     878         128 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     879         128 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     880             : 
     881         128 :                 REQUIRE_UNARY(intersect(voxel, r));
     882         128 :                 traverse.updateTraverse();
     883         128 :                 iter++;
     884         128 :             }
     885           1 :         }
     886           1 :     }
     887             : 
     888           8 :     GIVEN("A ray going diagonally through the volume")
     889           8 :     {
     890           1 :         ro << -0.5f, -0.5f;
     891             : 
     892           1 :         rd << 1, 1;
     893           1 :         rd.normalize();
     894             : 
     895           1 :         RealRay_t r(ro, rd);
     896             : 
     897           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     898           1 :         {
     899           1 :             TraverseAABB traverse(aabb, r);
     900           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     901             : 
     902           1 :             size_t iter = 0;
     903         256 :             while (traverse.isInBoundingBox()) {
     904         255 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     905         255 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     906             : 
     907         255 :                 REQUIRE_UNARY(intersect(voxel, r));
     908         255 :                 traverse.updateTraverse();
     909         255 :                 iter++;
     910         255 :             }
     911           1 :         }
     912           1 :     }
     913             : 
     914           8 :     GIVEN("A ray going diagonally through the volume")
     915           8 :     {
     916           1 :         ro << -0.5f, 32;
     917             : 
     918           1 :         rd << 1, 1;
     919           1 :         rd.normalize();
     920             : 
     921           1 :         RealRay_t r(ro, rd);
     922             : 
     923           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     924           1 :         {
     925           1 :             TraverseAABB traverse(aabb, r);
     926           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     927             : 
     928           1 :             size_t iter = 0;
     929         192 :             while (traverse.isInBoundingBox()) {
     930         191 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     931         191 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     932             : 
     933         191 :                 REQUIRE_UNARY(intersect(voxel, r));
     934         191 :                 traverse.updateTraverse();
     935         191 :                 iter++;
     936         191 :             }
     937           1 :         }
     938           1 :     }
     939             : 
     940           8 :     GIVEN("A ray going diagonally through the volume")
     941           8 :     {
     942           1 :         ro << -0.5f, -0.5f;
     943             : 
     944           1 :         rd << 0.699428f, 0.472203f;
     945           1 :         rd.normalize();
     946             : 
     947           1 :         RealRay_t r(ro, rd);
     948             : 
     949           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     950           1 :         {
     951           1 :             TraverseAABB traverse(aabb, r);
     952           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     953             : 
     954           1 :             size_t iter = 0;
     955         215 :             while (traverse.isInBoundingBox()) {
     956         214 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     957         214 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     958             : 
     959         214 :                 REQUIRE_UNARY(intersect(voxel, r));
     960         214 :                 traverse.updateTraverse();
     961         214 :                 iter++;
     962         214 :             }
     963           1 :         }
     964           1 :     }
     965             : 
     966           8 :     GIVEN("A ray going diagonally through the volume")
     967           8 :     {
     968           1 :         volumeDims << 64, 64;
     969           1 :         BoundingBox aabb(volumeDims);
     970             : 
     971           1 :         ro << 32.0002823f, 3232;
     972             : 
     973           1 :         rd << -0.000723466626f, -0.999999762f;
     974           1 :         rd.normalize();
     975             : 
     976           1 :         RealRay_t r(ro, rd);
     977             : 
     978           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     979           1 :         {
     980           1 :             TraverseAABB traverse(aabb, r);
     981           1 :             traverse.isInBoundingBox();
     982             : 
     983           1 :             size_t iter = 0;
     984          65 :             while (traverse.isInBoundingBox()) {
     985          64 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     986          64 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     987             : 
     988          64 :                 REQUIRE_UNARY(intersect(voxel, r));
     989          64 :                 traverse.updateTraverse();
     990          64 :                 iter++;
     991          64 :             }
     992           1 :         }
     993           1 :     }
     994           8 : }

Generated by: LCOV version 1.14