Eigen-unsupported  5.0.1-dev+284dcc12
 
Loading...
Searching...
No Matches
Spline.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 20010-2011 Hauke Heibel <hauke.heibel@gmail.com>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_SPLINE_H
11#define EIGEN_SPLINE_H
12
13// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16#include "SplineFwd.h"
17
18namespace Eigen {
36template <typename Scalar_, int Dim_, int Degree_>
37class Spline {
38 public:
39 typedef Scalar_ Scalar;
40 enum { Dimension = Dim_ };
41 enum { Degree = Degree_ };
42
44 typedef typename SplineTraits<Spline>::PointType PointType;
45
47 typedef typename SplineTraits<Spline>::KnotVectorType KnotVectorType;
48
50 typedef typename SplineTraits<Spline>::ParameterVectorType ParameterVectorType;
51
53 typedef typename SplineTraits<Spline>::BasisVectorType BasisVectorType;
54
56 typedef typename SplineTraits<Spline>::BasisDerivativeType BasisDerivativeType;
57
59 typedef typename SplineTraits<Spline>::ControlPointVectorType ControlPointVectorType;
60
66 : m_knots(1, (Degree == Dynamic ? 2 : 2 * Degree + 2)),
67 m_ctrls(ControlPointVectorType::Zero(Dimension, (Degree == Dynamic ? 1 : Degree + 1))) {
68 // in theory this code can go to the initializer list but it will get pretty
69 // much unreadable ...
70 enum { MinDegree = (Degree == Dynamic ? 0 : Degree) };
71 m_knots.template segment<MinDegree + 1>(0) = Array<Scalar, 1, MinDegree + 1>::Zero();
72 m_knots.template segment<MinDegree + 1>(MinDegree + 1) = Array<Scalar, 1, MinDegree + 1>::Ones();
73 }
74
80 template <typename OtherVectorType, typename OtherArrayType>
81 Spline(const OtherVectorType& knots, const OtherArrayType& ctrls) : m_knots(knots), m_ctrls(ctrls) {}
82
87 template <int OtherDegree>
88 Spline(const Spline<Scalar, Dimension, OtherDegree>& spline) : m_knots(spline.knots()), m_ctrls(spline.ctrls()) {}
89
93 const KnotVectorType& knots() const { return m_knots; }
94
98 const ControlPointVectorType& ctrls() const { return m_ctrls; }
99
112
125 typename SplineTraits<Spline>::DerivativeType derivatives(Scalar u, DenseIndex order) const;
126
132 template <int DerivativeOrder>
133 typename SplineTraits<Spline, DerivativeOrder>::DerivativeType derivatives(Scalar u,
134 DenseIndex order = DerivativeOrder) const;
135
152 typename SplineTraits<Spline>::BasisVectorType basisFunctions(Scalar u) const;
153
167 typename SplineTraits<Spline>::BasisDerivativeType basisFunctionDerivatives(Scalar u, DenseIndex order) const;
168
174 template <int DerivativeOrder>
175 typename SplineTraits<Spline, DerivativeOrder>::BasisDerivativeType basisFunctionDerivatives(
176 Scalar u, DenseIndex order = DerivativeOrder) const;
177
181 DenseIndex degree() const;
182
187 DenseIndex span(Scalar u) const;
188
192 static DenseIndex Span(typename SplineTraits<Spline>::Scalar u, DenseIndex degree,
193 const typename SplineTraits<Spline>::KnotVectorType& knots);
194
208
214 static BasisDerivativeType BasisFunctionDerivatives(const Scalar u, const DenseIndex order, const DenseIndex degree,
215 const KnotVectorType& knots);
216
217 private:
218 KnotVectorType m_knots;
219 ControlPointVectorType m_ctrls;
220
221 template <typename DerivativeType>
222 static void BasisFunctionDerivativesImpl(const typename Spline<Scalar_, Dim_, Degree_>::Scalar u,
223 const DenseIndex order, const DenseIndex p,
225 DerivativeType& N_);
226};
227
228template <typename Scalar_, int Dim_, int Degree_>
230 typename SplineTraits<Spline<Scalar_, Dim_, Degree_> >::Scalar u, DenseIndex degree,
231 const typename SplineTraits<Spline<Scalar_, Dim_, Degree_> >::KnotVectorType& knots) {
232 // Piegl & Tiller, "The NURBS Book", A2.1 (p. 68)
233 if (u <= knots(0)) return degree;
234 const Scalar* pos = std::upper_bound(knots.data() + degree - 1, knots.data() + knots.size() - degree - 1, u);
235 return static_cast<DenseIndex>(std::distance(knots.data(), pos) - 1);
236}
237
238template <typename Scalar_, int Dim_, int Degree_>
240 typename Spline<Scalar_, Dim_, Degree_>::Scalar u, DenseIndex degree,
242 const DenseIndex p = degree;
243 const DenseIndex i = Spline::Span(u, degree, knots);
244
245 const KnotVectorType& U = knots;
246
247 BasisVectorType left(p + 1);
248 left(0) = Scalar(0);
249 BasisVectorType right(p + 1);
250 right(0) = Scalar(0);
251
253 u - VectorBlock<const KnotVectorType, Degree>(U, i + 1 - p, p).reverse();
255
256 BasisVectorType N(1, p + 1);
257 N(0) = Scalar(1);
258 for (DenseIndex j = 1; j <= p; ++j) {
259 Scalar saved = Scalar(0);
260 for (DenseIndex r = 0; r < j; r++) {
261 const Scalar tmp = N(r) / (right(r + 1) + left(j - r));
262 N[r] = saved + right(r + 1) * tmp;
263 saved = left(j - r) * tmp;
264 }
265 N(j) = saved;
266 }
267 return N;
268}
269
270template <typename Scalar_, int Dim_, int Degree_>
272 if (Degree_ == Dynamic)
273 return m_knots.size() - m_ctrls.cols() - 1;
274 else
275 return Degree_;
276}
277
278template <typename Scalar_, int Dim_, int Degree_>
280 return Spline::Span(u, degree(), knots());
281}
282
283template <typename Scalar_, int Dim_, int Degree_>
285 enum { Order = SplineTraits<Spline>::OrderAtCompileTime };
286
287 const DenseIndex span = this->span(u);
288 const DenseIndex p = degree();
289 const BasisVectorType basis_funcs = basisFunctions(u);
290
291 const Replicate<BasisVectorType, Dimension, 1> ctrl_weights(basis_funcs);
293 return (ctrl_weights * ctrl_pts).rowwise().sum();
294}
295
296/* --------------------------------------------------------------------------------------------- */
297
298template <typename SplineType, typename DerivativeType>
299void derivativesImpl(const SplineType& spline, typename SplineType::Scalar u, DenseIndex order, DerivativeType& der) {
300 enum { Dimension = SplineTraits<SplineType>::Dimension };
301 enum { Order = SplineTraits<SplineType>::OrderAtCompileTime };
302 enum { DerivativeOrder = DerivativeType::ColsAtCompileTime };
303
304 typedef typename SplineTraits<SplineType>::ControlPointVectorType ControlPointVectorType;
305 typedef typename SplineTraits<SplineType, DerivativeOrder>::BasisDerivativeType BasisDerivativeType;
306 typedef typename BasisDerivativeType::ConstRowXpr BasisDerivativeRowXpr;
307
308 const DenseIndex p = spline.degree();
309 const DenseIndex span = spline.span(u);
310
311 const DenseIndex n = (std::min)(p, order);
312
313 der.resize(Dimension, n + 1);
314
315 // Retrieve the basis function derivatives up to the desired order...
316 const BasisDerivativeType basis_func_ders = spline.template basisFunctionDerivatives<DerivativeOrder>(u, n + 1);
317
318 // ... and perform the linear combinations of the control points.
319 for (DenseIndex der_order = 0; der_order < n + 1; ++der_order) {
320 const Replicate<BasisDerivativeRowXpr, Dimension, 1> ctrl_weights(basis_func_ders.row(der_order));
321 const Block<const ControlPointVectorType, Dimension, Order> ctrl_pts(spline.ctrls(), 0, span - p, Dimension, p + 1);
322 der.col(der_order) = (ctrl_weights * ctrl_pts).rowwise().sum();
323 }
324}
325
326template <typename Scalar_, int Dim_, int Degree_>
327typename SplineTraits<Spline<Scalar_, Dim_, Degree_> >::DerivativeType Spline<Scalar_, Dim_, Degree_>::derivatives(
328 Scalar u, DenseIndex order) const {
329 typename SplineTraits<Spline>::DerivativeType res;
330 derivativesImpl(*this, u, order, res);
331 return res;
332}
333
334template <typename Scalar_, int Dim_, int Degree_>
335template <int DerivativeOrder>
336typename SplineTraits<Spline<Scalar_, Dim_, Degree_>, DerivativeOrder>::DerivativeType
338 typename SplineTraits<Spline, DerivativeOrder>::DerivativeType res;
339 derivativesImpl(*this, u, order, res);
340 return res;
341}
342
343template <typename Scalar_, int Dim_, int Degree_>
344typename SplineTraits<Spline<Scalar_, Dim_, Degree_> >::BasisVectorType Spline<Scalar_, Dim_, Degree_>::basisFunctions(
345 Scalar u) const {
346 return Spline::BasisFunctions(u, degree(), knots());
347}
348
349/* --------------------------------------------------------------------------------------------- */
350
351template <typename Scalar_, int Dim_, int Degree_>
352template <typename DerivativeType>
353void Spline<Scalar_, Dim_, Degree_>::BasisFunctionDerivativesImpl(
354 const typename Spline<Scalar_, Dim_, Degree_>::Scalar u, const DenseIndex order, const DenseIndex p,
355 const typename Spline<Scalar_, Dim_, Degree_>::KnotVectorType& U, DerivativeType& N_) {
356 typedef Spline<Scalar_, Dim_, Degree_> SplineType;
357 enum { Order = SplineTraits<SplineType>::OrderAtCompileTime };
358
359 const DenseIndex span = SplineType::Span(u, p, U);
360
361 const DenseIndex n = (std::min)(p, order);
362
363 N_.resize(n + 1, p + 1);
364
365 BasisVectorType left = BasisVectorType::Zero(p + 1);
366 BasisVectorType right = BasisVectorType::Zero(p + 1);
367
368 Matrix<Scalar, Order, Order> ndu(p + 1, p + 1);
369
370 Scalar saved, temp; // FIXME These were double instead of Scalar. Was there a reason for that?
371
372 ndu(0, 0) = 1.0;
373
374 DenseIndex j;
375 for (j = 1; j <= p; ++j) {
376 left[j] = u - U[span + 1 - j];
377 right[j] = U[span + j] - u;
378 saved = 0.0;
379
380 for (DenseIndex r = 0; r < j; ++r) {
381 /* Lower triangle */
382 ndu(j, r) = right[r + 1] + left[j - r];
383 temp = ndu(r, j - 1) / ndu(j, r);
384 /* Upper triangle */
385 ndu(r, j) = static_cast<Scalar>(saved + right[r + 1] * temp);
386 saved = left[j - r] * temp;
387 }
388
389 ndu(j, j) = static_cast<Scalar>(saved);
390 }
391
392 for (j = p; j >= 0; --j) N_(0, j) = ndu(j, p);
393
394 // Compute the derivatives
395 DerivativeType a(n + 1, p + 1);
396 DenseIndex r = 0;
397 for (; r <= p; ++r) {
398 DenseIndex s1, s2;
399 s1 = 0;
400 s2 = 1; // alternate rows in array a
401 a(0, 0) = 1.0;
402
403 // Compute the k-th derivative
404 for (DenseIndex k = 1; k <= static_cast<DenseIndex>(n); ++k) {
405 Scalar d = 0.0;
406 DenseIndex rk, pk, j1, j2;
407 rk = r - k;
408 pk = p - k;
409
410 if (r >= k) {
411 a(s2, 0) = a(s1, 0) / ndu(pk + 1, rk);
412 d = a(s2, 0) * ndu(rk, pk);
413 }
414
415 if (rk >= -1)
416 j1 = 1;
417 else
418 j1 = -rk;
419
420 if (r - 1 <= pk)
421 j2 = k - 1;
422 else
423 j2 = p - r;
424
425 for (j = j1; j <= j2; ++j) {
426 a(s2, j) = (a(s1, j) - a(s1, j - 1)) / ndu(pk + 1, rk + j);
427 d += a(s2, j) * ndu(rk + j, pk);
428 }
429
430 if (r <= pk) {
431 a(s2, k) = -a(s1, k - 1) / ndu(pk + 1, r);
432 d += a(s2, k) * ndu(r, pk);
433 }
434
435 N_(k, r) = static_cast<Scalar>(d);
436 j = s1;
437 s1 = s2;
438 s2 = j; // Switch rows
439 }
440 }
441
442 /* Multiply through by the correct factors */
443 /* (Eq. [2.9]) */
444 r = p;
445 for (DenseIndex k = 1; k <= static_cast<DenseIndex>(n); ++k) {
446 for (j = p; j >= 0; --j) N_(k, j) *= r;
447 r *= p - k;
448 }
449}
450
451template <typename Scalar_, int Dim_, int Degree_>
452typename SplineTraits<Spline<Scalar_, Dim_, Degree_> >::BasisDerivativeType
454 typename SplineTraits<Spline<Scalar_, Dim_, Degree_> >::BasisDerivativeType der;
455 BasisFunctionDerivativesImpl(u, order, degree(), knots(), der);
456 return der;
457}
458
459template <typename Scalar_, int Dim_, int Degree_>
460template <int DerivativeOrder>
461typename SplineTraits<Spline<Scalar_, Dim_, Degree_>, DerivativeOrder>::BasisDerivativeType
463 typename SplineTraits<Spline<Scalar_, Dim_, Degree_>, DerivativeOrder>::BasisDerivativeType der;
464 BasisFunctionDerivativesImpl(u, order, degree(), knots(), der);
465 return der;
466}
467
468template <typename Scalar_, int Dim_, int Degree_>
469typename SplineTraits<Spline<Scalar_, Dim_, Degree_> >::BasisDerivativeType
471 const typename Spline<Scalar_, Dim_, Degree_>::Scalar u, const DenseIndex order, const DenseIndex degree,
473 typename SplineTraits<Spline>::BasisDerivativeType der;
474 BasisFunctionDerivativesImpl(u, order, degree, knots, der);
475 return der;
476}
477} // namespace Eigen
478
479#endif // EIGEN_SPLINE_H
A class representing multi-dimensional spline curves.
Definition Spline.h:37
Spline(const OtherVectorType &knots, const OtherArrayType &ctrls)
Creates a spline from a knot vector and control points.
Definition Spline.h:81
DenseIndex degree() const
Returns the spline degree.
Definition Spline.h:271
PointType operator()(Scalar u) const
Returns the spline value at a given site .
Definition Spline.h:284
@ Degree
Definition Spline.h:41
const KnotVectorType & knots() const
Definition Spline.h:93
SplineTraits< Spline >::ParameterVectorType ParameterVectorType
The data type used to store parameter vectors.
Definition Spline.h:50
SplineTraits< Spline >::BasisDerivativeType basisFunctionDerivatives(Scalar u, DenseIndex order) const
Computes the non-zero spline basis function derivatives up to given order.
Definition Spline.h:453
Spline(const Spline< Scalar, Dimension, OtherDegree > &spline)
Copy constructor for splines.
Definition Spline.h:88
SplineTraits< Spline, DerivativeOrder >::DerivativeType derivatives(Scalar u, DenseIndex order=DerivativeOrder) const
Evaluation of spline derivatives of up-to given order.
Definition Spline.h:337
SplineTraits< Spline, DerivativeOrder >::BasisDerivativeType basisFunctionDerivatives(Scalar u, DenseIndex order=DerivativeOrder) const
Computes the non-zero spline basis function derivatives up to given order.
Definition Spline.h:462
static DenseIndex Span(typename SplineTraits< Spline >::Scalar u, DenseIndex degree, const typename SplineTraits< Spline >::KnotVectorType &knots)
Computes the span within the provided knot vector in which u is falling.
Definition Spline.h:229
SplineTraits< Spline >::KnotVectorType KnotVectorType
The data type used to store knot vectors.
Definition Spline.h:47
SplineTraits< Spline >::ControlPointVectorType ControlPointVectorType
The data type representing the spline's control points.
Definition Spline.h:59
DenseIndex span(Scalar u) const
Returns the span within the knot vector in which u is falling.
Definition Spline.h:279
Spline()
Creates a (constant) zero spline. For Splines with dynamic degree, the resulting degree will be 0.
Definition Spline.h:65
SplineTraits< Spline >::PointType PointType
The point type the spline is representing.
Definition Spline.h:44
SplineTraits< Spline >::BasisVectorType BasisVectorType
The data type used to store non-zero basis functions.
Definition Spline.h:53
SplineTraits< Spline >::BasisDerivativeType BasisDerivativeType
The data type used to store the values of the basis function derivatives.
Definition Spline.h:56
@ Dimension
Definition Spline.h:40
static BasisDerivativeType BasisFunctionDerivatives(const Scalar u, const DenseIndex order, const DenseIndex degree, const KnotVectorType &knots)
Computes the non-zero spline basis function derivatives up to given order.
Definition Spline.h:470
static BasisVectorType BasisFunctions(Scalar u, DenseIndex degree, const KnotVectorType &knots)
Returns the spline's non-zero basis functions.
Definition Spline.h:239
Scalar_ Scalar
Definition Spline.h:39
SplineTraits< Spline >::DerivativeType derivatives(Scalar u, DenseIndex order) const
Evaluation of spline derivatives of up-to given order.
Definition Spline.h:327
SplineTraits< Spline >::BasisVectorType basisFunctions(Scalar u) const
Computes the non-zero basis functions at the given site.
Definition Spline.h:344
const ControlPointVectorType & ctrls() const
Definition Spline.h:98
Namespace containing all symbols from the Eigen library.
const int Dynamic