特征样条插值:末端的零导数

时间:2018-01-22 13:39:37

标签: c++ interpolation eigen

我需要插入一个tabled函数s.t.得到的样条曲线在间隔结束时具有零导数。我使用InterpolateWithDerivatives函数编写了示例,但生成的样条曲线并没有跨越给定的点:

typedef Eigen::Spline<double,1> Spline1d;
typedef Eigen::SplineFitting<Spline1d> Spline1dFitting;

void test_spline()
{
    Eigen::VectorXd x(5);
    Eigen::VectorXd y(5);
    x << 0.0, 0.25, 0.5, 0.75, 1.0;
    y << 0.0, 0.5, 1.0, 0.5, 0.0;

    Eigen::VectorXd derivatives(2);
    derivatives << 0., 0.;

    Eigen::VectorXi indices(2);
    indices << 0, x.size() - 1;

    Spline1d const& spline = Spline1dFitting::InterpolateWithDerivatives(
        y.transpose(), derivatives.transpose(), indices, 3, x);

    for (int i = 0; i < 5; ++ i)
        std::cout << "must be 0: " << spline(x(i)) - y(i) << std::endl;
}

虽然没有固定衍生品,但效果很好:

void test_spline_2()
{
    Eigen::VectorXd x(5);
    Eigen::VectorXd y(5);
    x << 0.0, 0.25, 0.5, 0.75, 1.0;
    y << 0.0, 0.5, 1.0, 0.5, 0.0;

    Spline1d const& spline2 = Spline1dFitting::Interpolate(y.transpose(), 3, x);
    for (int i = 0; i < 5; ++ i)
        std::cout << "must be 0: " << spline2(x(i)) - y(i) << std::endl;
}

这里有什么不对吗?

2 个答案:

答案 0 :(得分:0)

偶然发现了同一问题。本征似乎存在一个错误。

第一个示例:

must be 0: 0
must be 0: 7.54792e+168
must be 0: 1.90459e+185
must be 0: 7.54792e+168
must be 0: 0

第二个示例:

must be 0: 0
must be 0: 0
must be 0: 0
must be 0: 0
must be 0: 0

b(SplineFitting.h)中,右侧向量InterpolateWithDerivatives没有正确填充。

在您的示例中调用lu.solve时,b

0.0
0.0
1.0
1.90459157797e+185
2.06587336741e+161
0.0
0.0

答案 1 :(得分:0)

昨天我遇到了同样的问题。不幸的是,本征确实存在一个错误。正如Andreas指出的那样,向量b没有正确初始化。

由于我没有时间跟踪本征中的错误,因此我将补丁发布在这里,以便在有人遇到相同问题时提供帮助。

--- /original/eigen3/unsupported/Eigen/src/Splines/SplineFitting.h  2018-09-24 10:13:26.281178488 +0200
+++ /new/eigen3/unsupported/Eigen/src/Splines/SplineFitting.h   2018-09-26 14:59:13.737373531 +0200
@@ -381,11 +381,12 @@

 DenseIndex row = startRow;
 DenseIndex derivativeIndex = derivativeStart;
+
 for (DenseIndex i = 1; i < parameters.size() - 1; ++i)
 {
   const DenseIndex span = SplineType::Span(parameters[i], degree, knots);

-      if (derivativeIndices[derivativeIndex] == i)
+      if (derivativeIndex < derivativeIndices.size() && derivativeIndices[derivativeIndex] == i)
   {
     A.block(row, span - degree, 2, degree + 1)
       = SplineType::BasisFunctionDerivatives(parameters[i], 1, degree, knots);
@@ -395,8 +396,9 @@
   }
   else
   {
-        A.row(row++).segment(span - degree, degree + 1)
+        A.row(row).segment(span - degree, degree + 1)
           = SplineType::BasisFunctions(parameters[i], degree, knots);
+        b.col(row++) = points.col(i);
   }
 }
 b.col(0) = points.col(0);