Easy3D 2.5.3
spline_curve_interpolation.h
1/********************************************************************
2 * Copyright (C) 2015 Liangliang Nan <liangliang.nan@gmail.com>
3 * https://3d.bk.tudelft.nl/liangliang/
4 *
5 * This file is part of Easy3D. If it is useful in your research/work,
6 * I would be grateful if you show your appreciation by citing it:
7 * ------------------------------------------------------------------
8 * Liangliang Nan.
9 * Easy3D: a lightweight, easy-to-use, and efficient C++ library
10 * for processing and rendering 3D data.
11 * Journal of Open Source Software, 6(64), 3255, 2021.
12 * ------------------------------------------------------------------
13 *
14 * Easy3D is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License Version 3
16 * as published by the Free Software Foundation.
17 *
18 * Easy3D is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ********************************************************************/
26
27#ifndef EASY3D_CORE_SPLINE_CURVE_INTERPOLATION_H
28#define EASY3D_CORE_SPLINE_CURVE_INTERPOLATION_H
29
30
31#include <vector>
32#include <cassert>
33
34#include <easy3d/core/spline_interpolation.h>
35
36
37namespace easy3d {
38
39
58 template<typename Point_t>
60 public:
61 typedef typename Point_t::FT FT;
62
63 enum BoundaryType {
64 first_deriv = 1,
65 second_deriv = 2
66 };
67
68 public:
69
74 SplineCurveInterpolation() : left_(second_deriv), right_(second_deriv),
75 left_value_(0.0), right_value_(0.0), dim_(0), largest_t_(0.0) {
76 }
77
82 void set_boundary(BoundaryType left, FT left_value,
83 BoundaryType right, FT right_value);
84
93 void set_points(const std::vector<FT> &parameters, const std::vector<Point_t> &points, bool cubic_spline = true);
94
103 void set_points(const std::vector<Point_t> &points, bool cubic_spline = true);
104
110 Point_t eval_f(FT u) const;
111
112 private:
113 // -------------------------------------------------------------------------
115 // -------------------------------------------------------------------------
116 BoundaryType left_, right_;
117 FT left_value_, right_value_;
118
119 std::size_t dim_;
120 std::vector< SplineInterpolation<FT> > interpolators_;
121 FT largest_t_;
122 };
123
124
125
126 // Cubic spline interpolation implementation
127 // -----------------------
128
129 template<typename Point_t>
130 void SplineCurveInterpolation<Point_t>::set_boundary(typename SplineCurveInterpolation<Point_t>::BoundaryType left,
131 FT left_value,
132 typename SplineCurveInterpolation<Point_t>::BoundaryType right,
133 FT right_value) {
134 assert(interpolators_.size() == 0); // set_points() must not have happened yet
135 left_ = left;
136 right_ = right;
137 left_value_ = left_value;
138 right_value_ = right_value;
139 }
140
141
142 template<typename Point_t>
143 void SplineCurveInterpolation<Point_t>::set_points(const std::vector<FT> &input_parameters,
144 const std::vector<Point_t> &input_points, bool cubic_spline) {
145 if (input_parameters.empty() || input_parameters.size() != input_points.size())
146 return;
147
148 // filter out non-monotone data
149 std::vector<FT> parameters;
150 std::vector<Point_t> points;
151 for (std::size_t i=0; i<input_parameters.size(); ++i) {
152 const FT para = input_parameters[i];
153 if (i == 0 || para > parameters.back()) {
154 parameters.push_back(para);
155 points.push_back(input_points[i]);
156 }
157 }
158 const auto diff = input_points.size() - points.size();
159 LOG_IF(diff > 0, WARNING) << diff << " data points discarded because the input has to be monotonously increasing";
160
161 dim_ = points[0].dimension();
162 largest_t_ = parameters.back();
163
164 // an ND curve is represented in the parametric form: x1(t), x2(t), x3(t)...
165 std::vector< std::vector<FT> > coords(dim_, std::vector<FT>(points.size()));
166
167 FT t(0);
168 for (std::size_t i = 0; i < points.size(); ++i) {
169 const auto &p = points[i];
170 if (i > 0)
171 t += distance(points[i-1], p);
172 for (std::size_t j = 0; j<dim_; ++j)
173 coords[j][i] = p[j];
174 }
175
176 // class instantiation
177 interpolators_.resize(dim_);
178 for (std::size_t i=0; i<dim_; ++i) {
179 // set boundary condition
180 interpolators_[i].set_boundary(
182 left_value_,
184 right_value_,
185 cubic_spline
186 );
187 // set data
188 interpolators_[i].set_data(parameters, coords[i]);
189 }
190 }
191
192
193 template<typename Point_t>
194 void SplineCurveInterpolation<Point_t>::set_points(const std::vector<Point_t> &points, bool cubic_spline) {
195 if (points.size() < 2)
196 return;
197
198 // we use the accumulated curve distance as the parameters
199 std::vector<FT> parameters(points.size(), FT(0));
200
201 FT t(0);
202 for (std::size_t i = 1; i < points.size(); ++i) {
203 const auto &p = points[i];
204 t += distance(points[i-1], p);
205 parameters[i] = t;
206 }
207
208 set_points(parameters, points, cubic_spline);
209 }
210
211
212 template<typename Point_t>
214 Point_t p;
215 for (std::size_t i=0; i<dim_; ++i)
216 p[i] = interpolators_[i](u * largest_t_);
217 return p;
218 }
219
220
221} // namespace easy3d
222
223
224#endif // EASY3D_CORE_SPLINE_CURVE_INTERPOLATION_H
Cubic spline curve interpolation for arbitrary dimensions.
Definition: spline_curve_interpolation.h:59
void set_points(const std::vector< FT > &parameters, const std::vector< Point_t > &points, bool cubic_spline=true)
Definition: spline_curve_interpolation.h:143
SplineCurveInterpolation()
Definition: spline_curve_interpolation.h:74
void set_boundary(BoundaryType left, FT left_value, BoundaryType right, FT right_value)
Definition: spline_curve_interpolation.h:130
Point_t eval_f(FT u) const
Definition: spline_curve_interpolation.h:213
Cubic spline interpolation.
Definition: spline_interpolation.h:85
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