LCOV - code coverage report
Current view: top level - elsa/projectors - TraverseAABB.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 92 92 100.0 %
Date: 2024-12-21 07:37:52 Functions: 30 30 100.0 %

          Line data    Source code
       1             : #include "TraverseAABB.h"
       2             : #include "Intersection.h"
       3             : 
       4             : namespace elsa
       5             : {
       6             :     template <int dim>
       7             :     TraverseAABB<dim>::TraverseAABB(const BoundingBox& aabb, const RealRay_t& r,
       8             :                                     IndexArray_t<dim> productOfCoefficientsPerDimension)
       9             :         : _productOfCoefficientsPerDimension{std::move(productOfCoefficientsPerDimension)}
      10       61901 :     {
      11       61901 :         static_assert(dim == 2 || dim == 3);
      12       61901 :         _aabbMin = aabb.min();
      13       61901 :         _aabbMax = aabb.max();
      14             : 
      15             :         // compute the first intersection
      16       61901 :         const RealArray_t<dim> entryPoint = calculateAABBIntersections(r, aabb);
      17       61901 :         if (!isInBoundingBox()) // early abort if necessary
      18        5861 :             return;
      19             : 
      20             :         // constant array containing epsilon
      21       56040 :         const RealArray_t<dim> EPS{
      22       56040 :             RealArray_t<dim>().setConstant(std::numeric_limits<real_t>::epsilon())};
      23             : 
      24             :         // constant vector containing the maximum number
      25       56040 :         const RealArray_t<dim> MAX{
      26       56040 :             RealArray_t<dim>().setConstant(std::numeric_limits<real_t>::max())};
      27             : 
      28             :         // determine whether we go up/down or left/right
      29       56040 :         initStepDirection(r.direction());
      30             : 
      31             :         // select the initial voxel (closest to the entry point)
      32       56040 :         selectClosestVoxel(entryPoint);
      33             : 
      34             :         // initialize the step sizes for the step parameter
      35       56040 :         initDelta(r.direction(), EPS, MAX);
      36             : 
      37             :         // initialize the maximum step parameters
      38       56040 :         initT(r.direction(), EPS, MAX, entryPoint);
      39       56040 :         initCurrentIndex();
      40       56040 :     }
      41             : 
      42             :     template <int dim>
      43             :     void TraverseAABB<dim>::updateTraverse()
      44     2174542 :     {
      45             :         // --> calculate the mask that masks out all but the lowest t values
      46     2174542 :         calcMask();
      47             : 
      48             :         // --> step into the current direction
      49     2174542 :         _currentPos += _mask.select(_stepDirection.template cast<real_t>(), 0);
      50             : 
      51             :         // --> update the T for next iteration
      52     2174542 :         _T += _mask.select(_tDelta, 0);
      53             : 
      54             :         // --> check if we are still in bounding box
      55     2174542 :         _isInAABB = isCurrentPositionInAABB();
      56     2174542 :     }
      57             : 
      58             :     template <int dim>
      59             :     void TraverseAABB<dim>::calcMask()
      60     2073255 :     {
      61     2073255 :         if constexpr (dim == 2) {
      62       63225 :             _mask[0] = (_T[0] <= _T[1]);
      63       63225 :             _mask[1] = (_T[1] <= _T[0]);
      64       63225 :         } else if constexpr (dim == 3) {
      65       63009 :             _mask[0] = ((_T[0] <= _T[1]) && (_T[0] <= _T[2]));
      66       63009 :             _mask[1] = ((_T[1] <= _T[0]) && (_T[1] <= _T[2]));
      67       63009 :             _mask[2] = ((_T[2] <= _T[0]) && (_T[2] <= _T[1]));
      68       63009 :         }
      69     2073255 :     }
      70             : 
      71             :     template <int dim>
      72             :     real_t TraverseAABB<dim>::updateTraverseAndGetDistance()
      73     1709034 :     {
      74             :         // --> compute the distance
      75     1709034 :         real_t tEntry = _tExit;
      76     1709034 :         _tExit = _T.minCoeff();
      77             : 
      78             :         // --> do the update
      79     1709034 :         updateTraverse();
      80     1709034 :         updateCurrentIndex();
      81             : 
      82     1709034 :         return (_tExit - tEntry);
      83     1709034 :     }
      84             : 
      85             :     template <int dim>
      86             :     bool TraverseAABB<dim>::isInBoundingBox() const
      87     2402903 :     {
      88     2402903 :         return _isInAABB;
      89     2402903 :     }
      90             : 
      91             :     template <int dim>
      92             :     IndexArray_t<dim> TraverseAABB<dim>::getCurrentVoxel() const
      93      598505 :     {
      94      598505 :         return _currentPos.template cast<index_t>();
      95      598505 :     }
      96             : 
      97             :     template <int dim>
      98             :     index_t TraverseAABB<dim>::getCurrentIndex() const
      99     1850541 :     {
     100     1850541 :         return _currentIndex;
     101     1850541 :     }
     102             : 
     103             :     template <int dim>
     104             :     RealArray_t<dim> TraverseAABB<dim>::calculateAABBIntersections(const RealRay_t& r,
     105             :                                                                    const BoundingBox& aabb)
     106       61778 :     {
     107       61778 :         RealArray_t<dim> entryPoint;
     108             :         // entry and exit point parameters
     109       61778 :         real_t tmin;
     110             : 
     111             :         // --> calculate intersection parameter and if the volume is hit
     112       61778 :         auto opt = intersectRay(aabb, r);
     113             : 
     114       61778 :         if (opt) { // hit!
     115       56524 :             _isInAABB = true;
     116       56524 :             tmin = opt->_tmin;
     117             : 
     118             :             // --> get points at which they intersect
     119       56524 :             entryPoint = r.pointAt(tmin);
     120             : 
     121             :             // --> because of floating point error it can happen, that values are out of
     122             :             // the bounding box, this can lead to errors
     123       56524 :             entryPoint = (entryPoint < _aabbMin).select(_aabbMin, entryPoint);
     124       56524 :             entryPoint = (entryPoint > _aabbMax).select(_aabbMax, entryPoint);
     125       56524 :         }
     126       61778 :         return entryPoint;
     127       61778 :     }
     128             : 
     129             :     template <int dim>
     130             :     void TraverseAABB<dim>::initStepDirection(const RealArray_t<dim>& rd)
     131       56147 :     {
     132       56147 :         _stepDirection = rd.sign().template cast<index_t>();
     133       56147 :     }
     134             : 
     135             :     template <int dim>
     136             :     void TraverseAABB<dim>::selectClosestVoxel(const RealArray_t<dim>& entryPoint)
     137       56223 :     {
     138       56223 :         RealArray_t<dim> lowerCorner = entryPoint.floor();
     139       56223 :         lowerCorner = ((lowerCorner == entryPoint) && (_stepDirection < 0.0))
     140       56223 :                           .select(lowerCorner - 1, lowerCorner);
     141             : 
     142       56223 :         _currentPos = lowerCorner;
     143             : 
     144             :         // check if we are still inside the aabb
     145       56312 :         if ((_currentPos >= _aabbMax).any() || (_currentPos < _aabbMin).any())
     146          12 :             _isInAABB = false;
     147       56223 :     }
     148             : 
     149             :     template <int dim>
     150             :     void TraverseAABB<dim>::initDelta(const RealArray_t<dim>& rd, const RealArray_t<dim>& EPS,
     151             :                                       const RealArray_t<dim>& MAX)
     152       56178 :     {
     153       56178 :         RealArray_t<dim> tdelta = _stepDirection.template cast<real_t>() / rd;
     154             : 
     155       56178 :         _tDelta = (Eigen::abs(rd) > EPS).select(tdelta, MAX);
     156       56178 :     }
     157             : 
     158             :     template <int dim>
     159             :     void TraverseAABB<dim>::initT(const RealArray_t<dim>& rd, const RealArray_t<dim>& EPS,
     160             :                                   const RealArray_t<dim>& MAX, const RealArray_t<dim>& entryPoint)
     161       56186 :     {
     162       56186 :         RealArray_t<dim> T =
     163       56186 :             (((rd > 0.0f).select(_currentPos + 1., _currentPos)) - entryPoint) / rd;
     164             : 
     165       56186 :         _T = (Eigen::abs(rd) > EPS).select(T, MAX);
     166       56186 :     }
     167             : 
     168             :     template <int dim>
     169             :     bool TraverseAABB<dim>::isCurrentPositionInAABB() const
     170     2086513 :     {
     171     2193193 :         return (_currentPos < _aabbMax).all() && (_currentPos >= _aabbMin).all();
     172     2086513 :     }
     173             : 
     174             :     template <int dim>
     175             :     void TraverseAABB<dim>::updateCurrentIndex()
     176     1693860 :     {
     177     1693860 :         _currentIndex +=
     178     1693860 :             (_stepDirection * _mask.select(_productOfCoefficientsPerDimension, 0)).sum();
     179     1693860 :     }
     180             :     template <int dim>
     181             :     void TraverseAABB<dim>::initCurrentIndex()
     182       56155 :     {
     183       56155 :         _currentIndex = (_productOfCoefficientsPerDimension * getCurrentVoxel()).sum();
     184       56155 :     }
     185             : 
     186             :     template class TraverseAABB<2>;
     187             :     template class TraverseAABB<3>;
     188             : } // namespace elsa

Generated by: LCOV version 1.14