Line data Source code
1 : #include "BaseHelixTrajectoryGenerator.h" 2 : #include "Logger.h" 3 : 4 : namespace elsa 5 : { 6 : std::tuple<IndexVector_t, RealVector_t, std::vector<Geometry>> 7 : BaseHelixTrajectoryGenerator::createTrajectoryData( 8 : const DataDescriptor& volumeDescriptor, std::vector<real_t> thetas, real_t pitch, 9 : real_t sourceToCenter, real_t centerToDetector, 10 : std::optional<RealVector_t> principalPointOffset, 11 : std::optional<RealVector_t> centerOfRotOffset, 12 : std::optional<IndexVector_t> detectorSize, std::optional<RealVector_t> detectorSpacing) 13 15 : { 14 : // pull in geometry namespace, to reduce cluttering 15 15 : using namespace geometry; 16 : 17 : // sanity check 18 15 : const auto dim = volumeDescriptor.getNumberOfDimensions(); 19 : 20 15 : if (dim != 3) 21 1 : throw InvalidArgumentError("HelixTrajectoryGenerator: can only handle 3d"); 22 : 23 14 : Logger::get("HelixTrajectoryGenerator") 24 14 : ->info("creating {}D helical trajectory with {} poses and pitch of {}", dim, 25 14 : thetas.size(), pitch); 26 : 27 : // Calculate size and spacing for each geometry pose using a IIFE 28 14 : const auto [coeffs, spacing] = calculateSizeAndSpacingPerGeometry( 29 14 : volumeDescriptor, thetas.size(), detectorSize, detectorSpacing); 30 : 31 : // Create vector to store geometry configurations for each pose 32 14 : std::vector<Geometry> geometryList; 33 14 : geometryList.reserve(static_cast<std::size_t>(thetas.size())); 34 : 35 : // Iterate over each pose and calculate its specific geometry 36 3584 : for (auto degree : thetas) { 37 3584 : const auto angle = Degree{degree}.to_radian(); 38 : 39 3584 : geometryList.emplace_back( 40 3584 : SourceToCenterOfRotation{sourceToCenter}, 41 3584 : CenterOfRotationToDetector{centerToDetector}, 42 3584 : VolumeData3D{volumeDescriptor.getSpacingPerDimension(), 43 3584 : volumeDescriptor.getLocationOfOrigin()}, 44 3584 : SinogramData3D{Size3D{coeffs}, Spacing3D{spacing}}, 45 3584 : RotationAngles3D{Radian{angle}, Radian{0}, Radian{0}}, 46 3584 : principalPointOffset ? PrincipalPointOffset2D{principalPointOffset.value()} 47 3584 : : PrincipalPointOffset2D{0, 0}, 48 3584 : centerOfRotOffset ? RotationOffset3D{centerOfRotOffset.value()[0], 49 0 : pitch * angle + centerOfRotOffset.value()[1], 50 0 : centerOfRotOffset.value()[2]} 51 3584 : : RotationOffset3D{0, pitch * angle, 0}); 52 3584 : } 53 : 54 14 : return std::make_tuple(std::move(coeffs), std::move(spacing), std::move(geometryList)); 55 14 : } 56 : 57 : } // namespace elsa