Spline.h
Go to the documentation of this file.
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 #include "SplineFwd.h"
14 
15 namespace Eigen
16 {
34  template <typename _Scalar, int _Dim, int _Degree>
35  class Spline
36  {
37  public:
38  typedef _Scalar Scalar;
39  enum { Dimension = _Dim };
40  enum { Degree = _Degree };
41 
44 
47 
50 
53 
58  Spline()
59  : m_knots(1, (Degree==Dynamic ? 2 : 2*Degree+2))
60  , m_ctrls(ControlPointVectorType::Zero(2,(Degree==Dynamic ? 1 : Degree+1)))
61  {
62  // in theory this code can go to the initializer list but it will get pretty
63  // much unreadable ...
64  enum { MinDegree = (Degree==Dynamic ? 0 : Degree) };
65  m_knots.template segment<MinDegree+1>(0) = Array<Scalar,1,MinDegree+1>::Zero();
66  m_knots.template segment<MinDegree+1>(MinDegree+1) = Array<Scalar,1,MinDegree+1>::Ones();
67  }
68 
74  template <typename OtherVectorType, typename OtherArrayType>
75  Spline(const OtherVectorType& knots, const OtherArrayType& ctrls) : m_knots(knots), m_ctrls(ctrls) {}
76 
81  template <int OtherDegree>
83  m_knots(spline.knots()), m_ctrls(spline.ctrls()) {}
84 
88  const KnotVectorType& knots() const { return m_knots; }
89 
93  const ControlPointVectorType& ctrls() const { return m_ctrls; }
94 
106  PointType operator()(Scalar u) const;
107 
121  derivatives(Scalar u, DenseIndex order) const;
122 
128  template <int DerivativeOrder>
130  derivatives(Scalar u, DenseIndex order = DerivativeOrder) const;
131 
149  basisFunctions(Scalar u) const;
150 
165  basisFunctionDerivatives(Scalar u, DenseIndex order) const;
166 
172  template <int DerivativeOrder>
174  basisFunctionDerivatives(Scalar u, DenseIndex order = DerivativeOrder) const;
175 
179  DenseIndex degree() const;
180 
185  DenseIndex span(Scalar u) const;
186 
191 
204  static BasisVectorType BasisFunctions(Scalar u, DenseIndex degree, const KnotVectorType& knots);
205 
206 
207  private:
208  KnotVectorType m_knots;
209  ControlPointVectorType m_ctrls;
210  };
211 
212  template <typename _Scalar, int _Dim, int _Degree>
217  {
218  // Piegl & Tiller, "The NURBS Book", A2.1 (p. 68)
219  if (u <= knots(0)) return degree;
220  const Scalar* pos = std::upper_bound(knots.data()+degree-1, knots.data()+knots.size()-degree-1, u);
221  return static_cast<DenseIndex>( std::distance(knots.data(), pos) - 1 );
222  }
223 
224  template <typename _Scalar, int _Dim, int _Degree>
230  {
232 
233  const DenseIndex p = degree;
234  const DenseIndex i = Spline::Span(u, degree, knots);
235 
236  const KnotVectorType& U = knots;
237 
238  BasisVectorType left(p+1); left(0) = Scalar(0);
239  BasisVectorType right(p+1); right(0) = Scalar(0);
240 
243 
244  BasisVectorType N(1,p+1);
245  N(0) = Scalar(1);
246  for (DenseIndex j=1; j<=p; ++j)
247  {
248  Scalar saved = Scalar(0);
249  for (DenseIndex r=0; r<j; r++)
250  {
251  const Scalar tmp = N(r)/(right(r+1)+left(j-r));
252  N[r] = saved + right(r+1)*tmp;
253  saved = left(j-r)*tmp;
254  }
255  N(j) = saved;
256  }
257  return N;
258  }
259 
260  template <typename _Scalar, int _Dim, int _Degree>
262  {
263  if (_Degree == Dynamic)
264  return m_knots.size() - m_ctrls.cols() - 1;
265  else
266  return _Degree;
267  }
268 
269  template <typename _Scalar, int _Dim, int _Degree>
271  {
272  return Spline::Span(u, degree(), knots());
273  }
274 
275  template <typename _Scalar, int _Dim, int _Degree>
277  {
279 
280  const DenseIndex span = this->span(u);
281  const DenseIndex p = degree();
282  const BasisVectorType basis_funcs = basisFunctions(u);
283 
284  const Replicate<BasisVectorType,Dimension,1> ctrl_weights(basis_funcs);
286  return (ctrl_weights * ctrl_pts).rowwise().sum();
287  }
288 
289  /* --------------------------------------------------------------------------------------------- */
290 
291  template <typename SplineType, typename DerivativeType>
292  void derivativesImpl(const SplineType& spline, typename SplineType::Scalar u, DenseIndex order, DerivativeType& der)
293  {
296  enum { DerivativeOrder = DerivativeType::ColsAtCompileTime };
297 
299  typedef typename SplineTraits<SplineType,DerivativeOrder>::BasisDerivativeType BasisDerivativeType;
300  typedef typename BasisDerivativeType::ConstRowXpr BasisDerivativeRowXpr;
301 
302  const DenseIndex p = spline.degree();
303  const DenseIndex span = spline.span(u);
304 
305  const DenseIndex n = (std::min)(p, order);
306 
307  der.resize(Dimension,n+1);
308 
309  // Retrieve the basis function derivatives up to the desired order...
310  const BasisDerivativeType basis_func_ders = spline.template basisFunctionDerivatives<DerivativeOrder>(u, n+1);
311 
312  // ... and perform the linear combinations of the control points.
313  for (DenseIndex der_order=0; der_order<n+1; ++der_order)
314  {
315  const Replicate<BasisDerivativeRowXpr,Dimension,1> ctrl_weights( basis_func_ders.row(der_order) );
316  const Block<const ControlPointVectorType,Dimension,Order> ctrl_pts(spline.ctrls(),0,span-p,Dimension,p+1);
317  der.col(der_order) = (ctrl_weights * ctrl_pts).rowwise().sum();
318  }
319  }
320 
321  template <typename _Scalar, int _Dim, int _Degree>
322  typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::DerivativeType
324  {
326  derivativesImpl(*this, u, order, res);
327  return res;
328  }
329 
330  template <typename _Scalar, int _Dim, int _Degree>
331  template <int DerivativeOrder>
332  typename SplineTraits< Spline<_Scalar, _Dim, _Degree>, DerivativeOrder >::DerivativeType
334  {
336  derivativesImpl(*this, u, order, res);
337  return res;
338  }
339 
340  template <typename _Scalar, int _Dim, int _Degree>
341  typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::BasisVectorType
343  {
344  return Spline::BasisFunctions(u, degree(), knots());
345  }
346 
347  /* --------------------------------------------------------------------------------------------- */
348 
349  template <typename SplineType, typename DerivativeType>
350  void basisFunctionDerivativesImpl(const SplineType& spline, typename SplineType::Scalar u, DenseIndex order, DerivativeType& N_)
351  {
353 
354  typedef typename SplineTraits<SplineType>::Scalar Scalar;
357 
358  const KnotVectorType& U = spline.knots();
359 
360  const DenseIndex p = spline.degree();
361  const DenseIndex span = spline.span(u);
362 
363  const DenseIndex n = (std::min)(p, order);
364 
365  N_.resize(n+1, p+1);
366 
367  BasisVectorType left = BasisVectorType::Zero(p+1);
368  BasisVectorType right = BasisVectorType::Zero(p+1);
369 
370  Matrix<Scalar,Order,Order> ndu(p+1,p+1);
371 
372  double saved, temp;
373 
374  ndu(0,0) = 1.0;
375 
376  DenseIndex j;
377  for (j=1; j<=p; ++j)
378  {
379  left[j] = u-U[span+1-j];
380  right[j] = U[span+j]-u;
381  saved = 0.0;
382 
383  for (DenseIndex r=0; r<j; ++r)
384  {
385  /* Lower triangle */
386  ndu(j,r) = right[r+1]+left[j-r];
387  temp = ndu(r,j-1)/ndu(j,r);
388  /* Upper triangle */
389  ndu(r,j) = static_cast<Scalar>(saved+right[r+1] * temp);
390  saved = left[j-r] * temp;
391  }
392 
393  ndu(j,j) = static_cast<Scalar>(saved);
394  }
395 
396  for (j = p; j>=0; --j)
397  N_(0,j) = ndu(j,p);
398 
399  // Compute the derivatives
400  DerivativeType a(n+1,p+1);
401  DenseIndex r=0;
402  for (; r<=p; ++r)
403  {
404  DenseIndex s1,s2;
405  s1 = 0; s2 = 1; // alternate rows in array a
406  a(0,0) = 1.0;
407 
408  // Compute the k-th derivative
409  for (DenseIndex k=1; k<=static_cast<DenseIndex>(n); ++k)
410  {
411  double d = 0.0;
412  DenseIndex rk,pk,j1,j2;
413  rk = r-k; pk = p-k;
414 
415  if (r>=k)
416  {
417  a(s2,0) = a(s1,0)/ndu(pk+1,rk);
418  d = a(s2,0)*ndu(rk,pk);
419  }
420 
421  if (rk>=-1) j1 = 1;
422  else j1 = -rk;
423 
424  if (r-1 <= pk) j2 = k-1;
425  else j2 = p-r;
426 
427  for (j=j1; j<=j2; ++j)
428  {
429  a(s2,j) = (a(s1,j)-a(s1,j-1))/ndu(pk+1,rk+j);
430  d += a(s2,j)*ndu(rk+j,pk);
431  }
432 
433  if (r<=pk)
434  {
435  a(s2,k) = -a(s1,k-1)/ndu(pk+1,r);
436  d += a(s2,k)*ndu(r,pk);
437  }
438 
439  N_(k,r) = static_cast<Scalar>(d);
440  j = s1; s1 = s2; s2 = j; // Switch rows
441  }
442  }
443 
444  /* Multiply through by the correct factors */
445  /* (Eq. [2.9]) */
446  r = p;
447  for (DenseIndex k=1; k<=static_cast<DenseIndex>(n); ++k)
448  {
449  for (DenseIndex j=p; j>=0; --j) N_(k,j) *= r;
450  r *= p-k;
451  }
452  }
453 
454  template <typename _Scalar, int _Dim, int _Degree>
455  typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::BasisDerivativeType
457  {
459  basisFunctionDerivativesImpl(*this, u, order, der);
460  return der;
461  }
462 
463  template <typename _Scalar, int _Dim, int _Degree>
464  template <int DerivativeOrder>
465  typename SplineTraits< Spline<_Scalar, _Dim, _Degree>, DerivativeOrder >::BasisDerivativeType
467  {
469  basisFunctionDerivativesImpl(*this, u, order, der);
470  return der;
471  }
472 }
473 
474 #endif // EIGEN_SPLINE_H
A class representing multi-dimensional spline curves.
Definition: Spline.h:35
void derivativesImpl(const SplineType &spline, typename SplineType::Scalar u, DenseIndex order, DerivativeType &der)
Definition: Spline.h:292
#define N
static BasisVectorType BasisFunctions(Scalar u, DenseIndex degree, const KnotVectorType &knots)
Returns the spline&#39;s non-zero basis functions.
Definition: Spline.h:226
SplineTraits< Spline >::PointType PointType
The point type the spline is representing.
Definition: Spline.h:43
DenseIndex degree() const
Returns the spline degree.
Definition: Spline.h:261
KnotVectorType m_knots
Definition: Spline.h:208
SplineTraits< Spline >::BasisVectorType basisFunctions(Scalar u) const
Computes the non-zero basis functions at the given site.
Definition: Spline.h:342
iterative scaling algorithm to equilibrate rows and column norms in matrices
Definition: matrix.hpp:471
DenseIndex span(Scalar u) const
Returns the span within the knot vector in which u is falling.
Definition: Spline.h:270
Expression of a fixed-size or dynamic-size sub-vector.
const ControlPointVectorType & ctrls() const
Returns the knots of the underlying spline.
Definition: Spline.h:93
ControlPointVectorType m_ctrls
Definition: Spline.h:209
Spline()
Creates a (constant) zero spline. For Splines with dynamic degree, the resulting degree will be 0...
Definition: Spline.h:58
Expression of the multiple replication of a matrix or vector.
Definition: Replicate.h:62
PointType operator()(Scalar u) const
Returns the spline value at a given site .
Definition: Spline.h:276
const Block< const Derived, 1, internal::traits< Derived >::ColsAtCompileTime, IsRowMajor > ConstRowXpr
Definition: BlockMethods.h:19
static DenseIndex Span(typename SplineTraits< Spline >::Scalar u, DenseIndex degree, const typename SplineTraits< Spline >::KnotVectorType &knots)
Computes the spang within the provided knot vector in which u is falling.
Definition: Spline.h:213
SplineTraits< Spline >::BasisDerivativeType basisFunctionDerivatives(Scalar u, DenseIndex order) const
Computes the non-zero spline basis function derivatives up to given order.
Definition: Spline.h:456
const KnotVectorType & knots() const
Returns the knots of the underlying spline.
Definition: Spline.h:88
EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex
Definition: XprHelper.h:27
SplineTraits< Spline >::ControlPointVectorType ControlPointVectorType
The data type representing the spline&#39;s control points.
Definition: Spline.h:52
SplineTraits< Spline >::DerivativeType derivatives(Scalar u, DenseIndex order) const
Evaluation of spline derivatives of up-to given order.
Definition: Spline.h:323
Spline(const Spline< Scalar, Dimension, OtherDegree > &spline)
Copy constructor for splines.
Definition: Spline.h:82
Expression of a fixed-size or dynamic-size block.
Definition: Core/Block.h:102
void basisFunctionDerivativesImpl(const SplineType &spline, typename SplineType::Scalar u, DenseIndex order, DerivativeType &N_)
Definition: Spline.h:350
Spline(const OtherVectorType &knots, const OtherArrayType &ctrls)
Creates a spline from a knot vector and control points.
Definition: Spline.h:75
General-purpose arrays with easy API for coefficient-wise operations.
Definition: Array.h:42
SplineTraits< Spline >::BasisVectorType BasisVectorType
The data type used to store non-zero basis functions.
Definition: Spline.h:49
SplineTraits< Spline >::KnotVectorType KnotVectorType
The data type used to store knot vectors.
Definition: Spline.h:46
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:127
_Scalar Scalar
Definition: Spline.h:38


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:35:10