22 #pragma clang diagnostic push 23 #pragma clang diagnostic ignored "-Wpadded" 32 : outside{outside_}, volume_{vol} {}
34 template <
class Derived,
class DerivedOut>
35 inline void operator()(Eigen::MatrixBase<Derived>
const &positions,
36 Eigen::MatrixBase<DerivedOut> &values)
const {
37 using Eigen::Vector3f;
39 Expects(values.rows() == positions.rows());
40 Expects(positions.cols() == 3);
47 [
this, &positions, &values, scale](
auto const *ptr) {
49 #pragma omp parallel for 50 for (Eigen::Index i = 0; i < positions.rows(); ++i) {
52 values(i) = this->interpolate(
53 (positions.row(i).array() * scale.array().transpose())
56 gsl::make_not_null(ptr));
61 template <
class Derived>
62 inline Eigen::Matrix<VoxelVolume::ValueType, Eigen::Dynamic, 1>
63 operator()(Eigen::MatrixBase<Derived>
const &positions)
const {
64 Eigen::Matrix<VoxelVolume::ValueType, Eigen::Dynamic, 1> values(
67 operator()(positions, values);
73 template <
class Derived>
75 at(Eigen::MatrixBase<Derived>
const &pos,
76 gsl::not_null<VoxelVolume::ValueType const *> ptr)
const {
77 auto const &size = volume_.
size();
79 auto const isInside = (pos.array() >= 0).all() &&
80 pos(0) < gsl::narrow_cast<
int>(size.width) &&
81 pos(1) < gsl::narrow_cast<
int>(size.height) &&
82 pos(2) < gsl::narrow_cast<
int>(size.depth);
85 gsl::narrow_cast<std::size_t>(pos(2)) * size.width * size.height +
86 gsl::narrow_cast<std::size_t>(pos(1)) * size.width +
87 gsl::narrow_cast<std::size_t>(pos(0));
89 return isInside ? ptr.get()[index] : outside;
92 template <
class Derived>
94 interpolate(Eigen::MatrixBase<Derived>
const &pos,
95 gsl::not_null<VoxelVolume::ValueType const *> ptr)
const {
98 using Eigen::Vector3f;
99 using Eigen::Vector3i;
100 using gsl::make_not_null;
102 Vector3i
const x0 = pos.array().floor().matrix().template cast<int>();
103 Vector3i
const x1 = pos.array().ceil().matrix().template cast<int>();
104 Vector3f
const xd = pos - x0.cast<
float>();
105 Vector3f
const xn = Vector3f::Ones() - xd;
108 Value
const c000 = at(x0, ptr);
109 Value
const c001 = at(Vector3i{x0(0), x0(1), x1(2)}, ptr);
110 Value
const c010 = at(Vector3i{x0(0), x1(1), x0(2)}, ptr);
111 Value
const c011 = at(Vector3i{x0(0), x1(1), x1(2)}, ptr);
112 Value
const c100 = at(Vector3i{x1(0), x0(1), x0(2)}, ptr);
113 Value
const c101 = at(Vector3i{x1(0), x0(1), x1(2)}, ptr);
114 Value
const c110 = at(Vector3i{x1(0), x1(1), x0(2)}, ptr);
115 Value
const c111 = at(x1, ptr);
117 auto const c00 = c000 * xn(0) + c100 * xd(0);
118 auto const c01 = c001 * xn(0) + c101 * xd(0);
119 auto const c10 = c010 * xn(0) + c110 * xd(0);
120 auto const c11 = c011 * xn(0) + c111 * xd(0);
122 auto const c0 = c00 * xn(1) + c10 * xd(1);
123 auto const c1 = c01 * xn(1) + c11 * xd(1);
125 auto const c = c0 * xn(2) + c1 * xd(2);
139 template <
class DerivedIn,
class VectorOut>
140 inline void operator()(Eigen::MatrixBase<DerivedIn>
const &positions,
141 float offset, VectorOut &&values)
const {
142 using Eigen::Dynamic;
144 using Eigen::Vector3f;
146 Expects(values.rows() == positions.rows());
147 Expects(positions.cols() == 4);
148 Expects(values.cols() == 1);
150 Vector3f
const min{model_.samplingRange.min, model_.densityRange.min,
151 model_.angleRange.min};
152 Vector3f
const scale{1.f / model_.samplingRange.stride,
153 1.f / model_.densityRange.stride,
154 1.f / model_.angleRange.stride};
156 for (
auto &&label : model_.labels()) {
157 model_.withUnsafeDataPointer(label, [
this, &positions, &values, min,
159 label](
float const *ptr) {
160 for (Eigen::Index i = 0; i < positions.rows(); ++i) {
161 if (static_cast<MeasurementModel::Label>(positions(i, 3)) != label) {
165 Vector3f
const position{positions(i, 0) + offset, positions(i, 1),
167 values(i) = this->interpolate(
168 ((position - min).array() * scale.array()).matrix(), ptr);
174 template <
class Derived>
175 inline Eigen::Matrix<float, Eigen::Dynamic, 1>
176 operator()(Eigen::MatrixBase<Derived>
const &positions,
float offset)
const {
177 Eigen::Matrix<float, Eigen::Dynamic, 1> values(positions.rows());
179 operator()(positions, offset, values);
185 inline float at(
int x,
int y,
int z, Eigen::Vector3i
const &sizeI,
186 float const *ptr)
const {
188 auto const index = x * sizeI.y() * sizeI.z() + z * sizeI.y() + y;
192 template <
class Derived>
193 inline float interpolate(Eigen::MatrixBase<Derived>
const &pos,
194 float const *ptr)
const {
195 using Eigen::Vector3f;
196 using Eigen::Vector3i;
200 Vector3i
const sizeI{
static_cast<int>(model_.samplingRange.numElements()),
201 static_cast<int>(model_.densityRange.numElements()),
202 static_cast<int>(model_.angleRange.numElements())};
204 auto const x00 = clamp(static_cast<int>(pos(0)), 0, sizeI.x() - 1);
205 auto const x01 = clamp(static_cast<int>(pos(2) + 0.5f), 0, sizeI.z() - 1);
206 auto const x0 =
static_cast<int>(pos(1));
207 auto const x1 = x0 + 1;
208 auto const xd = pos(1) -
static_cast<float>(x0);
209 auto const xn = 1.f - xd;
211 auto const c0 = at(x00, clamp(x0, 0, sizeI.y() - 1), x01, sizeI, ptr);
212 auto const c1 = at(x00, clamp(x1, 0, sizeI.y() - 1), x01, sizeI, ptr);
214 auto const c = c0 * xn + c1 * xd;
221 #pragma clang diagnostic pop Name namespace for CortidQCT library.
Definition: CortidQCT.h:23
VolumeSize const & size() const noexcept
Returns the volume size.
Definition: VoxelVolume.h:76
VoxelSize const & voxelSize() const noexcept
Returns the voxel size.
Definition: VoxelVolume.h:79
Type representing a voxel volume.
Definition: VoxelVolume.h:32
Type representing the measurement model.
Definition: MeasurementModel.h:33
float depth
Size along the z-axis.
Definition: VoxelSize.h:28
float width
Size along the x-axis.
Definition: VoxelSize.h:24
Definition: Sampler.h:133
auto withUnsafeDataPointer(F &&f) const noexcept(noexcept(f(std::declval< VoxelData >().data())))
Calls the given functional with an unsafe pointer to the raw voxel storage.
Definition: VoxelVolume.h:108
This header contains the definition of the MeasurementModel type.
This header contains the definition of the VoxelVolume type.
float height
Size along the y-axis.
Definition: VoxelSize.h:26
float ValueType
Voxel value type.
Definition: VoxelVolume.h:35