我有一组点,我想使用B样条曲线平滑。
我的问题是如何实现B样条曲线来平滑这些点?
我想用c ++实现这个。
答案 0 :(得分:4)
以下是任意给定点数的函数:
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]
。
答案 1 :(得分:1)
我最初建议使用带样条函数的最小二乘拟合来拟合数据点,然后在拟合样条上重新采样以获得更平滑的数据点(请在OP后查看我的评论)。在这里,我想推荐一种不同于最小二乘拟合方法的方法:
1)创建三次Hermite曲线,插值所有数据点。立方Hermite曲线基本上是由两个连续数据点之间的许多三次多项式曲线段组成的曲线。立方Hermite曲线通常仅C1连续。
2)使用Kjellander方法平滑立方Hermite曲线。该方法基本上计算节点处(即数据点处)的C2不连续性,然后相应地调整节点以减少C2不连续性。
3)平滑后,立方Hermite曲线的节点将成为您的新数据点集。
这是Kjellander方法(和其他样条曲线整流方法)的link。源代码可供下载。