Line data Source code
1 : #include "CircleTrajectoryGenerator.h" 2 : #include "Logger.h" 3 : #include "VolumeDescriptor.h" 4 : #include "PlanarDetectorDescriptor.h" 5 : 6 : #include <stdexcept> 7 : 8 : namespace elsa 9 : { 10 0 : std::unique_ptr<DetectorDescriptor> CircleTrajectoryGenerator::createTrajectory( 11 : index_t numberOfPoses, const DataDescriptor& volumeDescriptor, index_t arcDegrees, 12 : real_t sourceToCenter, real_t centerToDetector) 13 : { 14 : // pull in geometry namespace, to reduce cluttering 15 : using namespace geometry; 16 : 17 : // sanity check 18 0 : const auto dim = volumeDescriptor.getNumberOfDimensions(); 19 : 20 0 : if (dim < 2 || dim > 3) 21 0 : throw InvalidArgumentError("CircleTrajectoryGenerator: can only handle 2d/3d"); 22 : 23 0 : Logger::get("CircleTrajectoryGenerator") 24 0 : ->info("creating {}D trajectory with {} poses in an {} degree arc", dim, numberOfPoses, 25 : arcDegrees); 26 : 27 : // Calculate size and spacing for each geometry pose using a IIFE 28 0 : const auto [coeffs, spacing] = 29 0 : calculateSizeAndSpacingPerGeometry(volumeDescriptor, numberOfPoses); 30 : 31 : // Create vector and reserve the necessary size, minor optimization such that no new 32 : // allocations are necessary in the loop 33 0 : std::vector<Geometry> geometryList; 34 0 : geometryList.reserve(static_cast<std::size_t>(numberOfPoses)); 35 : 36 0 : for (auto degree : RealVector_t::LinSpaced(numberOfPoses, 0, arcDegrees)) { 37 0 : const auto angle = Degree{degree}.to_radian(); 38 0 : if (dim == 2) { 39 : // Use emplace_back, then no copy is created 40 0 : geometryList.emplace_back(SourceToCenterOfRotation{sourceToCenter}, 41 0 : CenterOfRotationToDetector{centerToDetector}, 42 0 : Radian{angle}, 43 0 : VolumeData2D{volumeDescriptor.getSpacingPerDimension(), 44 0 : volumeDescriptor.getLocationOfOrigin()}, 45 0 : SinogramData2D{Size2D{coeffs}, Spacing2D{spacing}}); 46 : } else { 47 0 : geometryList.emplace_back(SourceToCenterOfRotation{sourceToCenter}, 48 0 : CenterOfRotationToDetector{centerToDetector}, 49 0 : VolumeData3D{volumeDescriptor.getSpacingPerDimension(), 50 0 : volumeDescriptor.getLocationOfOrigin()}, 51 0 : SinogramData3D{Size3D{coeffs}, Spacing3D{spacing}}, 52 0 : RotationAngles3D{Radian{angle}, Radian{0}, Radian{0}}); 53 : } 54 : } 55 : 56 0 : return std::make_unique<PlanarDetectorDescriptor>(coeffs, spacing, geometryList); 57 0 : } 58 : 59 : } // namespace elsa