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