CircleTrajectoryGenerator.cpp 2.99 KB
Newer Older
1 2
#include "CircleTrajectoryGenerator.h"
#include "Logger.h"
3
#include "VolumeDescriptor.h"
4
#include "PlanarDetectorDescriptor.h"
5 6 7 8 9

#include <stdexcept>

namespace elsa
{
10 11 12
    std::unique_ptr<DetectorDescriptor> CircleTrajectoryGenerator::createTrajectory(
        index_t numberOfPoses, const DataDescriptor& volumeDescriptor, index_t arcDegrees,
        real_t sourceToCenter, real_t centerToDetector)
13
    {
14 15 16
        // pull in geometry namespace, to reduce cluttering
        using namespace geometry;

17 18 19 20 21 22
        // sanity check
        auto dim = volumeDescriptor.getNumberOfDimensions();

        if (dim < 2 || dim > 3)
            throw std::invalid_argument("CircleTrajectoryGenerator: can only handle 2d/3d");

Jens Petit's avatar
Jens Petit committed
23 24 25
        Logger::get("CircleTrajectoryGenerator")
            ->info("creating {}D trajectory with {} poses in an {} degree arc", dim, numberOfPoses,
                   arcDegrees);
26 27 28 29

        IndexVector_t coeffs(dim);
        RealVector_t spacing(dim);
        if (dim == 2) {
Jens Petit's avatar
Jens Petit committed
30
            coeffs << volumeDescriptor.getNumberOfCoefficientsPerDimension()[0], numberOfPoses;
31
            spacing << volumeDescriptor.getSpacingPerDimension()[0], 1;
Jens Petit's avatar
Jens Petit committed
32 33 34
        } else {
            coeffs << volumeDescriptor.getNumberOfCoefficientsPerDimension()[0],
                volumeDescriptor.getNumberOfCoefficientsPerDimension()[1], numberOfPoses;
35
            spacing << volumeDescriptor.getSpacingPerDimension()[0],
Jens Petit's avatar
Jens Petit committed
36
                volumeDescriptor.getSpacingPerDimension()[1], 1;
37
        }
38

39 40
        std::vector<Geometry> geometryList;

41 42
        real_t angleIncrement = static_cast<real_t>(1.0f) * static_cast<real_t>(arcDegrees)
                                / (static_cast<real_t>(numberOfPoses) - 1.0f);
43
        for (index_t i = 0; i < numberOfPoses; ++i) {
44 45
            real_t angle =
                static_cast<real_t>(i) * angleIncrement * pi_t / 180.0f; // convert to radians
46
            if (dim == 2) {
47 48 49 50 51
                Geometry geom(SourceToCenterOfRotation{sourceToCenter},
                              CenterOfRotationToDetector{centerToDetector}, Radian{angle},
                              VolumeData2D{volumeDescriptor.getSpacingPerDimension(),
                                           volumeDescriptor.getLocationOfOrigin()},
                              SinogramData2D{Size2D{coeffs}, Spacing2D{spacing}});
52
                geometryList.push_back(geom);
Jens Petit's avatar
Jens Petit committed
53
            } else {
54 55 56 57 58 59
                Geometry geom(SourceToCenterOfRotation{sourceToCenter},
                              CenterOfRotationToDetector{centerToDetector},
                              VolumeData3D{volumeDescriptor.getSpacingPerDimension(),
                                           volumeDescriptor.getLocationOfOrigin()},
                              SinogramData3D{Size3D{coeffs}, Spacing3D{spacing}},
                              RotationAngles3D{Radian{angle}, Radian{0}, Radian{0}});
60 61 62 63
                geometryList.push_back(geom);
            }
        }

64
        return std::make_unique<PlanarDetectorDescriptor>(coeffs, spacing, geometryList);
65 66 67
    }

} // namespace elsa