web-dev-qa-db-ja.com

C ++でベジェ曲線を実装するにはどうすればよいですか?

ベジエ曲線 を実装したいと思います。これは以前にC#で行ったことがありますが、C++ライブラリにはまったく慣れていません。 2次曲線を作成するにはどうすればよいですか?

void printQuadCurve(float delta, Vector2f p0, Vector2f p1, Vector2f p2);

明らかに線形補間を使用する必要がありますが、これは標準の数学ライブラリに存在しますか?そうでない場合、どこで見つけることができますか?

更新1:

Linuxを使用していることを忘れていました。

17
Nick Bolton

以前にC#ライブラリを使用しましたか?

C++では、ベジェ曲線用の標準ライブラリ関数は(まだ)利用できません。もちろん、自分で(CodeProject sample )を転がしたり、数学ライブラリを探したりすることもできます。

これ ブログポストはアイデアをうまく​​説明していますが、Actionscriptで説明しています。翻訳はそれほど問題にはなりません。

8
dirkgently

最近、同じ質問に出くわし、自分で実装したいと思っていました。ウィキペディアからのこの画像は私を助けました:

http://upload.wikimedia.org/wikipedia/commons/3/35/Bezier_quadratic_anim.gif

次のコードはC++で記述されており、2次ベジェを計算する方法を示しています。

int getPt( int n1 , int n2 , float perc )
{
    int diff = n2 - n1;

    return n1 + ( diff * perc );
}    

for( float i = 0 ; i < 1 ; i += 0.01 )
{
    // The Green Line
    xa = getPt( x1 , x2 , i );
    ya = getPt( y1 , y2 , i );
    xb = getPt( x2 , x3 , i );
    yb = getPt( y2 , y3 , i );

    // The Black Dot
    x = getPt( xa , xb , i );
    y = getPt( ya , yb , i );

    drawPixel( x , y , COLOR_RED );
}

(x1 | y1)、(x2 | y2)および(x3 | y3)は画像のP0、P1およびP2です。基本的な考えを示すためだけに...

三次ベジエを要求する人にとっては、それはちょうど同様に動作します(これもWikipediaから):

http://upload.wikimedia.org/wikipedia/commons/a/a3/Bezier_cubic_anim.gif

これ 回答はコードを提供します。

108
Jakob Riedle

以下は、任意の数の点を持つ曲線の一般的な実装です。

vec2 getBezierPoint( vec2* points, int numPoints, float t ) {
    vec2* tmp = new vec2[numPoints];
    memcpy(tmp, points, numPoints * sizeof(vec2));
    int i = numPoints - 1;
    while (i > 0) {
        for (int k = 0; k < i; k++)
            tmp[k] = tmp[k] + t * ( tmp[k+1] - tmp[k] );
        i--;
    }
    vec2 answer = tmp[0];
    delete[] tmp;
    return answer;
}

一時配列にヒープメモリを使用しているため、それほど効率的ではないことに注意してください。固定数のポイントのみを処理する必要がある場合は、numPoints値をハードコードして、代わりにスタックメモリを使用できます。

もちろん、上記は、vec2構造とそのための演算子が次のようにあることを前提としています。

struct vec2 {
    float x, y;
    vec2(float x, float y) : x(x), y(y) {}
};

vec2 operator + (vec2 a, vec2 b) {
    return vec2(a.x + b.x, a.y + b.y);
}

vec2 operator - (vec2 a, vec2 b) {
    return vec2(a.x - b.x, a.y - b.y);
}

vec2 operator * (float s, vec2 a) {
    return vec2(s * a.x, s * a.y);
}
14
iforce2d

上で説明した線形補間を使用してポイントに到達するまで制御パスを再帰的に分割するde Casteljauの方法、または制御点をブレンドするBezierの方法のいずれかを選択できます。

ベジェの方法は

 p = (1-t)^3 *P0 + 3*t*(1-t)^2*P1 + 3*t^2*(1-t)*P2 + t^3*P3 

キュービックと

 p = (1-t)^2 *P0 + 2*(1-t)*t*P1 + t*t*P2

二次方程式。

tは通常0〜1ですが、それは必須ではありません。実際、曲線は無限大まで伸びています。 P0、P1などは制御点です。曲線は2つの端点を通過しますが、通常は他の点を通過しません。

9
Malcolm McLean
  • ベジエ曲線を表示したいだけの場合は、Windowsでは PolyBezier のようなものを使用できます。

  • ルーチンを自分で実装したい場合は、Intarnetz全体で 線形補間コード を見つけることができます。

  • Boost libraries はこれをサポートしていると思います。特にベジェではなく、線形補間。しかし、これについて私を引用しないでください。

1
user2189331