Line data Source code
1 : #pragma once 2 : 3 : #include "elsaDefines.h" 4 : #include "DetectorDescriptor.h" 5 : #include "StrongTypes.h" 6 : 7 : #include <tuple> 8 : #include <vector> 9 : 10 : namespace elsa 11 : { 12 : /** 13 : * @brief Class representing a curved detector surface. It uses a virtual 14 : * PlanarDetectorDescriptor in the background by mapping the coordinates of the curved detector 15 : * detector to coordinates of the planar one. 16 : * 17 : * @details The idea behind the current approach is to reduce the problem of computing 18 : * intersections between rays and a curved detector to the planar detector case. We project 19 : * coordinates of the curved detector onto coordinates on a virtual flat detector behind. 20 : * Conceptually, the flat detector has the same amount of pixels but they become increasingly 21 : * narrower towards the endpoints of the flat detector. The coordinates for the principal ray 22 : * are the same for the flat and the curved detector. 23 : * 24 : * @author Julia Spindler, Robert Imschweiler - adapt PlanarDetectorDescriptor for 25 : * CurvedDetectorDescriptor 26 : */ 27 : class CurvedDetectorDescriptor : public DetectorDescriptor 28 : { 29 : public: 30 : CurvedDetectorDescriptor() = delete; 31 : 32 31 : ~CurvedDetectorDescriptor() = default; 33 : 34 : /** 35 : * @brief Construct a CurvedDetectorDescriptor with given number of coefficients and spacing 36 : * per dimension, a list of geometry poses in the trajectory, an angle in radians, and 37 : * the length from the source to the detector. 38 : * 39 : * @details The information needed to model a curved detector includes the information 40 : * required for a planar detector. Additionally, we need a parameter describing the 41 : * curvature. Currently, this is implemented by providing the fanout angle (in radians), 42 : * which we use internally to compute the radius of the curved detector. Furthermore, we 43 : * need a parameter for the distance of the source to the detector (so, the sum of the 44 : * distances "source to center" and "center to detector"). 45 : */ 46 : CurvedDetectorDescriptor(const IndexVector_t& numOfCoeffsPerDim, 47 : const RealVector_t& spacingPerDim, 48 : const std::vector<Geometry>& geometryList, 49 : const geometry::Radian angle, const real_t s2d); 50 : 51 : /** 52 : * @brief Construct a CurvedDetectorDescriptor with given number of coefficients 53 : * per dimension, a list of geometry poses in the trajectory, an angle in radians, and 54 : * the length from the source to the detector. 55 : * 56 : * @details The information needed to model a curved detector includes the information 57 : * required for a planar detector. Additionally, we need a parameter describing the 58 : * curvature. Currently, this is implemented by providing the fanout angle (in radians), 59 : * which we use internally to compute the radius of the curved detector. Furthermore, we 60 : * need a parameter for the distance of the source to the detector (so, the sum of the 61 : * distances "source to center" and "center to detector"). 62 : */ 63 : CurvedDetectorDescriptor(const IndexVector_t& numOfCoeffsPerDim, 64 : const std::vector<Geometry>& geometryList, 65 : const geometry::Radian angle, const real_t s2d); 66 : 67 : using DetectorDescriptor::computeRayFromDetectorCoord; 68 : 69 : /** 70 : * @details The ray computation of the curved detector descriptor is a wrapper around the 71 : * ray computation of the planar detector descriptor. The wrapper is responsible for mapping 72 : * the user-provided coordinates of the curved detector to the corresponding coordinates of 73 : * the virtual planar detector descriptor. This overhead is encapsulated in the 74 : * mapCurvedCoordToPlanarCoord method, which "extends" the rays hitting the curved 75 : * detector to the virtual flat detector behind. Most importantly, the 76 : * CurvedDetectorDescriptor class overrides the computeRayFromDetectorCoord function. 77 : * This function receives the parameter detectorCoord which is treated as the index of a 78 : * pixel on the curved detector. If the x-coordinate of detectorCoord is of the form x.5, 79 : * i.e. references the pixel center, we can use the coordinates that were precomputed in 80 : * the constructor. This should usually be the case. Otherwise, the planar detector 81 : * coordinate needs to be dynamically computed by mapCurvedCoordToPlanarCoord. Finally, we 82 : * receive a coordinate in the detector space of the flat detector which we pass to the 83 : * parent implementation of computeRayFromDetectorCoord. 84 : * 85 : * ![Schematic Overview](docs/curved-detector-schematic-overview.png) 86 : */ 87 : RealRay_t computeRayFromDetectorCoord(const RealVector_t& detectorCoord, 88 : const index_t poseIndex) const override; 89 : 90 : /** 91 : * @brief Return the coordinates of the planar detector descriptor which 92 : * operates in background. 93 : */ 94 : const std::vector<RealVector_t>& getPlanarCoords() const; 95 : 96 : real_t getRadius() const; 97 : 98 : std::unique_ptr<DetectorDescriptor> 99 : cloneWithGeometry(std::vector<Geometry> geometries) const override; 100 : 101 : private: 102 : CurvedDetectorDescriptor* cloneImpl() const override; 103 : 104 : bool isEqual(const DataDescriptor& other) const override; 105 : 106 : /** 107 : * @brief setup function that is called in the constructor. 108 : * Precomputes the coordinates of the pixel midpoints on the hypothetical planar detector 109 : */ 110 : void setup(); 111 : 112 : /** 113 : * @brief Map a given coordinate of the curved detector to the corresponding coordinate of 114 : * the virtual flat detector. 115 : * 116 : * @param coord 117 : * @return real_t 118 : */ 119 : RealVector_t mapCurvedCoordToPlanarCoord(const RealVector_t& coord) const; 120 : 121 : // the coordinates of the pixel midpoints on the flat detector 122 : std::vector<RealVector_t> _planarCoords; 123 : 124 : // angle describing the fov of the detector 125 : geometry::Radian _angle; 126 : 127 : // radius of the circle the curved detector is a part of 128 : real_t _radius; 129 : 130 : // the detector pixels are evenly spaced, so the angle distance between them is fov/detector 131 : // length 132 : real_t _angleDelta; 133 : 134 : // the middle coordinate that the principal ray hits 135 : RealVector_t _detectorCenter; 136 : 137 : // the distance from the source to the detector 138 : real_t _s2d; 139 : 140 : // the center of the circle the curved detector lies on 141 : RealVector_t _centerOfCircle; 142 : }; 143 : } // namespace elsa