LCOV - code coverage report
Current view: top level - elsa/projectors/tests - test_TraverseAABB.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 785 785 100.0 %
Date: 2023-01-26 04:22:16 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        3255 : {
      21             :     // pre-check parallel rays
      22        8997 :     for (index_t i = 0; i < r.dim(); ++i) {
      23        6254 :         real_t tmp = std::abs(r.origin()(i) - voxel(i));
      24             : 
      25        6254 :         if (std::abs(r.direction()(i)) < 0.0000001 && tmp >= 0.0 && tmp < 1.0)
      26         512 :             return true;
      27        6254 :     }
      28             : 
      29             :     // check if ray intersects pixel
      30        3255 :     IndexVector_t ones(voxel.size());
      31        2743 :     ones.setOnes();
      32        2743 :     BoundingBox bb(ones);
      33        2743 :     bb.min() += voxel;
      34        2743 :     bb.max() += voxel;
      35             : 
      36        2743 :     return intersectRay(bb, r).operator bool();
      37        3255 : }
      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")
     431           1 :             {
     432           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     433           1 :             }
     434           1 :         }
     435             : 
     436          28 :         WHEN("A ray with origin = (3.5, 3.0) and direction (-1, 0) hits the top edge of aabb")
     437          28 :         {
     438           1 :             ro << 3.5, 3.0;
     439           1 :             rd << -1.0, 0.0;
     440           1 :             RealRay_t r(ro, rd);
     441             : 
     442           1 :             TraverseAABB traverse(aabb, r);
     443             : 
     444           1 :             THEN("the the aabb is not hit")
     445           1 :             {
     446           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     447           1 :             }
     448           1 :         }
     449             : 
     450          28 :         WHEN("A ray with origin = (0.0, -0.5) and direction (0, 1) hits the bottom edge of aabb)")
     451          28 :         {
     452           1 :             ro << 0.0, -0.5;
     453           1 :             rd << 0.0, 1.0;
     454           1 :             RealRay_t r(ro, rd);
     455             : 
     456           1 :             TraverseAABB traverse(aabb, r);
     457           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     458           1 :             THEN("The ray intersects the aabb at the bottom left pixel")
     459           1 :             {
     460           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     461           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     462           1 :             }
     463           1 :         }
     464             : 
     465          28 :         WHEN("A ray with origin = (0.0, 3.5) and direction (0, -1) hits the top edge of aabb)")
     466          28 :         {
     467           1 :             ro << 0.0, 3.5;
     468           1 :             rd << 0.0, -1.0;
     469           1 :             RealRay_t r(ro, rd);
     470             : 
     471           1 :             TraverseAABB traverse(aabb, r);
     472           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     473           1 :             THEN("The ray intersects the aabb at the top left pixel")
     474           1 :             {
     475           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     476           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 2);
     477           1 :             }
     478           1 :         }
     479             : 
     480          28 :         WHEN("A ray with origin = (3.0, -0.5) and direction (0, 1) hits the right edge of aabb)")
     481          28 :         {
     482           1 :             ro << 3.0, -0.5;
     483           1 :             rd << 0.0, 1.0;
     484           1 :             RealRay_t r(ro, rd);
     485             : 
     486           1 :             TraverseAABB traverse(aabb, r);
     487             : 
     488           1 :             THEN("the the aabb is not hit")
     489           1 :             {
     490           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     491           1 :             }
     492           1 :         }
     493             : 
     494          28 :         WHEN("A ray with origin = (3.0, 3.5) and direction (0, -1) hits the top edge of aabb)")
     495          28 :         {
     496           1 :             ro << 3.0, 3.5;
     497           1 :             rd << 0.0, -1.0;
     498           1 :             RealRay_t r(ro, rd);
     499             : 
     500           1 :             TraverseAABB traverse(aabb, r);
     501             : 
     502           1 :             THEN("the the aabb is not hit")
     503           1 :             {
     504           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     505           1 :             }
     506           1 :         }
     507          28 :     }
     508          28 : }
     509             : 
     510             : TEST_CASE("TraverseAABB: Construction of a 3D traversal object")
     511           1 : {
     512             :     // setup
     513           1 :     size_t dim = 3;
     514           1 :     IndexVector_t volumeDims(dim);
     515           1 :     volumeDims << 3, 3, 3;
     516             : 
     517           1 :     RealVector_t spacing(dim);
     518             : 
     519           1 :     RealVector_t ro(dim);
     520           1 :     RealVector_t rd(dim);
     521             : 
     522           1 :     GIVEN("a 3x3x3 aabb with standard spacing")
     523           1 :     {
     524           1 :         BoundingBox aabb(volumeDims);
     525             : 
     526           1 :         WHEN("A traversal algorithms is initialised with the aabb and a ray with origin = (0.5, "
     527           1 :              "-0.5, 0.5) and direction = (0, 1, 0)")
     528           1 :         {
     529           1 :             ro << 0.5, -0.5, 0.5;
     530           1 :             rd << 0.0, 1.0, 0.0;
     531           1 :             RealRay_t r(ro, rd);
     532             : 
     533           1 :             TraverseAABB traverse(aabb, r);
     534           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     535             : 
     536           1 :             THEN("The ray intersects the aabb at the voxel (0, 0, 0)")
     537           1 :             {
     538           1 :                 REQUIRE_UNARY(traverse.isInBoundingBox());
     539           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     540           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     541           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(2), 0);
     542           1 :             }
     543           1 :         }
     544           1 :     }
     545           1 : }
     546             : 
     547             : TEST_CASE("TraverseAABB: Traverse a minimal 3D volume of size 1x1x1")
     548           1 : {
     549             :     // setup
     550           1 :     size_t dim = 3;
     551           1 :     index_t x = 1;
     552           1 :     index_t y = 1;
     553           1 :     index_t z = 1;
     554           1 :     IndexVector_t volumeDims(dim);
     555           1 :     volumeDims << x, y, z;
     556             : 
     557           1 :     RealVector_t spacing(dim);
     558           1 :     RealVector_t ro(dim);
     559           1 :     RealVector_t rd(dim);
     560             : 
     561           1 :     GIVEN("A 1x1x1 volume with uniform scaling")
     562           1 :     {
     563           1 :         BoundingBox aabb(volumeDims);
     564           1 :         spacing << 1.0, 1.0, 1.0;
     565             : 
     566           1 :         WHEN("The volume is traversed with a ray with origin = (-0.5, 0.5, 0.5) and a direction = "
     567           1 :              "(0, 1, 0)")
     568           1 :         {
     569           1 :             ro << 0.5, -0.5, 0.5;
     570           1 :             rd << 0.0, 1.0, 0.0;
     571             : 
     572           1 :             RealRay_t r(ro, rd);
     573           1 :             TraverseAABB traverse(aabb, r);
     574           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     575             : 
     576           1 :             traverse.updateTraverse();
     577             : 
     578           1 :             THEN("The algorithms left the volume and the voxel it left the box is (0, 1, 0)")
     579           1 :             {
     580           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     581           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     582           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     583           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(2), 0);
     584           1 :             }
     585           1 :         }
     586           1 :     }
     587           1 : }
     588             : 
     589             : TEST_CASE("TraverseAABB: Traverse a 2D volume and only check that the endpoint is correct")
     590           1 : {
     591             :     // setup
     592           1 :     size_t dim = 2;
     593           1 :     index_t x = 10;
     594           1 :     index_t y = 10;
     595           1 :     IndexVector_t volumeDims(dim);
     596           1 :     volumeDims << x, y;
     597             : 
     598           1 :     RealVector_t spacing(dim);
     599           1 :     RealVector_t ro(dim);
     600           1 :     RealVector_t rd(dim);
     601             : 
     602           1 :     GIVEN("A 10x10 volume with uniform scaling")
     603           1 :     {
     604           1 :         BoundingBox aabb(volumeDims);
     605             : 
     606           1 :         WHEN("The volume is traversed with a ray with origin = (-0.5, 0.5, 0.5) and a direction = "
     607           1 :              "(0, 1, 0)")
     608           1 :         {
     609           1 :             ro << -1, 4.5;
     610           1 :             rd << 1.0, 0;
     611             : 
     612           1 :             RealRay_t r(ro, rd);
     613           1 :             TraverseAABB traverse(aabb, r);
     614           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     615             : 
     616          11 :             while (traverse.isInBoundingBox())
     617          10 :                 traverse.updateTraverse();
     618             : 
     619           1 :             THEN("The endpoint should be (10,4)")
     620           1 :             {
     621           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     622           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 10);
     623           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 4);
     624           1 :             }
     625           1 :         }
     626           1 :     }
     627           1 : }
     628             : 
     629             : TEST_CASE("TraverseAABB: Traverse a 3D Volume diagonally")
     630           2 : {
     631             :     // TODO: run through all 4 diagonals
     632             :     // TODO: make a non cube volume and run through all 4 diagonals
     633             :     // TODO: make non uniform scaling and run through all 4 diagonals
     634             : 
     635           2 :     size_t dim = 3;
     636           2 :     IndexVector_t volumeDims(dim);
     637           2 :     volumeDims << 10, 10, 10;
     638             : 
     639           2 :     RealVector_t spacing(dim);
     640           2 :     RealVector_t ro(dim);
     641           2 :     RealVector_t rd(dim);
     642             : 
     643           2 :     GIVEN("A 10x10 volume with uniform scaling")
     644           2 :     {
     645           2 :         BoundingBox aabb(volumeDims);
     646           2 :         WHEN("Start at (-1, -1, -1) (so bottom left front) and run to (10, 10, 10) (so top right "
     647           2 :              "back)")
     648           2 :         {
     649           2 :             ro << -1.0, -1.0, -1.0;
     650           2 :             rd << 1.0, 1.0, 1.0;
     651           2 :             rd.normalize();
     652             : 
     653           2 :             RealRay_t r(ro, rd);
     654             : 
     655           2 :             TraverseAABB traverse(aabb, r);
     656           2 :             CHECK_UNARY(traverse.isInBoundingBox());
     657             : 
     658           2 :             THEN("You entered at (0, 0, 0)")
     659           2 :             {
     660           1 :                 CHECK_EQ(traverse.getCurrentVoxel()(0), 0);
     661           1 :                 CHECK_EQ(traverse.getCurrentVoxel()(1), 0);
     662           1 :                 CHECK_EQ(traverse.getCurrentVoxel()(2), 0);
     663           1 :             }
     664          58 :             while (traverse.isInBoundingBox())
     665          56 :                 traverse.updateTraverse();
     666             : 
     667           2 :             THEN("You leave the volume at (10, 9, 9)")
     668           2 :             {
     669           1 :                 REQUIRE_UNARY_FALSE(traverse.isInBoundingBox());
     670           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 10);
     671           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 9);
     672           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(2), 9);
     673           1 :             }
     674           2 :         }
     675           2 :     }
     676           2 : }
     677             : 
     678             : TEST_CASE("TraverseAABB: Check that the first step into the 2D Volume is correct")
     679           4 : {
     680           4 :     size_t dim = 2;
     681           4 :     index_t x = 5;
     682           4 :     index_t y = 5;
     683           4 :     IndexVector_t volumeDims(dim);
     684           4 :     volumeDims << x, y;
     685             : 
     686           4 :     RealVector_t ro(dim);
     687           4 :     RealVector_t rd(dim);
     688             : 
     689           4 :     GIVEN("A 5x5 volume with uniform scaling")
     690           4 :     {
     691           4 :         BoundingBox aabb(volumeDims);
     692             : 
     693           4 :         WHEN("The ray direction has the biggest value on the y axis")
     694           4 :         {
     695           2 :             ro << 0, 0;
     696           2 :             rd << 0.5f, 0.7f;
     697           2 :             rd.normalize();
     698             : 
     699           2 :             RealRay_t r(ro, rd);
     700           2 :             TraverseAABB traverse(aabb, r);
     701           2 :             CHECK_UNARY(traverse.isInBoundingBox());
     702             : 
     703           2 :             THEN("The traversal is initially at (0, 0)")
     704           2 :             {
     705           1 :                 auto voxel = traverse.getCurrentVoxel();
     706           1 :                 CHECK_EQ(voxel(0), 0);
     707           1 :                 CHECK_EQ(voxel(1), 0);
     708           1 :             }
     709             : 
     710           2 :             traverse.updateTraverse();
     711             : 
     712           2 :             THEN("The first step is in y direction")
     713           2 :             {
     714           1 :                 REQUIRE_UNARY(traverse.isInBoundingBox());
     715           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 0);
     716           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 1);
     717           1 :             }
     718           2 :         }
     719             : 
     720           4 :         WHEN("The ray direction has the biggest value on the x axis")
     721           4 :         {
     722           2 :             ro << 0, 0;
     723           2 :             rd << 0.7f, 0.5f;
     724           2 :             rd.normalize();
     725             : 
     726           2 :             RealRay_t r(ro, rd);
     727           2 :             TraverseAABB traverse(aabb, r);
     728           2 :             CHECK_UNARY(traverse.isInBoundingBox());
     729             : 
     730           2 :             THEN("The traversal is initially at (0, 0)")
     731           2 :             {
     732           1 :                 auto voxel = traverse.getCurrentVoxel();
     733           1 :                 CHECK_EQ(voxel(0), 0);
     734           1 :                 CHECK_EQ(voxel(1), 0);
     735           1 :             }
     736             : 
     737           2 :             traverse.updateTraverse();
     738             : 
     739           2 :             THEN("The first step is in y direction")
     740           2 :             {
     741           1 :                 REQUIRE_UNARY(traverse.isInBoundingBox());
     742           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(0), 1);
     743           1 :                 REQUIRE_EQ(traverse.getCurrentVoxel()(1), 0);
     744           1 :             }
     745           2 :         }
     746           4 :     }
     747           4 : }
     748             : 
     749             : TEST_CASE("TraverseAABB: Traverse_Volume_2D_EachPointIsTested")
     750           1 : {
     751             :     // setup
     752           1 :     size_t dim = 2;
     753           1 :     index_t x = 128;
     754           1 :     index_t y = 128;
     755           1 :     IndexVector_t volumeDims(dim);
     756           1 :     volumeDims << x, y;
     757           1 :     BoundingBox aabb(volumeDims);
     758             : 
     759           1 :     RealVector_t ro(dim);
     760           1 :     ro << -168.274f, -143.397f;
     761           1 :     RealVector_t rd(dim);
     762           1 :     rd << 0.761124909f, 0.648605406f;
     763           1 :     rd.normalize();
     764           1 :     RealRay_t r(ro, rd);
     765             : 
     766           1 :     TraverseAABB traverse(aabb, r);
     767           1 :     CHECK_UNARY(traverse.isInBoundingBox());
     768             : 
     769           1 :     size_t iter = 0;
     770         238 :     while (traverse.isInBoundingBox()) {
     771         237 :         RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     772         237 :         INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     773             : 
     774         237 :         REQUIRE_UNARY(intersect(voxel, r));
     775         237 :         traverse.updateTraverse();
     776         237 :         iter++;
     777         237 :     }
     778           1 : }
     779             : 
     780             : TEST_CASE("TraverseAABB: Traversal through 2D volume should be equal to a ray voxel intersection "
     781             :           "for every voxel along the way")
     782           8 : {
     783             :     // TODO make this a stronger test, for first some "easy" direction (parallel ones)
     784             :     // TODO Then make some harder ones
     785             :     // setup
     786           8 :     size_t dim = 2;
     787           8 :     index_t x = 128;
     788           8 :     index_t y = 128;
     789           8 :     IndexVector_t volumeDims(dim);
     790           8 :     volumeDims << x, y;
     791           8 :     BoundingBox aabb(volumeDims);
     792             : 
     793           8 :     RealVector_t ro(dim);
     794           8 :     RealVector_t rd(dim);
     795             : 
     796           8 :     GIVEN("a point at the bottom left of the volume and a ray with leading dimension x")
     797           8 :     {
     798           1 :         ro << -168.274f, -143.397f;
     799             : 
     800           1 :         rd << 0.761124909f, 0.648605406f;
     801           1 :         rd.normalize();
     802             : 
     803           1 :         RealRay_t r(ro, rd);
     804             : 
     805           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     806           1 :         {
     807           1 :             TraverseAABB traverse(aabb, r);
     808           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     809             : 
     810           1 :             size_t iter = 0;
     811         238 :             while (traverse.isInBoundingBox()) {
     812         237 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     813         237 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     814             : 
     815         237 :                 REQUIRE_UNARY(intersect(voxel, r));
     816         237 :                 traverse.updateTraverse();
     817         237 :                 iter++;
     818         237 :             }
     819           1 :         }
     820           1 :     }
     821             : 
     822           8 :     GIVEN("a point at the bottom left of the volume and a ray with leading dimension y")
     823           8 :     {
     824           1 :         ro << 0, 0;
     825             : 
     826           1 :         rd << 0.648605406f, 0.761124909f;
     827           1 :         rd.normalize();
     828             : 
     829           1 :         RealRay_t r(ro, rd);
     830             : 
     831           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     832           1 :         {
     833           1 :             TraverseAABB traverse(aabb, r);
     834           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     835             : 
     836           1 :             size_t iter = 0;
     837         238 :             while (traverse.isInBoundingBox()) {
     838         237 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     839         237 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     840             : 
     841         237 :                 REQUIRE_UNARY(intersect(voxel, r));
     842         237 :                 traverse.updateTraverse();
     843         237 :                 iter++;
     844         237 :             }
     845           1 :         }
     846           1 :     }
     847             : 
     848           8 :     GIVEN("a ray going through the border of voxel column 0 and 1")
     849           8 :     {
     850           1 :         ro << 1, -0.5f;
     851             : 
     852           1 :         rd << 0, 1;
     853           1 :         rd.normalize();
     854             : 
     855           1 :         RealRay_t r(ro, rd);
     856             : 
     857           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     858           1 :         {
     859           1 :             TraverseAABB traverse(aabb, r);
     860           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     861             : 
     862           1 :             size_t iter = 0;
     863         129 :             while (traverse.isInBoundingBox()) {
     864         128 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     865         128 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     866             : 
     867         128 :                 REQUIRE_UNARY(intersect(voxel, r));
     868         128 :                 traverse.updateTraverse();
     869         128 :                 iter++;
     870         128 :             }
     871           1 :         }
     872           1 :     }
     873             : 
     874           8 :     GIVEN("a ray going through the border of voxel row 0 and 1")
     875           8 :     {
     876           1 :         ro << -0.5f, 1;
     877             : 
     878           1 :         rd << 1, 0;
     879           1 :         rd.normalize();
     880             : 
     881           1 :         RealRay_t r(ro, rd);
     882             : 
     883           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     884           1 :         {
     885           1 :             TraverseAABB traverse(aabb, r);
     886           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     887             : 
     888           1 :             size_t iter = 0;
     889         129 :             while (traverse.isInBoundingBox()) {
     890         128 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     891         128 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     892             : 
     893         128 :                 REQUIRE_UNARY(intersect(voxel, r));
     894         128 :                 traverse.updateTraverse();
     895         128 :                 iter++;
     896         128 :             }
     897           1 :         }
     898           1 :     }
     899             : 
     900           8 :     GIVEN("A ray going diagonally through the volume")
     901           8 :     {
     902           1 :         ro << -0.5f, -0.5f;
     903             : 
     904           1 :         rd << 1, 1;
     905           1 :         rd.normalize();
     906             : 
     907           1 :         RealRay_t r(ro, rd);
     908             : 
     909           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     910           1 :         {
     911           1 :             TraverseAABB traverse(aabb, r);
     912           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     913             : 
     914           1 :             size_t iter = 0;
     915         256 :             while (traverse.isInBoundingBox()) {
     916         255 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     917         255 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     918             : 
     919         255 :                 REQUIRE_UNARY(intersect(voxel, r));
     920         255 :                 traverse.updateTraverse();
     921         255 :                 iter++;
     922         255 :             }
     923           1 :         }
     924           1 :     }
     925             : 
     926           8 :     GIVEN("A ray going diagonally through the volume")
     927           8 :     {
     928           1 :         ro << -0.5f, 32;
     929             : 
     930           1 :         rd << 1, 1;
     931           1 :         rd.normalize();
     932             : 
     933           1 :         RealRay_t r(ro, rd);
     934             : 
     935           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     936           1 :         {
     937           1 :             TraverseAABB traverse(aabb, r);
     938           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     939             : 
     940           1 :             size_t iter = 0;
     941         192 :             while (traverse.isInBoundingBox()) {
     942         191 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     943         191 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     944             : 
     945         191 :                 REQUIRE_UNARY(intersect(voxel, r));
     946         191 :                 traverse.updateTraverse();
     947         191 :                 iter++;
     948         191 :             }
     949           1 :         }
     950           1 :     }
     951             : 
     952           8 :     GIVEN("A ray going diagonally through the volume")
     953           8 :     {
     954           1 :         ro << -0.5f, -0.5f;
     955             : 
     956           1 :         rd << 0.699428f, 0.472203f;
     957           1 :         rd.normalize();
     958             : 
     959           1 :         RealRay_t r(ro, rd);
     960             : 
     961           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     962           1 :         {
     963           1 :             TraverseAABB traverse(aabb, r);
     964           1 :             CHECK_UNARY(traverse.isInBoundingBox());
     965             : 
     966           1 :             size_t iter = 0;
     967         215 :             while (traverse.isInBoundingBox()) {
     968         214 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     969         214 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     970             : 
     971         214 :                 REQUIRE_UNARY(intersect(voxel, r));
     972         214 :                 traverse.updateTraverse();
     973         214 :                 iter++;
     974         214 :             }
     975           1 :         }
     976           1 :     }
     977             : 
     978           8 :     GIVEN("A ray going diagonally through the volume")
     979           8 :     {
     980           1 :         volumeDims << 64, 64;
     981           1 :         BoundingBox aabb(volumeDims);
     982             : 
     983           1 :         ro << 32.0002823f, 3232;
     984             : 
     985           1 :         rd << -0.000723466626f, -0.999999762f;
     986           1 :         rd.normalize();
     987             : 
     988           1 :         RealRay_t r(ro, rd);
     989             : 
     990           1 :         THEN("Then all points the traversal visits are also hit by the intersection algorithm")
     991           1 :         {
     992           1 :             TraverseAABB traverse(aabb, r);
     993           1 :             traverse.isInBoundingBox();
     994             : 
     995           1 :             size_t iter = 0;
     996          65 :             while (traverse.isInBoundingBox()) {
     997          64 :                 RealVector_t voxel = traverse.getCurrentVoxel().template cast<real_t>();
     998          64 :                 INFO("Current Voxel: (" << voxel(0) << ", " << voxel(1) << ") in iter: " << iter);
     999             : 
    1000          64 :                 REQUIRE_UNARY(intersect(voxel, r));
    1001          64 :                 traverse.updateTraverse();
    1002          64 :                 iter++;
    1003          64 :             }
    1004           1 :         }
    1005           1 :     }
    1006           8 : }

Generated by: LCOV version 1.14