27#ifndef EASY3D_CORE_SPLINE_CURVE_FITTING_H
28#define EASY3D_CORE_SPLINE_CURVE_FITTING_H
60 template<
typename Po
int_t>
63 typedef typename Point_t::FT FT;
90 Point_t
eval_f(FT u)
const;
95 int get_order()
const {
return _k; }
110 void assert_splines()
const;
114 void set_nodal_vector();
117 void set_node_to_uniform();
120 void set_node_to_open_uniform();
133 const std::vector<Point_t> &point,
135 const std::vector<FT> &node,
138 Point_t eval_rec(FT u,
139 std::vector<Point_t> p_in,
141 std::vector<FT> node_in)
const;
149 std::vector<Point_t> _point;
150 std::vector<Point_t> _vec;
151 std::vector<FT> _node;
155 template<
typename Po
int_t>
157 _node_type(node_type),
161 _node(_k + _point.size()) {
167 template<
typename Po
int_t>
170 _vec.resize(_point.size() - 1);
171 for (
int i = 0; i < (int) _vec.size(); ++i)
172 _vec[i] = _point[i + 1] - _point[i];
176 for (
int i = 0; i < (int) _vec.size(); ++i)
177 _vec[i] /= _node[_k + i] - _node[i + 1];
182 template<
typename Po
int_t>
190 template<
typename Po
int_t>
199 template<
typename Po
int_t>
201 u = std::max(std::min(u, (FT) 1), (FT) 0);
202 return eval(u, _point, _k, _node);
207 template<
typename Po
int_t>
209 u = std::max(std::min(u, (FT) 1), (FT) 0);
210 return eval(u, _vec, (_k - 1), _node, 1) * (FT) (_k - 1);
215 template<
typename Po
int_t>
219 std::vector<FT> lengths(steps, 0);
220 std::vector<FT> parameters(steps, 0);
222 for (std::size_t i = 0; i < steps; ++i) {
223 const FT u =
static_cast<FT
>(i) /
static_cast<FT
>(steps - 1);
225 const Point_t pos = eval_f(u);
227 lengths[i] = lengths[i - 1] +
distance(pos, prev_point);
230 FT total_length = lengths.back();
234 auto find_closest_less_or_equal = [](
const std::vector<FT> &sorted_values, FT value,
235 std::size_t start) -> std::size_t {
236 assert(value >= sorted_values.front() && value <= sorted_values.back());
237 std::size_t index = start;
238 while (sorted_values[index] < value)
240 while (sorted_values[index] > value)
245 std::vector<FT> U(steps);
246 for (std::size_t i = 0; i < steps; ++i) {
247 FT u =
static_cast<FT
>(i) /
static_cast<FT
>(steps - 1);
248 FT
length = total_length * u;
249 std::size_t left_index = find_closest_less_or_equal(lengths,
length, i);
250 std::size_t right_index = (lengths[left_index] ==
length) ? left_index : left_index + 1;
251 if (lengths[left_index] == lengths[right_index])
252 u = parameters[left_index];
254 FT left_u = parameters[left_index];
255 FT right_u = parameters[right_index];
256 FT w = (
length - lengths[left_index]) / (lengths[right_index] - lengths[left_index]);
257 u = (1.0f - w) * left_u + w * right_u;
266 template<
typename Po
int_t>
269 assert((
int) _point.size() >= _k);
270 assert(_node.size() == (_k + _point.size()));
271 assert(_point.size() == (_vec.size() + 1));
276 template<
typename Po
int_t>
277 void SplineCurveFitting<Point_t>::set_nodal_vector() {
278 if (_node_type == eOPEN_UNIFORM)
279 set_node_to_open_uniform();
280 else if (_node_type == eUNIFORM)
281 set_node_to_uniform();
286 template<
typename Po
int_t>
287 void SplineCurveFitting<Point_t>::set_node_to_uniform() {
288 const std::size_t n = _point.size() - 1;
289 _node.resize(_k + n + 1);
291 FT step = (FT) 1 / (FT) (n - _k + 2);
292 for (std::size_t i = 0; i < _node.size(); ++i) {
293 _node[i] = ((FT) i) * step - step * (FT) (_k - 1);
299 template<
typename Po
int_t>
300 void SplineCurveFitting<Point_t>::set_node_to_open_uniform() {
301 _node.resize(_k + _point.size());
304 for (
int i = 0; i < (int) _node.size(); ++i) {
307 else if (i >= ((
int) _point.size() + 1))
310 _node[i] = (FT) acc / (FT) (_point.size() + 1 - _k);
318 template<
typename Po
int_t>
319 Point_t SplineCurveFitting<Point_t>::eval(FT u,
320 const std::vector<Point_t> &point,
322 const std::vector<FT> &node,
325 assert((
int) point.size() >= k);
330 while (u > node[dec + k + off])
334 std::vector<Point_t> p_rec(k, Point_t());
335 for (
int i = dec, j = 0; i < (dec + k); ++i, ++j)
338 std::vector<FT> node_rec(k + k - 2, (FT) 0);
339 for (
int i = (dec + 1), j = 0; i < (dec + k + k - 1); ++i, ++j)
340 node_rec[j] = node[i + off];
342 return eval_rec(u, p_rec, k, node_rec);
347 template<
typename Po
int_t>
348 Point_t SplineCurveFitting<Point_t>::eval_rec(FT u,
349 std::vector<Point_t> p_in,
351 std::vector<FT> node_in)
const {
352 if (p_in.size() == 1)
356 std::vector<Point_t> p_out(k - 1, Point_t());
357 for (
int i = 0; i < (k - 1); ++i) {
358 const FT n0 = node_in[i + k - 1];
359 const FT n1 = node_in[i];
360 const FT f0 = (n0 - u) / (n0 - n1);
361 const FT f1 = (u - n1) / (n0 - n1);
363 p_out[i] = p_in[i] * f0 + p_in[i + 1] * f1;
366 std::vector<FT> node_out(node_in.size() - 2);
367 for (
int i = 1, j = 0; i < ((int) node_in.size() - 1); ++i, ++j)
368 node_out[j] = node_in[i];
370 return eval_rec(u, p_out, (k - 1), node_out);
Spline curve fitting for arbitrary dimensions.
Definition: spline_curve_fitting.h:61
SplineCurveFitting(int k=2, Node_e node_type=eOPEN_UNIFORM)
Constructor.
Definition: spline_curve_fitting.h:156
Point_t eval_df(FT u) const
Evaluates speed of the spline.
Definition: spline_curve_fitting.h:208
void set_ctrl_points(const std::vector< Point_t > &point)
Sets the position of the spline control points.
Definition: spline_curve_fitting.h:168
Node_e
Definition: spline_curve_fitting.h:64
@ eOPEN_UNIFORM
Connected to the first and last control points.
Definition: spline_curve_fitting.h:66
void get_ctrl_points(std::vector< Point_t > &points) const
Gets the control points of the spline.
Definition: spline_curve_fitting.h:183
Point_t eval_f(FT u) const
Evaluates position of the spline.
Definition: spline_curve_fitting.h:200
std::vector< FT > get_equally_spaced_parameters(std::size_t steps) const
Gets parameters such that evaluation of the curve positions using these parameters results in equally...
Definition: spline_curve_fitting.h:216
void set_node_type(Node_e type)
Sets the the nodal vector type.
Definition: spline_curve_fitting.h:191
Definition: collider.cpp:182
T distance(const Vec< N, T > &v1, const Vec< N, T > &v2)
Computes the distance between two vectors/points.
Definition: vec.h:295
T length(const Vec< N, T > &v)
Computes the length/magnitude of a vector.
Definition: vec.h:289