Tatooine
moving_least_squares_sampler3.h
Go to the documentation of this file.
1#ifndef TATOOINE_DETAIL_POINTSET_MOVING_LEAST_SQUARES_SAMPLER3_H
2#define TATOOINE_DETAIL_POINTSET_MOVING_LEAST_SQUARES_SAMPLER3_H
3//==============================================================================
4#if TATOOINE_FLANN_AVAILABLE
5//==============================================================================
7#include <tatooine/pointset.h>
8//==============================================================================
10//==============================================================================
15template <floating_point Real, typename T, invocable<Real> Weighting>
16struct moving_least_squares_sampler<Real, 3, T, Weighting>
17 : field<moving_least_squares_sampler<Real, 3, T, Weighting>, Real, 3, T> {
20 using typename parent_type::pos_type;
21 using typename parent_type::real_type;
22 using typename parent_type::tensor_type;
25 typename pointset_type::template typed_vertex_property_type<T>;
27 //==========================================================================
31 Weighting m_weighting;
32 //==========================================================================
34 property_type const& property,
35 arithmetic auto const radius,
36 convertible_to<Weighting> auto&& weighting)
37 : m_pointset{ps},
38 m_property{property},
39 m_radius{radius},
40 m_weighting{std::forward<decltype(weighting)>(weighting)} {}
41 //--------------------------------------------------------------------------
43 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
45 default;
46 //--------------------------------------------------------------------------
47 auto operator =(moving_least_squares_sampler const&)
48 -> moving_least_squares_sampler& = default;
49 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
50 auto operator=(moving_least_squares_sampler&&) noexcept
51 -> moving_least_squares_sampler& = default;
52 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54 //--------------------------------------------------------------------------
55 private:
56 [[nodiscard]] auto evaluate_0_neighbors() const {
57 if constexpr (is_arithmetic<tensor_type>) {
58 return Real(0) / Real(0);
59 } else {
60 return tensor_type::fill(Real(0) / Real(0));
61 }
62 }
63 //------------------------------------------------------------------------------
64 [[nodiscard]] auto evaluate_1_neighbors(
65 std::vector<int> const& indices) const {
66 return m_property[vertex_handle{indices[0]}];
67 }
68 //------------------------------------------------------------------------------
69 [[nodiscard]] auto evaluate_2_neighbors(
70 std::vector<int> const& indices,
71 std::vector<Real> const& distances) const {
72 auto const& p0 = m_property[vertex_handle{indices[0]}];
73 auto const& p1 = m_property[vertex_handle{indices[1]}];
74
75 auto d0 = distances[0];
76 auto d1 = distances[1];
77
78 auto const d_norm = 1 / (d0 + d1);
79 d0 *= d_norm;
80 d1 *= d_norm;
81
82 return p0 * d1 + p1 * d0;
83 }
84 //------------------------------------------------------------------------------
85 [[nodiscard]] auto evaluate_3_neighbors() const {
86 return evaluate_0_neighbors();
87 }
88 //------------------------------------------------------------------------------
90 std::vector<int> const& indices, std::vector<Real> const& distances,
91 pos_type const& q) const {
92 auto const num_neighbors = size(indices);
93 auto const w = construct_weights(num_neighbors, distances);
94 auto const F = construct_F(num_neighbors, indices);
95 auto const B = construct_B(num_neighbors, indices, q);
96 auto const BtW = transposed(B) * diag(w);
97 auto const C = *solve(BtW * B, BtW * F);
98
99 if constexpr (tensor_num_components<T> == 1) {
100 return C(0);
101 } else {
102 auto ret = T{};
103 for (std::size_t i = 0; i < tensor_num_components<T>; ++i) {
104 ret(i) = C(0, i);
105 }
106 return ret;
107 }
108 }
109 //------------------------------------------------------------------------------
110 auto construct_B(std::size_t const num_neighbors,
111 std::vector<int> const& indices, pos_type const& q) const {
112 auto B = allocate_B(num_neighbors);
113 auto local_positions = std::vector<pos_type>(num_neighbors);
114 std::ranges::copy(indices | std::views::transform([&](auto const i) {
115 return m_pointset.vertex_at(i) - q;
116 }),
117 begin(local_positions));
118 if (num_neighbors >= 4) {
119 construct_linear_part_of_B(local_positions, q, B);
120 }
121 if (num_neighbors >= 10) {
122 construct_quadratic_part_of_B(local_positions, q, B);
123 }
124 if (num_neighbors >= 20) {
125 construct_cubic_part_of_B(local_positions, q, B);
126 }
127 return B;
128 }
129 //------------------------------------------------------------------------------
130 auto allocate_B(std::size_t const num_neighbors) const {
131 if (num_neighbors >= 20) {
132 return tensor<Real>::ones(num_neighbors, 20);
133 }
134 if (num_neighbors >= 10) {
135 return tensor<Real>::ones(num_neighbors, 10);
136 }
137 if (num_neighbors >= 4) {
138 return tensor<Real>::ones(num_neighbors, 4);
139 }
140 return tensor<Real>::ones(1, 1);
141 }
142 //------------------------------------------------------------------------------
143 auto construct_linear_part_of_B(std::vector<pos_type> const& local_positions,
144 pos_type const& /*q*/, auto& B) const {
145 auto i = std::size_t{};
146 for (auto const& x : local_positions) {
147 B(i, 1) = x.x();
148 B(i, 2) = x.y();
149 B(i, 3) = x.z();
150 ++i;
151 }
152 }
153 //------------------------------------------------------------------------------
155 std::vector<pos_type> const& local_positions, pos_type const& /*q*/,
156 auto& B) const {
157 auto i = std::size_t{};
158 for (auto const& x : local_positions) {
159 B(i, 4) = x.x() * x.x();
160 B(i, 5) = x.x() * x.y();
161 B(i, 6) = x.x() * x.z();
162 B(i, 7) = x.y() * x.y();
163 B(i, 8) = x.y() * x.z();
164 B(i, 9) = x.z() * x.z();
165 ++i;
166 }
167 }
168 //------------------------------------------------------------------------------
169 auto construct_cubic_part_of_B(std::vector<pos_type> const& local_positions,
170 pos_type const& /*q*/, auto& B) const {
171 auto i = std::size_t{};
172 for (auto const& x : local_positions) {
173 B(i, 10) = x.x() * x.x() * x.x();
174 B(i, 11) = x.y() * x.y() * x.y();
175 B(i, 12) = x.z() * x.z() * x.z();
176 B(i, 13) = x.x() * x.x() * x.y();
177 B(i, 14) = x.x() * x.x() * x.z();
178 B(i, 15) = x.y() * x.y() * x.x();
179 B(i, 16) = x.y() * x.y() * x.z();
180 B(i, 17) = x.z() * x.z() * x.x();
181 B(i, 18) = x.z() * x.z() * x.y();
182 B(i, 19) = x.x() * x.y() * x.z();
183 ++i;
184 }
185 }
186 //----------------------------------------------------------------------------
187 auto construct_weights(std::size_t const num_neighbors,
188 std::vector<Real> const& distances) const {
189 auto w = tensor<Real>::zeros(num_neighbors);
190 for (std::size_t i = 0; i < num_neighbors; ++i) {
191 w(i) = m_weighting(distances[i] / m_radius);
192 }
193 return w;
194 }
195 //----------------------------------------------------------------------------
197 auto construct_F(std::size_t const num_neighbors,
198 std::vector<int> const& indices) const {
199 auto F = tensor_num_components<T> > 1
200 ? tensor<Real>::zeros(num_neighbors, tensor_num_components<T>)
201 : tensor<Real>::zeros(num_neighbors);
202 for (std::size_t i = 0; i < num_neighbors; ++i) {
203 if constexpr (tensor_num_components<T> == 1) {
204 F(i) = m_property[vertex_handle{indices[i]}];
205 } else {
206 for (std::size_t j = 0; j < tensor_num_components<T>; ++j) {
207 F(i, j) = m_property[vertex_handle{indices[i]}](j);
208 }
209 }
210 }
211 return F;
212 }
213 //==========================================================================
214 public:
215 [[nodiscard]] auto evaluate(pos_type const& q, Real const /*t*/) const
216 -> tensor_type {
217 auto [indices, distances] =
218 m_pointset.nearest_neighbors_radius_raw(q, m_radius);
219 switch (size(indices)) {
220 case 0:
221 return evaluate_0_neighbors(q);
222 case 1:
223 return m_property[vertex_handle{indices[0]}];
224 case 2:
225 return evaluate_2_neighbors(indices, distances);
226 case 3:
227 return evaluate_3_neighbors();
228 default:
229 return evaluate_more_than_3_neighbors(indices, distances, q);
230 }
231 }
232};
233//==============================================================================
234} // namespace tatooine::detail::pointset
235//==============================================================================
236#else
237#pragma message( \
238 "including <tatooine/detail/pointset/moving_least_squares_sampler2.h> without FLANN support.")
239#endif
240#endif
Definition: concepts.h:33
Definition: concepts.h:39
Definition: inverse_distance_weighting_sampler.h:4
auto size(vertex_container< Real, NumDimensions > verts)
Definition: vertex_container.h:269
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto solve(polynomial< Real, 1 > const &p) -> std::vector< Real >
solve a + b*x
Definition: polynomial.h:187
auto transposed(dynamic_tensor auto &&t)
Definition: transposed_tensor.h:170
static constexpr forward_tag forward
Definition: tags.h:9
property_type const & m_property
Definition: moving_least_squares_sampler3.h:29
auto construct_linear_part_of_B(std::vector< pos_type > const &local_positions, pos_type const &, auto &B) const
Definition: moving_least_squares_sampler3.h:143
auto construct_cubic_part_of_B(std::vector< pos_type > const &local_positions, pos_type const &, auto &B) const
Definition: moving_least_squares_sampler3.h:169
Weighting m_weighting
Definition: moving_least_squares_sampler3.h:31
auto evaluate_2_neighbors(std::vector< int > const &indices, std::vector< Real > const &distances) const
Definition: moving_least_squares_sampler3.h:69
auto construct_quadratic_part_of_B(std::vector< pos_type > const &local_positions, pos_type const &, auto &B) const
Definition: moving_least_squares_sampler3.h:154
moving_least_squares_sampler(moving_least_squares_sampler const &)=default
moving_least_squares_sampler(moving_least_squares_sampler &&) noexcept=default
auto evaluate_1_neighbors(std::vector< int > const &indices) const
Definition: moving_least_squares_sampler3.h:64
typename pointset_type::vertex_handle vertex_handle
Definition: moving_least_squares_sampler3.h:26
pointset_type const & m_pointset
Definition: moving_least_squares_sampler3.h:28
auto allocate_B(std::size_t const num_neighbors) const
Definition: moving_least_squares_sampler3.h:130
moving_least_squares_sampler(pointset_type const &ps, property_type const &property, arithmetic auto const radius, convertible_to< Weighting > auto &&weighting)
Definition: moving_least_squares_sampler3.h:33
auto construct_F(std::size_t const num_neighbors, std::vector< int > const &indices) const
Represents function values f(x_i)
Definition: moving_least_squares_sampler3.h:197
auto evaluate(pos_type const &q, Real const) const -> tensor_type
Definition: moving_least_squares_sampler3.h:215
auto evaluate_more_than_3_neighbors(std::vector< int > const &indices, std::vector< Real > const &distances, pos_type const &q) const
Definition: moving_least_squares_sampler3.h:89
auto evaluate_3_neighbors() const
Definition: moving_least_squares_sampler3.h:85
auto construct_B(std::size_t const num_neighbors, std::vector< int > const &indices, pos_type const &q) const
Definition: moving_least_squares_sampler3.h:110
auto construct_weights(std::size_t const num_neighbors, std::vector< Real > const &distances) const
Definition: moving_least_squares_sampler3.h:187
typename pointset_type::template typed_vertex_property_type< T > property_type
Definition: moving_least_squares_sampler3.h:25
Definition: moving_least_squares_samplerN.h:12
Definition: field.h:134
Real real_type
Definition: field.h:17
auto nearest_neighbors_radius_raw(pos_type const &x, Real const radius, flann::SearchParams const params={}) const -> std::pair< std::vector< int >, std::vector< Real > >
Definition: pointset.h:1088
auto vertex_at(vertex_handle const v) -> auto &
Definition: pointset.h:205
Definition: tags.h:96
static constexpr auto zeros()
Definition: tensor.h:144
static constexpr auto ones()
Definition: tensor.h:146
Definition: vec.h:12