【C++】【Eigen】EigenでBスプライン補間を行う
はじめに
Eigenには、unsupportedながらBスプライン補間を行うライブラリが用意されています。今回、これを使用してBスプライン補間を行うプログラムを作成してみます。
Eigen::Splineクラス
Bスプライン補間を行うには、Eigen::Spline<>
クラスのオブジェクトを作成する必要があります。基本的な使い方はオブジェクトを作成し、値を得るときにEigen::Spline<>::operator()
を呼び出すだけです。
ノットベクトルと制御点がわかっている場合と、補間したい点だけが得られている場合で、初期化のやり方が変わってきます。
ノットベクトルと制御点がわかっている場合
Eigen::Spline<>
クラスのコンストラクタでノットベクトルと制御点を設定します。
#include <iostream>
#include <Eigen/Eigen>
#include <unsupported/Eigen/Spline>
int main()
{
Eigen::VectorXd knots(11);
Eigen::MatrixXd ctrls(2, 7);
knots << 0, 0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1, 1;
ctrls << 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
0.0, 2.0, 1.5, 3.0, 2.0, 3.0, 4.5;
Eigen::Spline<double, 2, Eigen::Dynamic> spline(knots, ctrls);
for(int i = 0; i <= 100; i++){
auto y = spline(i / 100.0);
std::cout << y(0) << '\t' << y(1) << std::endl;
}
return 0;
}
テンプレート引数の2
は2D(平面)であることを示します。Eigen::Dynamic
は補間する次数をノットベクトルで指定することを示します(今回は3次です)。
また、Eigen::Spline<>::operator()
の引数u
は$0 \leqq u \leqq 1$であることに注意します。$x$座標から補間する場合は、適切な変換が必要です。戻り値はArrayで、インデックス0が$x$座標、インデックス1が$y$座標となります。
補間したい点だけが得られている場合
補間するための関数を呼び出す必要があります。これには、Eigen::SplineFitting<>::Interpolate()
という関数を使用します。
#include <iostream>
#include <Eigen/Eigen>
#include <unsupported/Eigen/Spline>
int main()
{
Eigen::Spline<double, 2, Eigen::Dynamic> spline;
Eigen::MatrixXd points;
points << 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
0.0, 2.0, 1.5, 3.0, 2.0, 3.0, 4.5;
spline = Eigen::SplineFitting< Eigen::Spline<double, 2, Eigen::Dynamic> >::Interpolate(points, 3);
for(int i = 0; i <= 100; i++){
auto y = spline(i / 100.0);
std::cout << y(0) << '\t' << y(1) << std::endl;
}
return 0;
}
Interpolate()
メソッドの3
は補間する次数を示します(今回は3次)。Bスプラインはノットベクトルによって、補間曲線の形が変わるため、Interpolate()
メソッドでは、ノットベクトルを指定することもできます。その場合は、以下のようにします。
// knotsはノットベクトル(Eigen::VectorXd)とする
spline = Eigen::SplineFitting< Eigen::Spline<double, 2, Eigen::Dynamic> >::Interpolate(points, 3, knots);
ノットベクトルと制御点はEigen::Spline<>::knots()
とEigen::Spline<>::ctrls()
を使用することで得られます。
std::cout << "knots" << std::endl << spline.knots() << std::endl;
std::cout << "control points" << std::endl << spline.ctrls() << std::endl;
出力結果
knots
0 0 0 0 0.365991 0.51362 0.671336 1 1 1 1
control points
-2.52966e-17 -0.460933 2.08686 2.83392 4.45454 5.53068 6
-2.63835e-17 4.66037 -0.659575 3.98773 0.175466 4.82719 4.5
まとめ
EigenでBスプライン補間を使う方法をまとめます。
- ノットベクトルと制御点がわかっている場合は、
Eigen::Spline<>
のコンストラクタで指定する。 - 補間したい点が与えられた場合は、
Eigen::SplineFitting<>::Interpolate()
を使う。 - 補間する場合は、
Eigen::Spline<>::operator()
を使う。戻り値は$(x, y)$。引数u
は$0 \leqq u \leqq 1$を取る。 - ノットベクトルを得る場合は、
Eigen::Spline<>::knots()
を使う。 - 制御点を得る場合は、
Eigen::Spline<>::ctrls()
を使う。
ディスカッション
コメント一覧
まだ、コメントがありません