Added spline interpolation with pre-defined knot parameters.

This commit is contained in:
Hauke Heibel 2012-04-13 12:50:05 +02:00
parent f6a5508392
commit 84c93b048e
2 changed files with 53 additions and 13 deletions

View File

@ -102,38 +102,53 @@ namespace Eigen
template <typename SplineType> template <typename SplineType>
struct SplineFitting struct SplineFitting
{ {
typedef typename SplineType::KnotVectorType KnotVectorType;
/** /**
* \brief Fits an interpolating Spline to the given data points. * \brief Fits an interpolating Spline to the given data points.
*
* \param pts The points for which an interpolating spline will be computed.
* \param degree The degree of the interpolating spline.
*
* \returns A spline interpolating the initially provided points.
**/ **/
template <typename PointArrayType> template <typename PointArrayType>
static SplineType Interpolate(const PointArrayType& pts, DenseIndex degree); static SplineType Interpolate(const PointArrayType& pts, DenseIndex degree);
/**
* \brief Fits an interpolating Spline to the given data points.
*
* \param pts The points for which an interpolating spline will be computed.
* \param degree The degree of the interpolating spline.
* \param knot_parameters The knot parameters for the interpolation.
*
* \returns A spline interpolating the initially provided points.
**/
template <typename PointArrayType>
static SplineType Interpolate(const PointArrayType& pts, DenseIndex degree, const KnotVectorType& knot_parameters);
}; };
template <typename SplineType> template <typename SplineType>
template <typename PointArrayType> template <typename PointArrayType>
SplineType SplineFitting<SplineType>::Interpolate(const PointArrayType& pts, DenseIndex degree) SplineType SplineFitting<SplineType>::Interpolate(const PointArrayType& pts, DenseIndex degree, const KnotVectorType& knot_parameters)
{ {
typedef typename SplineType::KnotVectorType::Scalar Scalar; typedef typename SplineType::KnotVectorType::Scalar Scalar;
typedef typename SplineType::KnotVectorType KnotVectorType;
typedef typename SplineType::BasisVectorType BasisVectorType; typedef typename SplineType::BasisVectorType BasisVectorType;
typedef typename SplineType::ControlPointVectorType ControlPointVectorType; typedef typename SplineType::ControlPointVectorType ControlPointVectorType;
typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType; typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType;
KnotVectorType chord_lengths; // knot parameters
ChordLengths(pts, chord_lengths);
KnotVectorType knots; KnotVectorType knots;
KnotAveraging(chord_lengths, degree, knots); KnotAveraging(knot_parameters, degree, knots);
DenseIndex n = pts.cols(); DenseIndex n = pts.cols();
MatrixType A = MatrixType::Zero(n,n); MatrixType A = MatrixType::Zero(n,n);
for (DenseIndex i=1; i<n-1; ++i) for (DenseIndex i=1; i<n-1; ++i)
{ {
const DenseIndex span = SplineType::Span(chord_lengths[i], degree, knots); const DenseIndex span = SplineType::Span(knot_parameters[i], degree, knots);
// The segment call should somehow be told the spline order at compile time. // The segment call should somehow be told the spline order at compile time.
A.row(i).segment(span-degree, degree+1) = SplineType::BasisFunctions(chord_lengths[i], degree, knots); A.row(i).segment(span-degree, degree+1) = SplineType::BasisFunctions(knot_parameters[i], degree, knots);
} }
A(0,0) = 1.0; A(0,0) = 1.0;
A(n-1,n-1) = 1.0; A(n-1,n-1) = 1.0;
@ -145,6 +160,15 @@ namespace Eigen
return SplineType(knots, ctrls); return SplineType(knots, ctrls);
} }
template <typename SplineType>
template <typename PointArrayType>
SplineType SplineFitting<SplineType>::Interpolate(const PointArrayType& pts, DenseIndex degree)
{
KnotVectorType chord_lengths; // knot parameters
ChordLengths(pts, chord_lengths);
return Interpolate(pts, degree, chord_lengths);
}
} }
#endif // EIGEN_SPLINE_FITTING_H #endif // EIGEN_SPLINE_FITTING_H

View File

@ -216,16 +216,32 @@ void check_global_interpolation2d()
typedef Spline2d::ControlPointVectorType ControlPointVectorType; typedef Spline2d::ControlPointVectorType ControlPointVectorType;
ControlPointVectorType points = ControlPointVectorType::Random(2,100); ControlPointVectorType points = ControlPointVectorType::Random(2,100);
const Spline2d spline = SplineFitting<Spline2d>::Interpolate(points,3);
KnotVectorType chord_lengths; // knot parameters KnotVectorType chord_lengths; // knot parameters
Eigen::ChordLengths(points, chord_lengths); Eigen::ChordLengths(points, chord_lengths);
for (Eigen::DenseIndex i=0; i<points.cols(); ++i) // interpolation without knot parameters
{ {
PointType pt = spline( chord_lengths(i) ); const Spline2d spline = SplineFitting<Spline2d>::Interpolate(points,3);
PointType ref = points.col(i);
VERIFY( (pt - ref).matrix().norm() < 1e-14 ); for (Eigen::DenseIndex i=0; i<points.cols(); ++i)
{
PointType pt = spline( chord_lengths(i) );
PointType ref = points.col(i);
VERIFY( (pt - ref).matrix().norm() < 1e-14 );
}
}
// interpolation with given knot parameters
{
const Spline2d spline = SplineFitting<Spline2d>::Interpolate(points,3,chord_lengths);
for (Eigen::DenseIndex i=0; i<points.cols(); ++i)
{
PointType pt = spline( chord_lengths(i) );
PointType ref = points.col(i);
VERIFY( (pt - ref).matrix().norm() < 1e-14 );
}
} }
} }