4

我有一组要使用 B 样条曲线平滑的点。
我的问题是如何实现 B 样条曲线来平滑这些点集?
我想用 c++ 来实现它。

4

2 回答 2

6

这是任何给定点数的函数:

void Spline(double x[N+1],double y[N+1], // input
            double A[N],double B[N],     // output
            double C[N],double D[N])     // output
{
    double w[N];
    double h[N];
    double ftt[N+1];

    for (int i=0; i<N; i++)
    {
        w[i] = (x[i+1]-x[i]);
        h[i] = (y[i+1]-y[i])/w[i];
    }

    ftt[0] = 0;
    for (int i=0; i<N-1; i++)
        ftt[i+1] = 3*(h[i+1]-h[i])/(w[i+1]+w[i]);
    ftt[N] = 0;

    for (int i=0; i<N; i++)
    {
        A[i] = (ftt[i+1]-ftt[i])/(6*w[i]);
        B[i] = ftt[i]/2;
        C[i] = h[i]-w[i]*(ftt[i+1]+2*ftt[i])/6;
        D[i] = y[i];
    }
}

以下是如何打印此函数的结果:

void PrintSpline(double x[N+1],            // input
                 double A[N], double B[N], // input
                 double C[N], double D[N]) // input
{
    for (int i=0; i<N; i++)
    {
        cout << x[i] << " <= x <= " << x[i+1] << " : f(x) = ";
        cout << A[i] << "(x-" << x[i] << ")^3 + ";
        cout << B[i] << "(x-" << x[i] << ")^2 + ";
        cout << C[i] << "(x-" << x[i] << ")^1 + ";
        cout << D[i] << "(x-" << x[i] << ")^0";
        cout << endl;
    }
}

请注意,这两个函数都假定x[0] < x[1] < ... < x[N].

于 2014-08-19T09:24:01.717 回答
3

我最初建议使用带有样条函数的最小二乘拟合来拟合数据点,然后在拟合的样条上重新采样以获得更平滑的数据点集(请参阅我在 OP 之后的评论)。在这里,我想推荐一种不同的方法,它可能比最小二乘拟合方法更简单:

1)创建插值所有数据点的三次 Hermite 曲线。三次 Hermite 曲线基本上是由两个连续数据点之间的许多三次多项式曲线段组成的曲线。三次 Hermite 曲线通常只有 C1 连续。
2) 使用凯氏法平滑三次厄米特曲线。该方法主要计算节点处(即数据点处)的 C2 不连续性,然后相应地调整节点以减少 C2 不连续性。
3) 平滑后,三次 Hermite 曲线的节点将成为您的新数据点集。

这是 Kjellander 方法(和其他样条整流罩方法)的链接。源代码可供下载。

于 2014-08-20T16:28:13.957 回答