GCC Code Coverage Report


Directory: ./
File: include/ndcurves/cubic_hermite_spline.h
Date: 2025-03-05 17:18:30
Exec Total Coverage
Lines: 137 148 92.6%
Branches: 100 190 52.6%

Line Branch Exec Source
1 /**
2 * \file cubic_hermite_spline.h
3 * \brief class allowing to create a cubic hermite spline of any dimension.
4 * \author Justin Carpentier <jcarpent@laas.fr> modified by Jason Chemin
5 * <jchemin@laas.fr> \date 05/2019
6 */
7
8 #ifndef _CLASS_CUBICHERMITESPLINE
9 #define _CLASS_CUBICHERMITESPLINE
10
11 #include <boost/serialization/utility.hpp> // To serialize std::pair
12 #include <iostream>
13 #include <stdexcept>
14 #include <vector>
15
16 #include "MathDefs.h"
17 #include "bezier_curve.h"
18 #include "curve_abc.h"
19 #include "piecewise_curve.h"
20
21 namespace ndcurves {
22 /// \class CubicHermiteSpline.
23 /// \brief Represents a set of cubic hermite splines defining a continuous
24 /// function \f$p(t)\f$. A hermite cubic spline is a minimal degree polynom
25 /// interpolating a function in two points \f$P_i\f$ and \f$P_{i+1}\f$ with its
26 /// tangent \f$m_i\f$ and \f$m_{i+1}\f$.<br> A hermite cubic spline :
27 /// - crosses each of the waypoint given in its initialization (\f$P_0\f$,
28 /// \f$P_1\f$,...,\f$P_N\f$).
29 /// - has its derivatives on \f$P_i\f$ and \f$P_{i+1}\f$ are \f$p'(t_{P_i}) =
30 /// m_i\f$ and \f$p'(t_{P_{i+1}}) = m_{i+1}\f$.
31 ///
32 template <typename Time = double, typename Numeric = Time, bool Safe = false,
33 typename Point = Eigen::Matrix<Numeric, Eigen::Dynamic, 1> >
34 struct cubic_hermite_spline : public curve_abc<Time, Numeric, Safe, Point> {
35 typedef Point point_t;
36 typedef std::pair<Point, Point> pair_point_tangent_t;
37 typedef std::vector<pair_point_tangent_t,
38 Eigen::aligned_allocator<pair_point_tangent_t> >
39 t_pair_point_tangent_t;
40 typedef std::vector<Time> vector_time_t;
41 typedef Time time_t;
42 typedef Numeric num_t;
43 typedef curve_abc<Time, Numeric, Safe, point_t> curve_abc_t; // parent class
44 typedef cubic_hermite_spline<Time, Numeric, Safe, point_t>
45 cubic_hermite_spline_t;
46 typedef bezier_curve<Time, Numeric, Safe, point_t> bezier_t;
47 typedef typename bezier_t::t_point_t t_point_t;
48 typedef piecewise_curve<Time, Numeric, Safe, point_t, point_t, bezier_t>
49 piecewise_bezier_t;
50
51 public:
52 /// \brief Empty constructor. Curve obtained this way can not perform other
53 /// class functions.
54 ///
55
1/2
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
22 cubic_hermite_spline() : dim_(0), T_min_(0), T_max_(0) {}
56
57 /// \brief Constructor.
58 /// \param PairsBegin : an iterator pointing to the first element of a
59 /// pair(position, derivative) container. \param PairsEnd : an iterator
60 /// pointing to the last element of a pair(position, derivative) container.
61 /// \param time_control_points : vector containing time for each waypoint.
62 ///
63 template <typename In>
64 49 cubic_hermite_spline(In PairsBegin, In PairsEnd,
65 const vector_time_t& time_control_points)
66
2/4
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 29 times.
✗ Branch 8 not taken.
49 : size_(std::distance(PairsBegin, PairsEnd)), degree_(3) {
67 // Check size of pairs container.
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
49 if (Safe && size_ < 1) {
69 throw std::length_error(
70 "can not create cubic_hermite_spline, number of pairs is inferior to "
71 "2.");
72 }
73 // Set dimension according to size of points
74 49 dim_ = PairsBegin->first.size();
75 // Push all pairs in controlPoints
76 49 In it(PairsBegin);
77
2/2
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 29 times.
149 for (; it != PairsEnd; ++it) {
78
2/4
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 59 times.
200 if (Safe && (static_cast<size_t>(it->first.size()) != dim_ ||
79
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
100 static_cast<size_t>(it->second.size()) != dim_))
80 throw std::invalid_argument(
81 "All the control points and their derivatives must have the same "
82 "dimension.");
83
1/2
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
100 control_points_.push_back(*it);
84 }
85 // Set time
86
1/2
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
49 setTime(time_control_points);
87 49 }
88
89 13 cubic_hermite_spline(const cubic_hermite_spline& other)
90 13 : dim_(other.dim_),
91 13 control_points_(other.control_points_),
92
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 time_control_points_(other.time_control_points_),
93
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 duration_splines_(other.duration_splines_),
94 13 T_min_(other.T_min_),
95 13 T_max_(other.T_max_),
96 13 size_(other.size_),
97
1/2
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
26 degree_(other.degree_) {}
98
99 /// \brief Destructor.
100 140 virtual ~cubic_hermite_spline() {}
101
102 /*Operations*/
103 public:
104 /// \brief Evaluation of the cubic hermite spline at time t.
105 /// \param t : time when to evaluate the spline.
106 /// \return \f$p(t)\f$ point corresponding on spline at time t.
107 ///
108 4354 virtual Point operator()(const time_t t) const {
109 4354 check_conditions();
110
3/6
✓ Branch 0 taken 2177 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2177 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2177 times.
4354 if (Safe & !(T_min_ <= t && t <= T_max_)) {
111 throw std::invalid_argument(
112 "can't evaluate cubic hermite spline, out of range");
113 }
114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2177 times.
4354 if (size_ == 1) {
115 return control_points_.front().first;
116 } else {
117
1/2
✓ Branch 1 taken 2177 times.
✗ Branch 2 not taken.
4354 const bezier_t bezier = buildCurrentBezier(t);
118
1/2
✓ Branch 1 taken 2177 times.
✗ Branch 2 not taken.
4354 return bezier(t);
119 }
120 }
121
122 /**
123 * @brief isApprox check if other and *this are approximately equals.
124 * Only two curves of the same class can be approximately equals, for
125 * comparison between different type of curves see isEquivalent
126 * @param other the other curve to check
127 * @param prec the precision threshold, default
128 * Eigen::NumTraits<Numeric>::dummy_precision()
129 * @return true is the two curves are approximately equals
130 */
131 14 bool isApprox(
132 const cubic_hermite_spline_t& other,
133 const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision()) const {
134
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
28 bool equal = ndcurves::isApprox<num_t>(T_min_, other.min()) &&
135 14 ndcurves::isApprox<num_t>(T_max_, other.max()) &&
136
3/6
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
28 dim_ == other.dim() && degree_ == other.degree() &&
137 14 size_ == other.size() &&
138
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
42 time_control_points_ == other.time_control_points_ &&
139
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
14 duration_splines_ == other.duration_splines_;
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
14 if (!equal) return false;
141
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6 times.
40 for (std::size_t i = 0; i < size_; ++i) {
142 28 if ((!control_points_[i].first.isApprox(other.control_points_[i].first,
143
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13 times.
54 prec)) ||
144
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
26 (!control_points_[i].second.isApprox(other.control_points_[i].second,
145 prec)))
146 2 return false;
147 }
148 12 return true;
149 }
150
151 4 virtual bool isApprox(
152 const curve_abc_t* other,
153 const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision()) const {
154 4 const cubic_hermite_spline_t* other_cast =
155
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 dynamic_cast<const cubic_hermite_spline_t*>(other);
156
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 if (other_cast)
157 4 return isApprox(*other_cast, prec);
158 else
159 return false;
160 }
161
162 10 virtual bool operator==(const cubic_hermite_spline_t& other) const {
163 10 return isApprox(other);
164 }
165
166 4 virtual bool operator!=(const cubic_hermite_spline_t& other) const {
167 4 return !(*this == other);
168 }
169
170 /// \brief Evaluate the derivative of order N of spline at time t.
171 /// \param t : time when to evaluate the spline.
172 /// \param order : order of derivative.
173 /// \return \f$\frac{d^Np(t)}{dt^N}\f$ point corresponding on derivative
174 /// spline of order N at time t.
175 ///
176 412 virtual Point derivate(const time_t t, const std::size_t order) const {
177 412 check_conditions();
178
3/6
✓ Branch 0 taken 206 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 206 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 206 times.
412 if (Safe & !(T_min_ <= t && t <= T_max_)) {
179 throw std::invalid_argument(
180 "can't derivate cubic hermite spline, out of range");
181 }
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206 times.
412 if (size_ == 1) {
183 return control_points_.front().second;
184 } else {
185
1/2
✓ Branch 1 taken 206 times.
✗ Branch 2 not taken.
412 const bezier_t bezier = buildCurrentBezier(t);
186
1/2
✓ Branch 1 taken 206 times.
✗ Branch 2 not taken.
412 return bezier.derivate(t, order);
187 }
188 }
189
190 8 piecewise_bezier_t compute_derivate(const std::size_t order) const {
191 8 piecewise_bezier_t res;
192
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
24 for (size_t i = 0; i < size_ - 1; ++i) {
193
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
16 const bezier_t curve = buildCurrentBezier(time_control_points_[i]);
194
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
16 res.add_curve(curve.compute_derivate(order));
195 }
196 8 return res;
197 }
198
199 /// \brief Compute the derived curve at order N.
200 /// \param order : order of derivative.
201 /// \return A pointer to \f$\frac{d^Nx(t)}{dt^N}\f$ derivative order N of the
202 /// curve.
203 8 piecewise_bezier_t* compute_derivate_ptr(const std::size_t order) const {
204
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 return new piecewise_bezier_t(compute_derivate(order));
205 }
206
207 /// \brief Set time of each control point of cubic hermite spline.
208 /// Set duration of each spline, Exemple : \f$( 0., 0.5, 0.9, ..., 4.5 )\f$
209 /// with values corresponding to times for \f$P_0, P_1, P_2, ..., P_N\f$
210 /// respectively.<br> \param time_control_points : Vector containing time for
211 /// each control point.
212 ///
213 30 void setTime(const vector_time_t& time_control_points) {
214 30 time_control_points_ = time_control_points;
215 30 T_min_ = time_control_points_.front();
216 30 T_max_ = time_control_points_.back();
217
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
30 if (time_control_points.size() != size()) {
218 throw std::length_error(
219 "size of time control points should be equal to number of control "
220 "points");
221 }
222 30 computeDurationSplines();
223
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (!checkDurationSplines()) {
224 throw std::invalid_argument(
225 "time_splines not monotonous, all spline duration should be superior "
226 "to 0");
227 }
228 30 }
229
230 /// \brief Get vector of pair (positition, derivative) corresponding to
231 /// control points. \return vector containing control points.
232 ///
233 t_pair_point_tangent_t getControlPoints() { return control_points_; }
234
235 /// \brief Get vector of Time corresponding to Time for each control point.
236 /// \return vector containing time of each control point.
237 ///
238 1 vector_time_t getTime() { return time_control_points_; }
239
240 /// \brief Get number of control points contained in the trajectory.
241 /// \return number of control points.
242 ///
243 198 std::size_t size() const { return size_; }
244
245 /// \brief Get number of intervals (subsplines) contained in the trajectory.
246 /// \return number of intervals (subsplines).
247 ///
248 std::size_t numIntervals() const { return size() - 1; }
249
250 private:
251 /// \brief Get index of the interval (subspline) corresponding to time t for
252 /// the interpolation. \param t : time where to look for interval. \return
253 /// Index of interval for time t.
254 ///
255 4782 std::size_t findInterval(const time_t t) const {
256 // time before first control point time.
257
2/2
✓ Branch 1 taken 77 times.
✓ Branch 2 taken 2314 times.
4782 if (t <= time_control_points_[0]) {
258 154 return 0;
259 }
260 // time is after last control point time
261
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 2282 times.
4628 if (t >= time_control_points_[size_ - 1]) {
262 64 return size_ - 2;
263 }
264 4564 std::size_t left_id = 0;
265 4564 std::size_t right_id = size_ - 1;
266
2/2
✓ Branch 0 taken 4552 times.
✓ Branch 1 taken 2270 times.
13644 while (left_id <= right_id) {
267 9104 const std::size_t middle_id = left_id + (right_id - left_id) / 2;
268
2/2
✓ Branch 1 taken 2270 times.
✓ Branch 2 taken 2282 times.
9104 if (time_control_points_.at(middle_id) < t) {
269 4540 left_id = middle_id + 1;
270
2/2
✓ Branch 1 taken 2270 times.
✓ Branch 2 taken 12 times.
4564 } else if (time_control_points_.at(middle_id) > t) {
271 4540 right_id = middle_id - 1;
272 } else {
273 24 return middle_id;
274 }
275 }
276 4540 return left_id - 1;
277 }
278
279 /**
280 * @brief buildCurrentBezier set up the current_bezier_ attribut to represent
281 * the curve of the interval that contain t. This bezier is defined by the
282 * following control points: p0, p0 + m0/3, p1 - m1/3, p1
283 * @param t the time for which the bezier is build
284 * @return the bezier curve
285 */
286 4782 bezier_t buildCurrentBezier(const time_t t) const {
287
1/2
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
4782 size_t id_interval = findInterval(t);
288
2/4
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2391 times.
✗ Branch 5 not taken.
4782 const pair_point_tangent_t pair0 = control_points_.at(id_interval);
289
2/4
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2391 times.
✗ Branch 5 not taken.
4782 const pair_point_tangent_t pair1 = control_points_.at(id_interval + 1);
290 4782 const Time& t0 = time_control_points_[id_interval];
291 4782 const Time& t1 = time_control_points_[id_interval + 1];
292
1/2
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
4782 t_point_t control_points;
293
1/2
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
4782 control_points.reserve(4);
294
1/2
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
4782 control_points.push_back(pair0.first);
295
5/10
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2391 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2391 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2391 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2391 times.
✗ Branch 14 not taken.
4782 control_points.push_back(pair0.first + pair0.second / 3. * (t1 - t0));
296
5/10
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2391 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2391 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2391 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2391 times.
✗ Branch 14 not taken.
4782 control_points.push_back(pair1.first - pair1.second / 3. * (t1 - t0));
297
1/2
✓ Branch 1 taken 2391 times.
✗ Branch 2 not taken.
4782 control_points.push_back(pair1.first);
298
1/2
✓ Branch 3 taken 2391 times.
✗ Branch 4 not taken.
9564 return bezier_t(control_points.begin(), control_points.end(), t0, t1);
299 }
300
301 /// \brief Check if control points list is not empty and dimension of point
302 /// superior to zero.
303 ///
304 4766 void check_conditions() const {
305
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2383 times.
4766 if (control_points_.size() == 0) {
306 throw std::runtime_error(
307 "Error in cubic hermite : there is no control points set / did you "
308 "use empty constructor ?");
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2383 times.
4766 } else if (dim_ == 0) {
310 throw std::runtime_error(
311 "Error in cubic hermite : Dimension of points is zero / did you use "
312 "empty constructor ?");
313 }
314 }
315
316 /// \brief compute duration of each spline.
317 /// For N control points with time \f$T_{P_0}, T_{P_1}, T_{P_2}, ...,
318 /// T_{P_N}\f$ respectively, Duration of each subspline is : (
319 /// T_{P_1}-T_{P_0}, T_{P_2}-T_{P_1}, ..., T_{P_N}-T_{P_{N-1} ).
320 ///
321 30 void computeDurationSplines() {
322 30 duration_splines_.clear();
323 Time actual_time;
324 30 Time prev_time = *(time_control_points_.begin());
325 30 std::size_t i = 0;
326
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 30 times.
62 for (i = 0; i < size() - 1; i++) {
327 32 actual_time = time_control_points_.at(i + 1);
328
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 duration_splines_.push_back(actual_time - prev_time);
329 32 prev_time = actual_time;
330 }
331 30 }
332
333 /// \brief Check if duration of each subspline is strictly positive.
334 /// \return true if all duration of strictly positive, false otherwise.
335 ///
336 30 bool checkDurationSplines() const {
337 30 std::size_t i = 0;
338 30 bool is_positive = true;
339
5/6
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 30 times.
62 while (is_positive && i < duration_splines_.size()) {
340 32 is_positive = (duration_splines_.at(i) > 0.);
341 32 i++;
342 }
343 30 return is_positive;
344 }
345 /*Operations*/
346
347 /*Helpers*/
348 public:
349 /// \brief Get dimension of curve.
350 /// \return dimension of curve.
351 60 std::size_t virtual dim() const { return dim_; }
352 /// \brief Get the minimum time for which the curve is defined
353 /// \return \f$t_{min}\f$, lower bound of time range.
354 160 Time virtual min() const { return time_control_points_.front(); }
355 /// \brief Get the maximum time for which the curve is defined.
356 /// \return \f$t_{max}\f$, upper bound of time range.
357 364 Time virtual max() const { return time_control_points_.back(); }
358 /// \brief Get the degree of the curve.
359 /// \return \f$degree\f$, the degree of the curve.
360 48 virtual std::size_t degree() const { return degree_; }
361 /*Helpers*/
362
363 /*Attributes*/
364 /// Dim of curve
365 std::size_t dim_;
366 /// Vector of pair < Point, Tangent >.
367 t_pair_point_tangent_t control_points_;
368 /// Vector of Time corresponding to time of each N control points : time at
369 /// \f$P_0, P_1, P_2, ..., P_N\f$. Exemple : \f$( 0., 0.5, 0.9, ..., 4.5 )\f$
370 /// with values corresponding to times for \f$P_0, P_1, P_2, ..., P_N\f$
371 /// respectively.
372 vector_time_t time_control_points_;
373 /// Vector of Time corresponding to time duration of each subspline.<br>
374 /// For N control points with time \f$T_{P_0}, T_{P_1}, T_{P_2}, ...,
375 /// T_{P_N}\f$ respectively, duration of each subspline is : (
376 /// T_{P_1}-T_{P_0}, T_{P_2}-T_{P_1}, ..., T_{P_N}-T_{P_{N-1} )<br> It
377 /// contains \f$N-1\f$ durations.
378 vector_time_t duration_splines_;
379 /// Starting time of cubic hermite spline : T_min_ is equal to first time of
380 /// control points.
381 /*const*/ Time T_min_;
382 /// Ending time of cubic hermite spline : T_max_ is equal to last time of
383 /// control points.
384 /*const*/ Time T_max_;
385 /// Number of control points (pairs).
386 std::size_t size_;
387 /// Degree (Cubic so degree 3)
388 std::size_t degree_;
389 /*Attributes*/
390
391 // Serialization of the class
392 friend class boost::serialization::access;
393
394 template <class Archive>
395 44 void serialize(Archive& ar, const unsigned int version) {
396 if (version) {
397 // Do something depending on version ?
398 }
399
1/2
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
44 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(curve_abc_t);
400
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 ar& boost::serialization::make_nvp("dim", dim_);
401
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 ar& boost::serialization::make_nvp("control_points", control_points_);
402
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 ar& boost::serialization::make_nvp("time_control_points",
403 44 time_control_points_);
404
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 ar& boost::serialization::make_nvp("duration_splines", duration_splines_);
405
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 ar& boost::serialization::make_nvp("T_min", T_min_);
406
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 ar& boost::serialization::make_nvp("T_max", T_max_);
407
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 ar& boost::serialization::make_nvp("size", size_);
408
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
44 ar& boost::serialization::make_nvp("degree", degree_);
409 }
410 }; // End struct Cubic hermite spline
411 } // namespace ndcurves
412
413 DEFINE_CLASS_TEMPLATE_VERSION(
414 SINGLE_ARG(typename Time, typename Numeric, bool Safe, typename Point),
415 SINGLE_ARG(ndcurves::cubic_hermite_spline<Time, Numeric, Safe, Point>))
416 #endif //_CLASS_CUBICHERMITESPLINE
417