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_