B スプライン曲線を使用して滑らかにしたい点のセットがあります。
私の質問は、これらの点のセットを滑らかにするために B スプライン曲線を実装するにはどうすればよいですか?
これをc++で実装したい。
2 に答える
これは、任意の数のポイントに対する関数です。
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]
。
スプライン関数で最小二乗フィッティングを使用してデータ ポイントをフィッティングし、その後、フィッティングされたスプラインをリサンプリングして、よりスムーズなデータ ポイントのセットを取得することをお勧めします (OP の後の私のコメントを参照してください)。ここでは、最小二乗法よりも簡単な別のアプローチをお勧めします。
1) すべてのデータ ポイントを補間する 3 次エルミート曲線を作成します。3 次エルミート曲線は、基本的に、2 つの連続するデータ ポイント間の多くの 3 次多項式曲線セグメントで構成される曲線です。通常、3 次エルミート曲線は C1 連続のみです。
2) ケルランダー法を使用して、3 次エルミート曲線を滑らかにします。この方法は基本的に、ノード (つまり、データ ポイント) で C2 不連続を計算し、それに応じてノードを調整して C2 不連続を減らします。
3) 平滑化後、3 次エルミート曲線のノードが新しいデータ ポイントのセットになります。
Kjellander メソッド (およびその他のスプライン フェアリング メソッド) へのリンクは次のとおりです。ソースコードはダウンロード可能です。