1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C++】バーンスタイン基底関数とベジェ曲線

Posted at

始点と終点があるとき、なめらかな曲線を引きたい場合があります。
制御点を指定することで、それを実現する方法が、ベジェ曲線を利用する方法です。
本記事ではC++と、ライブラリのhlslppを使用して、ベジェ曲線の実装サンプルコードを紹介したいと思います。

hlslppセットアップ方法は下記の記事からご参照ください。

バーンスタイン基底関数

ベジェ曲線を構成する各通過点は、各制御点にバーンスタイン基底関数というものを乗算したものの総和で求められます。
つまり、パラメトリック変数tを使用した補間が可能であるということです。
どうやらバーンスタイン基底関数を式で表すとこのように表せるようです。

B_{i,n}(t) = \binom{n}{i} t^i (1 - t)^{n - i}

とりあえず、基底関数をコードにします。

//---------------------------------------------------------------------------------
//! 二項係数(nCk)を計算する関数
//---------------------------------------------------------------------------------
int BinomialCoefficient(int n, int k)
{
    if(k == 0 || k == n)
        return 1;

    int res = 1;
    for(int i = 1; i <= k; ++i) {
        res *= (n - i + 1);
        res /= i;
    }
    return res;
}
//---------------------------------------------------------------------------------
//! バーンスタイン基底関数 b_{i,n}(t) を計算
//--------------------------------------------------------------------------------
float BernsteinBasis(int i, int n, float t)
{
    float coeff = static_cast<float>(BinomialCoefficient(n, i));
    return coeff * powf(t, i) * powf(1.0f - t, n - i);
}

ベジェ曲線

制御点と、パラメトリック変数を渡すことで、ベジェ曲線の通過点を求める関数を記述してみます。

//---------------------------------------------------------------------------------
//! 3Dのベジェ曲線を生成する関数
//--------------------------------------------------------------------------------
float3 Bezier3D(const std::vector<float3>& control_points, float t)
{
    int    n     = static_cast<int>(control_points.size()) - 1;
    float3 point = float3(0.0f, 0.0f, 0.0f);

    // 各制御点に対応するバーンスタイン基底関数を掛けて加算
    for(int i = 0; i <= n; ++i) {
        float b  = BernsteinBasis(i, n, t);
        point   += b * control_points[i];
    }

    return point;
}

上記の場合はfloat3なので3Dですが、float2にすれば、2Dでも曲線を表現することが可能です。

総括

  • ベジェ曲線の性質を利用することで、始点と終点、制御点から曲線を描くことが出来る。
  • 制御点とバーンスタイン基底関数の乗算結果の総和で、通過点を求めることが出来る。
  • tの値を変更することで、補間が可能。
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?