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