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

          Line data    Source code
       1             : /**
       2             :  * @file test_Intersection.cpp
       3             :  *
       4             :  * @brief Test for Intersection class
       5             :  *
       6             :  * @author David Frank - initial code
       7             :  * @author Maximilian Hornung - modularization
       8             :  * @author Tobias Lasser - consistency changes
       9             :  */
      10             : 
      11             : #include "doctest/doctest.h"
      12             : 
      13             : #include "Intersection.h"
      14             : 
      15             : using namespace elsa;
      16             : using namespace doctest;
      17             : 
      18             : #include "PrettyPrint/Stl.h"
      19             : #include "PrettyPrint/Eigen.h"
      20             : 
      21             : TEST_CASE("Intersection: Intersect corners of pixels")
      22           1 : {
      23           1 :     size_t dim = 2;
      24             : 
      25           1 :     IndexVector_t voxel(dim);
      26           1 :     voxel << 1, 0;
      27           1 :     BoundingBox aabb(voxel);
      28             : 
      29             :     // top left corner
      30           1 :     RealVector_t ro(dim);
      31           1 :     ro << -3, -3;
      32           1 :     RealVector_t rd(dim);
      33           1 :     rd << 1.0, 1.0;
      34           1 :     rd.normalize();
      35           1 :     RealRay_t r(ro, rd);
      36             : 
      37           1 :     REQUIRE_UNARY(intersectRay(aabb, r));
      38             : 
      39             :     // top right corner
      40           1 :     ro << 1, 2;
      41           1 :     rd << 1.0, -1.0;
      42           1 :     rd.normalize();
      43           1 :     r = RealRay_t(ro, rd);
      44             : 
      45           1 :     REQUIRE_UNARY_FALSE(intersectRay(aabb, r));
      46             : 
      47             :     // bottom left corner
      48           1 :     ro << 3, -2;
      49           1 :     rd << -1.0, 1.0;
      50           1 :     rd.normalize();
      51           1 :     r = RealRay_t(ro, rd);
      52             : 
      53           1 :     REQUIRE_UNARY(intersectRay(aabb, r));
      54             : 
      55             :     // bottom right corner
      56           1 :     ro << 3, 1;
      57           1 :     rd << -1.0, -1.0;
      58           1 :     rd.normalize();
      59           1 :     r = RealRay_t(ro, rd);
      60             : 
      61           1 :     REQUIRE_UNARY_FALSE(intersectRay(aabb, r));
      62           1 : }
      63             : 
      64             : TEST_CASE("Intersection: Intersect edges of voxels")
      65           9 : {
      66           9 :     GIVEN("A ray which intersects the edge of a voxel")
      67           9 :     {
      68           9 :         size_t dim = 2;
      69           9 :         RealVector_t ro(dim);
      70           9 :         ro << 132, 30;
      71           9 :         RealVector_t rd(dim);
      72           9 :         rd << -1.0, 0;
      73           9 :         RealRay_t r(ro, rd);
      74             : 
      75           9 :         IndexVector_t voxel(dim);
      76             : 
      77             :         // horizontal check
      78           9 :         voxel << 30, 31;
      79           9 :         THEN("the ray intersects")
      80           9 :         {
      81           1 :             BoundingBox aabb(voxel);
      82           1 :             REQUIRE_UNARY(intersectRay(aabb, r));
      83           1 :         }
      84             : 
      85           9 :         voxel << 40, 30;
      86           9 :         THEN("the ray intersects")
      87           9 :         {
      88           1 :             BoundingBox aabb(voxel);
      89           1 :             REQUIRE_UNARY(intersectRay(aabb, r));
      90           1 :         }
      91             : 
      92           9 :         voxel << 40, 29;
      93           9 :         THEN("the ray does not intersect")
      94           9 :         {
      95           1 :             BoundingBox aabb(voxel);
      96           1 :             REQUIRE_UNARY_FALSE(intersectRay(aabb, r));
      97           1 :         }
      98             : 
      99             :         // vertical check
     100           9 :         ro << 30, -35;
     101           9 :         rd << 0, 1.0;
     102           9 :         r = RealRay_t(ro, rd);
     103             : 
     104           9 :         voxel << 31, 30;
     105           9 :         THEN("the ray intersects")
     106           9 :         {
     107           1 :             BoundingBox aabb(voxel);
     108           1 :             REQUIRE_UNARY(intersectRay(aabb, r));
     109           1 :         }
     110             : 
     111           9 :         voxel << 30, 40;
     112           9 :         THEN("the ray intersects")
     113           9 :         {
     114           1 :             BoundingBox aabb(voxel);
     115           1 :             REQUIRE_UNARY(intersectRay(aabb, r));
     116           1 :         }
     117             : 
     118           9 :         voxel << 29, 40;
     119           9 :         THEN("the ray does not intersect")
     120           9 :         {
     121           1 :             BoundingBox aabb(voxel);
     122           1 :             REQUIRE_UNARY_FALSE(intersectRay(aabb, r));
     123           1 :         }
     124             : 
     125           9 :         rd << 0.0, 1.0;
     126           9 :         ro << 1.5, -10;
     127           9 :         r = RealRay_t(ro, rd);
     128             : 
     129           9 :         voxel << 0, 1;
     130           9 :         THEN("the ray does not intersect")
     131           9 :         {
     132           1 :             BoundingBox aabb(voxel);
     133           1 :             REQUIRE_UNARY_FALSE(intersectRay(aabb, r));
     134           1 :         }
     135             : 
     136           9 :         voxel << 1, 1;
     137           9 :         THEN("the ray does not intersect")
     138           9 :         {
     139           1 :             BoundingBox aabb(voxel);
     140           1 :             REQUIRE_UNARY_FALSE(intersectRay(aabb, r));
     141           1 :         }
     142             : 
     143           9 :         voxel << 2, 1;
     144           9 :         THEN("the ray intersects")
     145           9 :         {
     146           1 :             BoundingBox aabb(voxel);
     147           1 :             REQUIRE_UNARY(intersectRay(aabb, r));
     148           1 :         }
     149           9 :     }
     150           9 : }
     151             : 
     152             : TEST_SUITE_BEGIN("Intersection::voxelCenter");
     153             : 
     154             : Eigen::IOFormat vecfmt(8, 0, ", ", ", ", "", "", "[", "]");
     155             : 
     156             : TEST_CASE("Intersection: Ray with voxel center")
     157           6 : {
     158           6 :     IndexVector_t upperbound({{5, 5}});
     159           6 :     BoundingBox aabb(upperbound);
     160             : 
     161           6 :     GIVEN("Ray entering the bottom of the volume")
     162           6 :     {
     163             :         // Check multiple different rays all coming from the bottom
     164           3 :         auto steps = 30;
     165          96 :         for (int i = 0; i <= steps; ++i) {
     166          93 :             auto inc = (1.f / static_cast<float>(steps)) * static_cast<float>(i);
     167          93 :             auto dirinc = static_cast<float>(i) / (2 * static_cast<float>(steps));
     168             : 
     169          93 :             RealVector_t origin({{0.75f + inc, 0}});
     170          93 :             RealVector_t dir({{1, 0.5f + dirinc}});
     171          93 :             dir.normalize();
     172             : 
     173          93 :             CAPTURE(inc);
     174          93 :             CAPTURE(origin.format(vecfmt));
     175          93 :             CAPTURE(dir.format(vecfmt));
     176             : 
     177          93 :             RealRay_t ray(origin, dir);
     178             : 
     179          93 :             auto hit = intersectXPlanes(aabb, ray);
     180             : 
     181          93 :             CAPTURE(hit);
     182          93 :             REQUIRE(hit);
     183             : 
     184          93 :             THEN("entries x-coord lies in the middle of a voxel")
     185          93 :             {
     186           1 :                 RealVector_t enter = ray.pointAt(hit->_tmin);
     187           1 :                 CAPTURE(enter.format(vecfmt));
     188             : 
     189           1 :                 real_t trash = 0;
     190           1 :                 CHECK_EQ(0.5, doctest::Approx(std::modf(enter[0], &trash)));
     191             : 
     192           1 :                 CHECK((enter.array() < upperbound.template cast<real_t>().array()).all());
     193           1 :                 CHECK((enter.array() > 0).all());
     194           1 :             }
     195             : 
     196          93 :             THEN("x-coord lies in the middle of a voxel")
     197          93 :             {
     198           1 :                 RealVector_t leave = ray.pointAt(hit->_tmax);
     199           1 :                 CAPTURE(leave.format(vecfmt));
     200             : 
     201           1 :                 real_t trash = 0;
     202           1 :                 CHECK_EQ(0.5, doctest::Approx(std::modf(leave[0], &trash)));
     203             : 
     204           1 :                 CHECK((leave.array() < upperbound.template cast<real_t>().array()).all());
     205           1 :                 CHECK((leave.array() > 0).all());
     206           1 :             }
     207          93 :         }
     208           3 :     }
     209             : 
     210           6 :     GIVEN("Ray entering the top of the volume")
     211           6 :     {
     212             :         // Check multiple different rays all coming from the top
     213           3 :         auto steps = 30;
     214          96 :         for (int i = 0; i <= steps; ++i) {
     215          93 :             auto inc = (1.f / static_cast<float>(steps)) * static_cast<float>(i);
     216          93 :             auto dirinc = static_cast<float>(i) / (2 * static_cast<float>(steps));
     217             : 
     218          93 :             RealVector_t origin({{0.75f + inc, 6}});
     219          93 :             RealVector_t dir({{1, -0.5f - dirinc}});
     220          93 :             dir.normalize();
     221             : 
     222          93 :             CAPTURE(inc);
     223          93 :             CAPTURE(origin.format(vecfmt));
     224          93 :             CAPTURE(dir.format(vecfmt));
     225             : 
     226          93 :             RealRay_t ray(origin, dir);
     227             : 
     228          93 :             auto hit = intersectXPlanes(aabb, ray);
     229             : 
     230          93 :             CAPTURE(hit);
     231          93 :             REQUIRE(hit);
     232             : 
     233          93 :             THEN("entries x-coord lies in the middle of a voxel")
     234          93 :             {
     235           1 :                 RealVector_t enter = ray.pointAt(hit->_tmin);
     236           1 :                 CAPTURE(enter.format(vecfmt));
     237             : 
     238           1 :                 real_t trash = 0;
     239           1 :                 CHECK_EQ(0.5, doctest::Approx(std::modf(enter[0], &trash)));
     240             : 
     241           1 :                 CHECK((enter.array() < upperbound.template cast<real_t>().array()).all());
     242           1 :                 CHECK((enter.array() > 0).all());
     243           1 :             }
     244             : 
     245          93 :             THEN("x-coord lies in the middle of a voxel")
     246          93 :             {
     247           1 :                 RealVector_t leave = ray.pointAt(hit->_tmax);
     248           1 :                 CAPTURE(leave.format(vecfmt));
     249             : 
     250           1 :                 real_t trash = 0;
     251           1 :                 CHECK_EQ(0.5, doctest::Approx(std::modf(leave[0], &trash)));
     252             : 
     253           1 :                 CHECK((leave.array() < upperbound.template cast<real_t>().array()).all());
     254           1 :                 CHECK((leave.array() > 0).all());
     255           1 :             }
     256          93 :         }
     257           3 :     }
     258           6 : }
     259             : 
     260             : TEST_CASE("Intersection: Quick bug tests")
     261           2 : {
     262           2 :     const IndexVector_t size({{3, 3}});
     263             : 
     264           2 :     BoundingBox aabb(size);
     265           2 :     aabb.min() = RealVector_t({{-1.5f, -1.5f}});
     266           2 :     aabb.max() = RealVector_t({{1.5f, 1.5f}});
     267             : 
     268           2 :     const RealVector_t ro({{-2, -3}});
     269           2 :     RealVector_t rd({{1, 1}});
     270           2 :     rd.normalize();
     271           2 :     const RealRay_t ray(ro, rd);
     272             : 
     273           2 :     auto hit = intersectXPlanes(aabb, ray);
     274             : 
     275           2 :     CAPTURE(hit);
     276           2 :     REQUIRE(hit);
     277             : 
     278           2 :     auto dist_to_integer = [&](auto f) {
     279           2 :         real_t aabbmin = static_cast<int>(std::round(f));
     280           2 :         auto frac = std::abs(f - aabbmin);
     281           2 :         return frac;
     282           2 :     };
     283             : 
     284           2 :     THEN("entries x-coord lies in the middle of a voxel")
     285           2 :     {
     286           1 :         RealVector_t entry = ray.pointAt(hit->_tmin);
     287           1 :         CAPTURE(entry.format(vecfmt));
     288             : 
     289             :         // real_t trash = 0;
     290           1 :         CHECK_EQ(0, doctest::Approx(dist_to_integer(entry[0])));
     291             : 
     292           1 :         CHECK((entry.array() < 1.5).all());
     293           1 :         CHECK((entry.array() > -1.5).all());
     294           1 :     }
     295             : 
     296           2 :     THEN("x-coord lies in the middle of a voxel")
     297           2 :     {
     298           1 :         RealVector_t leave = ray.pointAt(hit->_tmax);
     299           1 :         CAPTURE(leave.format(vecfmt));
     300             : 
     301             :         // real_t trash = 0;
     302             :         // CHECK_EQ(0, doctest::Approx(std::modf(leave[0], &trash)));
     303           1 :         CHECK_EQ(0, doctest::Approx(dist_to_integer(leave[0])));
     304             : 
     305           1 :         CHECK((leave.array() < 1.5).all());
     306           1 :         CHECK((leave.array() > -1.5).all());
     307           1 :     }
     308           2 : }
     309             : 
     310             : TEST_CASE("Intersection: Quick bug tests")
     311           2 : {
     312           2 :     const IndexVector_t size({{3, 3}});
     313             : 
     314           2 :     BoundingBox aabb(size);
     315           2 :     aabb.min() = RealVector_t({{-1.5f, -1.5f}});
     316           2 :     aabb.max() = RealVector_t({{1.5f, 1.5f}});
     317             : 
     318           2 :     const RealVector_t ro({{-2, -3}});
     319           2 :     RealVector_t rd({{1, 1}});
     320           2 :     rd.normalize();
     321           2 :     const RealRay_t ray(ro, rd);
     322             : 
     323           2 :     auto hit = intersectXPlanes(aabb, ray);
     324             : 
     325           2 :     CAPTURE(hit);
     326           2 :     REQUIRE(hit);
     327             : 
     328           2 :     auto dist_to_integer = [&](auto f) {
     329           2 :         real_t aabbmin = static_cast<int>(std::round(f));
     330           2 :         auto frac = std::abs(f - aabbmin);
     331           2 :         return frac;
     332           2 :     };
     333             : 
     334           2 :     THEN("entries x-coord lies in the middle of a voxel")
     335           2 :     {
     336           1 :         RealVector_t entry = ray.pointAt(hit->_tmin);
     337           1 :         CAPTURE(entry.format(vecfmt));
     338             : 
     339             :         // real_t trash = 0;
     340           1 :         CHECK_EQ(0, doctest::Approx(dist_to_integer(entry[0])));
     341             : 
     342           1 :         CHECK((entry.array() < 1.5).all());
     343           1 :         CHECK((entry.array() > -1.5).all());
     344           1 :     }
     345             : 
     346           2 :     THEN("x-coord lies in the middle of a voxel")
     347           2 :     {
     348           1 :         RealVector_t leave = ray.pointAt(hit->_tmax);
     349           1 :         CAPTURE(leave.format(vecfmt));
     350             : 
     351             :         // real_t trash = 0;
     352             :         // CHECK_EQ(0, doctest::Approx(std::modf(leave[0], &trash)));
     353           1 :         CHECK_EQ(0, doctest::Approx(dist_to_integer(leave[0])));
     354             : 
     355           1 :         CHECK((leave.array() < 1.5).all());
     356           1 :         CHECK((leave.array() > -1.5).all());
     357           1 :     }
     358           2 : }
     359             : 
     360             : // Redefine GIVEN such that it's nicely usable inside an loop
     361             : #undef GIVEN
     362     6250000 : #define GIVEN(...) DOCTEST_SUBCASE((std::string("   Given: ") + std::string(__VA_ARGS__)).c_str())
     363             : 
     364             : TEST_CASE("Intersection: 3D rays with bounding box")
     365        2500 : {
     366        2500 :     const IndexVector_t upperbound({{5, 5, 5}});
     367        2500 :     const BoundingBox aabb(upperbound);
     368             : 
     369       65000 :     for (int z = 0; z < 25; ++z) {
     370     1625000 :         for (int y = 0; y < 25; ++y) {
     371     1562500 :             const auto zinc = static_cast<real_t>(z) / 5.f;
     372     1562500 :             const auto yinc = static_cast<real_t>(y) / 5.f;
     373     1562500 :             GIVEN("ray starting at (6, " + std::to_string(yinc) + ", " + std::to_string(zinc) + ")")
     374     1562500 :             {
     375        1250 :                 const RealVector_t origin({{-1, yinc, zinc}});
     376        1250 :                 RealVector_t dir({{1, 0, 0}});
     377             : 
     378        1250 :                 CAPTURE(yinc);
     379        1250 :                 CAPTURE(zinc);
     380        1250 :                 CAPTURE(origin.format(vecfmt));
     381        1250 :                 CAPTURE(dir.format(vecfmt));
     382             : 
     383        1250 :                 RealRay_t ray(origin, dir);
     384             : 
     385        1250 :                 auto hit = intersectXPlanes(aabb, ray);
     386             : 
     387        1250 :                 CAPTURE(hit);
     388        1250 :                 REQUIRE(hit);
     389             : 
     390        1250 :                 THEN("entries x-coord lies in the middle of a voxel")
     391        1250 :                 {
     392         625 :                     RealVector_t enter = ray.pointAt(hit->_tmin);
     393         625 :                     CAPTURE(enter.format(vecfmt));
     394             : 
     395         625 :                     real_t trash = 0;
     396         625 :                     CHECK_EQ(0.5, doctest::Approx(std::modf(enter[0], &trash)));
     397             : 
     398         625 :                     CHECK((enter.array() <= upperbound.template cast<real_t>().array()).all());
     399         625 :                     CHECK((enter.array() >= 0).all());
     400         625 :                 }
     401             : 
     402        1250 :                 THEN("x-coord lies in the middle of a voxel")
     403        1250 :                 {
     404         625 :                     RealVector_t leave = ray.pointAt(hit->_tmax);
     405         625 :                     CAPTURE(leave.format(vecfmt));
     406             : 
     407         625 :                     real_t trash = 0;
     408         625 :                     CHECK_EQ(0.5, doctest::Approx(std::modf(leave[0], &trash)));
     409             : 
     410         625 :                     CHECK((leave.array() <= upperbound.template cast<real_t>().array()).all());
     411         625 :                     CHECK((leave.array() >= 0).all());
     412         625 :                 }
     413        1250 :             }
     414     1562500 :         }
     415       62500 :     }
     416             : 
     417       65000 :     for (int z = 0; z < 25; ++z) {
     418     1625000 :         for (int y = 0; y < 25; ++y) {
     419     1562500 :             const auto zinc = static_cast<real_t>(z) / 5.f;
     420     1562500 :             const auto yinc = static_cast<real_t>(y) / 5.f;
     421     1562500 :             GIVEN("ray starting at (6, " + std::to_string(yinc) + ", " + std::to_string(zinc) + ")")
     422     1562500 :             {
     423        1250 :                 const RealVector_t origin({{6, yinc, zinc}});
     424        1250 :                 RealVector_t dir({{-1, 0, 0}});
     425             : 
     426        1250 :                 CAPTURE(yinc);
     427        1250 :                 CAPTURE(zinc);
     428        1250 :                 CAPTURE(origin.format(vecfmt));
     429        1250 :                 CAPTURE(dir.format(vecfmt));
     430             : 
     431        1250 :                 RealRay_t ray(origin, dir);
     432             : 
     433        1250 :                 auto hit = intersectXPlanes(aabb, ray);
     434             : 
     435        1250 :                 CAPTURE(hit);
     436        1250 :                 REQUIRE(hit);
     437             : 
     438        1250 :                 THEN("entries x-coord lies in the middle of a voxel")
     439        1250 :                 {
     440         625 :                     RealVector_t enter = ray.pointAt(hit->_tmin);
     441         625 :                     CAPTURE(enter.format(vecfmt));
     442             : 
     443         625 :                     real_t trash = 0;
     444         625 :                     CHECK_EQ(0.5, doctest::Approx(std::modf(enter[0], &trash)));
     445             : 
     446         625 :                     CHECK((enter.array() <= upperbound.template cast<real_t>().array()).all());
     447         625 :                     CHECK((enter.array() >= 0).all());
     448         625 :                 }
     449             : 
     450        1250 :                 THEN("x-coord lies in the middle of a voxel")
     451        1250 :                 {
     452         625 :                     RealVector_t leave = ray.pointAt(hit->_tmax);
     453         625 :                     CAPTURE(leave.format(vecfmt));
     454             : 
     455         625 :                     real_t trash = 0;
     456         625 :                     CHECK_EQ(0.5, doctest::Approx(std::modf(leave[0], &trash)));
     457             : 
     458         625 :                     CHECK((leave.array() <= upperbound.template cast<real_t>().array()).all());
     459         625 :                     CHECK((leave.array() >= 0).all());
     460         625 :                 }
     461        1250 :             }
     462     1562500 :         }
     463       62500 :     }
     464        2500 : }
     465             : 
     466             : TEST_CASE("Intersection: 3D rays with bounding box")
     467        2500 : {
     468        2500 :     const IndexVector_t upperbound({{5, 5, 5}});
     469        2500 :     BoundingBox aabb(upperbound);
     470        2500 :     aabb.min() = RealVector_t({{-2.5f, -2.5f, -2.5f}});
     471        2500 :     aabb.max() = RealVector_t({{2.5f, 2.5f, 2.5f}});
     472             : 
     473       65000 :     for (int z = 0; z < 25; ++z) {
     474     1625000 :         for (int y = 0; y < 25; ++y) {
     475     1562500 :             const auto zinc = static_cast<real_t>(z) / 5.f - 2.5f;
     476     1562500 :             const auto yinc = static_cast<real_t>(y) / 5.f - 2.5f;
     477             : 
     478     1562500 :             GIVEN("ray starting at (6, " + std::to_string(yinc) + ", " + std::to_string(zinc) + ")")
     479     1562500 :             {
     480        1250 :                 const RealVector_t origin({{-5, yinc, zinc}});
     481        1250 :                 RealVector_t dir({{1, 0, 0}});
     482             : 
     483        1250 :                 CAPTURE(yinc);
     484        1250 :                 CAPTURE(zinc);
     485        1250 :                 CAPTURE(origin.format(vecfmt));
     486        1250 :                 CAPTURE(dir.format(vecfmt));
     487             : 
     488        1250 :                 RealRay_t ray(origin, dir);
     489             : 
     490        1250 :                 auto hit = intersectXPlanes(aabb, ray);
     491             : 
     492        1250 :                 CAPTURE(hit);
     493        1250 :                 REQUIRE(hit);
     494             : 
     495        1250 :                 THEN("entries x-coord lies in the middle of a voxel")
     496        1250 :                 {
     497         625 :                     RealVector_t enter = ray.pointAt(hit->_tmin);
     498         625 :                     CAPTURE(enter.format(vecfmt));
     499             : 
     500         625 :                     CHECK_EQ(-2, doctest::Approx(enter[0]));
     501             : 
     502         625 :                     CHECK((enter.array() <= 2.5).all());
     503         625 :                     CHECK((enter.array() >= -2.5).all());
     504         625 :                 }
     505             : 
     506        1250 :                 THEN("x-coord lies in the middle of a voxel")
     507        1250 :                 {
     508         625 :                     RealVector_t leave = ray.pointAt(hit->_tmax);
     509         625 :                     CAPTURE(leave.format(vecfmt));
     510             : 
     511         625 :                     CHECK_EQ(2, doctest::Approx(leave[0]));
     512             : 
     513         625 :                     CHECK((leave.array() <= 2.5).all());
     514         625 :                     CHECK((leave.array() >= -2.5).all());
     515         625 :                 }
     516        1250 :             }
     517             : 
     518     1562500 :             GIVEN("ray starting at (6, " + std::to_string(yinc) + ", " + std::to_string(zinc) + ")")
     519     1562500 :             {
     520        1250 :                 const RealVector_t origin({{6, yinc, zinc}});
     521        1250 :                 RealVector_t dir({{-1, 0, 0}});
     522             : 
     523        1250 :                 CAPTURE(yinc);
     524        1250 :                 CAPTURE(zinc);
     525        1250 :                 CAPTURE(origin.format(vecfmt));
     526        1250 :                 CAPTURE(dir.format(vecfmt));
     527             : 
     528        1250 :                 RealRay_t ray(origin, dir);
     529             : 
     530        1250 :                 auto hit = intersectXPlanes(aabb, ray);
     531             : 
     532        1250 :                 CAPTURE(hit);
     533        1250 :                 REQUIRE(hit);
     534             : 
     535        1250 :                 THEN("entries x-coord lies in the middle of a voxel")
     536        1250 :                 {
     537         625 :                     RealVector_t enter = ray.pointAt(hit->_tmin);
     538         625 :                     CAPTURE(enter.format(vecfmt));
     539             : 
     540         625 :                     CHECK_EQ(2, doctest::Approx(enter[0]));
     541             : 
     542         625 :                     CHECK((enter.array() <= 2.5).all());
     543         625 :                     CHECK((enter.array() >= -2.5).all());
     544         625 :                 }
     545             : 
     546        1250 :                 THEN("x-coord lies in the middle of a voxel")
     547        1250 :                 {
     548         625 :                     RealVector_t leave = ray.pointAt(hit->_tmax);
     549         625 :                     CAPTURE(leave.format(vecfmt));
     550             : 
     551         625 :                     CHECK_EQ(-2, doctest::Approx(leave[0]));
     552             : 
     553         625 :                     CHECK((leave.array() <= 2.5).all());
     554         625 :                     CHECK((leave.array() >= -2.5).all());
     555         625 :                 }
     556        1250 :             }
     557     1562500 :         }
     558       62500 :     }
     559        2500 : }
     560             : 
     561             : TEST_SUITE_END();

Generated by: LCOV version 1.14