13 #ifndef AIKIDO_COMMON_BSPLINE_HPP_ 
   14 #define AIKIDO_COMMON_BSPLINE_HPP_ 
   38 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
   89     m_knots.template segment<MinDegree + 1>(0)
 
   90         = Eigen::Array<Scalar, 1, MinDegree + 1>::Zero();
 
   91     m_knots.template segment<MinDegree + 1>(MinDegree + 1)
 
   92         = Eigen::Array<Scalar, 1, MinDegree + 1>::Ones();
 
  100   template <
typename OtherVectorType, 
typename OtherArrayType>
 
  110   template <
int OtherDegree>
 
  168       Scalar u, Eigen::DenseIndex order) 
const;
 
  175   template <
int DerivativeOrder>
 
  177       Scalar u, Eigen::DenseIndex order = DerivativeOrder) 
const;
 
  214       Scalar u, Eigen::DenseIndex order) 
const;
 
  221   template <
int DerivativeOrder>
 
  224       Scalar u, Eigen::DenseIndex order = DerivativeOrder) 
const;
 
  229   Eigen::DenseIndex 
degree() 
const;
 
  241   static Eigen::DenseIndex 
Span(
 
  268       const Eigen::DenseIndex order,
 
  269       const Eigen::DenseIndex 
degree,
 
  276   template <
typename DerivativeType>
 
  279       const Eigen::DenseIndex order,
 
  280       const Eigen::DenseIndex p,
 
  285 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  288     Eigen::DenseIndex degree,
 
  295   const Scalar* pos = std::upper_bound(
 
  296       knots.data() + degree - 1, knots.data() + knots.size() - degree - 1, u);
 
  297   return static_cast<Eigen::DenseIndex
>(std::distance(knots.data(), pos) - 1);
 
  300 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  304     Eigen::DenseIndex degree,
 
  310   const Eigen::DenseIndex p = degree;
 
  320   Eigen::VectorBlock<BasisVectorType, Degree>(left, 1, p)
 
  322         - Eigen::VectorBlock<const KnotVectorType, Degree>(U, i + 1 - p, p)
 
  324   Eigen::VectorBlock<BasisVectorType, Degree>(right, 1, p)
 
  325       = Eigen::VectorBlock<const KnotVectorType, Degree>(U, i + 1, p) - u;
 
  329   for (Eigen::DenseIndex j = 1; j <= p; ++j)
 
  332     for (Eigen::DenseIndex r = 0; r < j; r++)
 
  334       const Scalar tmp = N(r) / (right(r + 1) + left(j - r));
 
  335       N[r] = saved + right(r + 1) * tmp;
 
  336       saved = left(j - r) * tmp;
 
  343 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  346   if (_Degree == Eigen::Dynamic)
 
  347     return m_knots.size() - m_ctrls.cols() - 1;
 
  352 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  358 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  367   const Eigen::DenseIndex span = this->span(u);
 
  368   const Eigen::DenseIndex p = degree();
 
  371   const Eigen::Replicate<BasisVectorType, Dimension, 1> ctrl_weights(
 
  373   const Eigen::Block<const ControlPointVectorType, Dimension, Order> ctrl_pts(
 
  374       ctrls(), 0, span - p, Dimension, p + 1);
 
  375   return (ctrl_weights * ctrl_pts).rowwise().sum();
 
  381 template <
typename SplineType, 
typename DerivativeType>
 
  383     const SplineType& spline,
 
  384     typename SplineType::Scalar u,
 
  385     Eigen::DenseIndex order,
 
  398     DerivativeOrder = DerivativeType::ColsAtCompileTime
 
  402       ControlPointVectorType;
 
  406   typedef typename BasisDerivativeType::ConstRowXpr BasisDerivativeRowXpr;
 
  408   const Eigen::DenseIndex p = spline.degree();
 
  409   const Eigen::DenseIndex span = spline.span(u);
 
  411   const Eigen::DenseIndex n = (std::min)(p, order);
 
  413   der.resize(Dimension, n + 1);
 
  416   const BasisDerivativeType basis_func_ders
 
  417       = spline.template basisFunctionDerivatives<DerivativeOrder>(u, n + 1);
 
  420   for (Eigen::DenseIndex der_order = 0; der_order < n + 1; ++der_order)
 
  422     const Eigen::Replicate<BasisDerivativeRowXpr, Dimension, 1> ctrl_weights(
 
  423         basis_func_ders.row(der_order));
 
  424     const Eigen::Block<const ControlPointVectorType, Dimension, Order> ctrl_pts(
 
  425         spline.ctrls(), 0, span - p, Dimension, p + 1);
 
  426     der.col(der_order) = (ctrl_weights * ctrl_pts).rowwise().sum();
 
  430 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  431 typename SplineTraits<BSpline<_Scalar, _Dim, _Degree> >::DerivativeType
 
  433     Scalar u, Eigen::DenseIndex order)
 const 
  440 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  441 template <
int DerivativeOrder>
 
  445         Scalar u, Eigen::DenseIndex order)
 const 
  452 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  453 typename SplineTraits<BSpline<_Scalar, _Dim, _Degree> >::BasisVectorType
 
  462 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  463 template <
typename DerivativeType>
 
  466     const Eigen::DenseIndex order,
 
  467     const Eigen::DenseIndex p,
 
  480   const Eigen::DenseIndex span = SplineType::Span(u, p, U);
 
  482   const Eigen::DenseIndex n = (std::min)(p, order);
 
  484   N_.resize(n + 1, p + 1);
 
  489   Eigen::Matrix<Scalar, Order, Order> ndu(p + 1, p + 1);
 
  497   for (j = 1; j <= p; ++j)
 
  499     left[j] = u - U[span + 1 - j];
 
  500     right[j] = U[span + j] - u;
 
  503     for (Eigen::DenseIndex r = 0; r < j; ++r)
 
  506       ndu(j, r) = right[r + 1] + left[j - r];
 
  507       temp = ndu(r, j - 1) / ndu(j, r);
 
  509       ndu(r, j) = 
static_cast<Scalar>(saved + right[r + 1] * temp);
 
  510       saved = left[j - r] * temp;
 
  513     ndu(j, j) = 
static_cast<Scalar>(saved);
 
  516   for (j = p; j >= 0; --j)
 
  517     N_(0, j) = ndu(j, p);
 
  520   DerivativeType a(n + 1, p + 1);
 
  521   Eigen::DenseIndex r = 0;
 
  524     Eigen::DenseIndex s1, s2;
 
  530     for (Eigen::DenseIndex k = 1; k <= static_cast<Eigen::DenseIndex>(n); ++k)
 
  533       Eigen::DenseIndex rk, pk, j1, j2;
 
  539         a(s2, 0) = a(s1, 0) / ndu(pk + 1, rk);
 
  540         d = a(s2, 0) * ndu(rk, pk);
 
  553       for (j = j1; j <= j2; ++j)
 
  555         a(s2, j) = (a(s1, j) - a(s1, j - 1)) / ndu(pk + 1, rk + j);
 
  556         d += a(s2, j) * ndu(rk + j, pk);
 
  561         a(s2, k) = -a(s1, k - 1) / ndu(pk + 1, r);
 
  562         d += a(s2, k) * ndu(r, pk);
 
  565       N_(k, r) = 
static_cast<Scalar>(d);
 
  575   for (Eigen::DenseIndex k = 1; k <= static_cast<Eigen::DenseIndex>(n); ++k)
 
  577     for (j = p; j >= 0; --j)
 
  583 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  586     Scalar u, Eigen::DenseIndex order)
 const 
  590   BasisFunctionDerivativesImpl(u, order, degree(), knots(), der);
 
  594 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  595 template <
int DerivativeOrder>
 
  599         Scalar u, Eigen::DenseIndex order)
 const 
  602       BasisDerivativeType der;
 
  603   BasisFunctionDerivativesImpl(u, order, degree(), knots(), der);
 
  607 template <
typename _Scalar, 
int _Dim, 
int _Degree>
 
  608 typename SplineTraits<BSpline<_Scalar, _Dim, _Degree> >::BasisDerivativeType
 
  611     const Eigen::DenseIndex order,
 
  612     const Eigen::DenseIndex degree,
 
  616   BasisFunctionDerivativesImpl(u, order, degree, knots, der);
 
  623 #endif // AIKIDO_COMMON_BSPLINE_HPP_