NURBS曲線の特徴
CGの分野では解像度に非依存な形状を保存するために、パラメトリック曲線を利用することがあります. 今回は、その中でも特に自由度の高いNURBS曲線の基本的な事項をおさらいします.
ベクタ形式ではBezier曲線が有名で、古くから使われていますが、Bezier曲線にはいくつかの欠点があります. その中でも代表的なものを纏めてみると
- 次数が制御点数に影響される
- 重み付けができない
- 局所的な変更が難しい
これらの問題点を解決するために考案されたのが、BSpline曲線です.
NURBS曲線(Non-Uniform Rational BSpline curve)とは、名前の通りBSpline曲線に便利な特性(重み付けと非一様ノット列)を追加した形のことを言います.
NURBS曲線はBezier曲線とBspline曲線の上位版にあたり、高度な表現力をもちながら扱いやすい表現です
NURBS曲線の定義
NURBS曲線は以下の式で表現されます.
ただし、k
は制御点の個数, n
は次数です
はBSpline基底関数と呼ばれ、以下のように定義されます
のとき
のとき
ここで、のときに1を返す範囲は、
のどちらかを採用します.
開区間になっているほうの端は範囲に含まれなくなるので、エラー処理を行う必要があることに注意してください.
また、
を採用して、で例外処理を行う方法もあります
以下に基底関数の素直な実装を載せておきます.(改良の余地はあります.エラー処理はお好みで追加してください)
今度はDeBoorのアルゴリズムとかをやりたいですね
/** @fun * @brief BSpline基底関数を計算します * @param t 独立変数t * @param i 制御点の番号i * @param n 次数n * @param knots ノットベクトル */ double NURBS::basis(double t, size_t i, size_t n, const std::vector<double> &knots) { // N[i][0] if (n == 0) return (knots[i] <= t && t < knots[i + 1]) ? 1 : 0; double a1 = knots[i + n] - knots[i]; double a2 = knots[i + n + 1] - knots[i + 1]; double b1 = t - knots[i]; double b2 = knots[i + n + 1] - t; // "ゼロで割られたらゼロ"という決まりです double r1 = (b1 == 0) ? 0 : basis(t, i, n - 1, knots) * b1 / a1; double r2 = (b2 == 0) ? 0 : basis(t, i + 1, n - 1, knots) * b2 / a2; return r1 + r2; }