20#include <covfie/core/algebra/affine.hpp>
21#include <covfie/core/backend/primitive/array.hpp>
22#include <covfie/core/backend/transformer/affine.hpp>
23#include <covfie/core/backend/transformer/clamp.hpp>
24#include <covfie/core/backend/transformer/linear.hpp>
25#include <covfie/core/backend/transformer/nearest_neighbour.hpp>
26#include <covfie/core/backend/transformer/strided.hpp>
27#include <covfie/core/field.hpp>
28#include <covfie/core/field_view.hpp>
29#include <covfie/core/parameter_pack.hpp>
30#include <covfie/core/vector.hpp>
45using stored_backend_t = covfie::backend::strided<covfie::vector::size3, array_backend_t>;
48 covfie::backend::affine<covfie::backend::clamp<covfie::backend::linear<stored_backend_t>>>>;
51 covfie::backend::clamp<covfie::backend::nearest_neighbour<stored_backend_t>>>>;
55 std::array<float, 3>
min;
56 std::array<float, 3>
max;
57 std::array<std::size_t, 3>
n;
65 for (std::size_t i = 0; i < 3; ++i) {
67 throw std::invalid_argument(
"GridSpec: axis " + std::to_string(i) +
68 " needs at least 2 samples");
70 if (!(spec.
max[i] > spec.
min[i])) {
71 throw std::invalid_argument(
"GridSpec: axis " + std::to_string(i) +
" needs max > min");
80[[nodiscard]]
inline float grid_pos(
float min,
float max, std::size_t n, std::size_t i) {
81 return min +
static_cast<float>(i) * (max - min) /
static_cast<float>(n - 1);
86 covfie::algebra::affine<3> translation =
87 covfie::algebra::affine<3>::translation(-spec.
min[0], -spec.
min[1], -spec.
min[2]);
88 covfie::algebra::affine<3> scaling = covfie::algebra::affine<3>::scaling(
89 static_cast<float>(spec.
n[0] - 1) / (spec.
max[0] - spec.
min[0]),
90 static_cast<float>(spec.
n[1] - 1) / (spec.
max[1] - spec.
min[1]),
91 static_cast<float>(spec.
n[2] - 1) / (spec.
max[2] - spec.
min[2]));
92 return scaling * translation;
99template <
typename clamp_cfg_t>
101 clamp_cfg_t clamp_cfg{};
102 for (std::size_t i = 0; i < 3; ++i) {
103 clamp_cfg.min[i] = 0.0f;
104 clamp_cfg.max[i] = std::nextafter(
static_cast<float>(spec.
n[i] - 1), 0.0f);
113 using clamp_cfg_t = writer_field_t::backend_t::backend_t::configuration_t;
115 writer_field_t::backend_t::configuration_t(
make_affine(spec)),
116 make_clamp<clamp_cfg_t>(spec), std::monostate{},
117 writer_field_t::backend_t::backend_t::backend_t::backend_t::configuration_t{
118 spec.
n[0], spec.
n[1], spec.
n[2]}));
127 using affine_t = reader_field_t::backend_t;
128 using clamp_t = affine_t::backend_t;
129 using linear_t = clamp_t::backend_t;
130 using strided_t = linear_t::backend_t;
131 std::size_t
const size = spec.
n[0] * spec.
n[1] * spec.
n[2];
132 strided_t::owning_data_t stored(strided_t::configuration_t{spec.
n[0], spec.
n[1], spec.
n[2]},
133 array_backend_t::owning_data_t(size, std::move(values)));
134 linear_t::owning_data_t linear(std::monostate{}, std::move(stored));
135 clamp_t::owning_data_t clamp(make_clamp<clamp_t::configuration_t>(spec), std::move(linear));
Definition covfie_chains.h:38
array_backend_t::vector_t stored_vector_t
One stored node: {Bx, By, Bz} in Tesla.
Definition covfie_chains.h:43
covfie::algebra::affine< 3 > make_affine(GridSpec const &spec)
World (mm) to fractional grid index: node i on each axis maps to i.
Definition covfie_chains.h:85
covfie::backend::array< covfie::vector::float3 > array_backend_t
Definition covfie_chains.h:40
covfie::field< covfie::backend::affine< covfie::backend::clamp< covfie::backend::nearest_neighbour< stored_backend_t > > > > writer_field_t
Definition covfie_chains.h:51
clamp_cfg_t make_clamp(GridSpec const &spec)
Clamp fractional grid indices to the mapped box.
Definition covfie_chains.h:100
float grid_pos(float min, float max, std::size_t n, std::size_t i)
Position of sample i on an axis with n samples spanning [min, max].
Definition covfie_chains.h:80
void validate(GridSpec const &spec)
Throw if spec cannot produce a well-formed grid: every axis needs at least two samples (n - 1 underfl...
Definition covfie_chains.h:64
covfie::backend::strided< covfie::vector::size3, array_backend_t > stored_backend_t
Definition covfie_chains.h:45
reader_field_t make_reader_field(GridSpec const &spec, std::unique_ptr< stored_vector_t[]> values)
Build a reader-chain field over spec that adopts values: one node per grid point, n[0] * n[1] * n[2] ...
Definition covfie_chains.h:124
covfie::field< covfie::backend::affine< covfie::backend::clamp< covfie::backend::linear< stored_backend_t > > > > reader_field_t
Definition covfie_chains.h:48
writer_field_t make_writer_field(GridSpec const &spec)
Build an empty writer-chain field over spec, ready to be filled via writer_field_t::view_t::at(x,...
Definition covfie_chains.h:111
Axis-aligned grid: n[i] samples spanning [min[i], max[i]] (mm).
Definition covfie_chains.h:54
std::array< float, 3 > min
Definition covfie_chains.h:55
std::array< std::size_t, 3 > n
Definition covfie_chains.h:57
std::array< float, 3 > max
Definition covfie_chains.h:56