2013-03-06 53 views
12

のは、私がBezier curveB(u)を持っているとしましょう、私は一定の速度でuパラメータをインクリメントする場合、私は曲線に沿っcostant高速移動を取得していない、uパラメータとポイントの関係理由得られた曲線は線形ではないと評価する。ベジェ次曲線:等加速度で移動

David Eberlyのarticleを読んで実装しました。パラメトリックカーブに沿って一定の速度で移動する方法について説明します。

一定の速度でTパラメータを変化させる、Iは、入力として、時間値tと時間t速度値を返す速度関数sigmaをとる関数F(t)を有する、私は曲線に沿っcostant速度運動を得ることができると仮定それは私が供給時間を用いて算出した曲線パラメータuを取得することができます

float umin, umax; // The curve parameter interval [umin,umax]. 
Point Y (float u); // The position Y(u), umin <= u <= umax. 
Point DY (float u); // The derivative dY(u)/du, umin <= u <= umax. 
float LengthDY (float u) { return Length(DY(u)); } 
float ArcLength (float t) { return Integral(umin,u,LengthDY()); } 
float L = ArcLength(umax); // The total length of the curve. 
float tmin, tmax; // The user-specified time interval [tmin,tmax] 
float Sigma (float t); // The user-specified speed at time t. 

float GetU (float t) // tmin <= t <= tmax 
{ 
    float h = (t - tmin)/n; // step size, `n' is application-specified 
    float u = umin; // initial condition 
    t = tmin; // initial condition 
    for (int i = 1; i <= n; i++) 
    { 
    // The divisions here might be a problem if the divisors are 
    // nearly zero. 
    float k1 = h*Sigma(t)/LengthDY(u); 
    float k2 = h*Sigma(t + h/2)/LengthDY(u + k1/2); 
    float k3 = h*Sigma(t + h/2)/LengthDY(u + k2/2); 
    float k4 = h*Sigma(t + h)/LengthDY(u + k3); 
    t += h; 
    u += (k1 + 2*(k2 + k3) + k4)/6; 
    } 
    return u; 
} 

B(F(t))

私が使用している製品のコアは、次の関数であります210とシグマ関数。 この関数は、速度シグマがコストがかかるときにうまく機能します。シグマが一様なアクセントを表しているなら、私はそれから間違った値を得ています。

直線ベジェ曲線の例です。ここで、P0とP1は制御点、T0は接線です。カーブの定義された:

[x,y,z]= B(u) =(1–u)3P0 + 3(1–u)2uT0 + 3(1–u)u2T1 + u3P2 

enter image description here

のは、私は時間t = 3でカーブに沿った位置を知りたいとしましょう。 I等速の場合:私は私のベジエスプラインを使用して同じ方程式を解く場合

px = v0 * t = 1 * 3 = 3 

:私はanalitically位置を算出することができる

V0 = 1; 
V1 = 1; 
t0 = 0; 
L = 10; 

float sigma(float t) 
{ 
    return 1f; 
} 

と、次のデータ上記のアルゴリズムはn =5となります。

px = 3.002595; 

数値近似を考えると、値はかなり正確です(私はそれについて多くのテストを行いました。細部は省略していますが、私の曲線の実装はうまくあり、カーブ自体の長さはGaussian Quadratureを使ってかなり正確に計算されています。

今、シグマを等加速度関数として定義しようとすると、結果が悪くなります。 次のデータを考慮してください

V0 = 1; 
V1 = 2; 
t0 = 0; 
L = 10; 

Iの粒子は、線形運動方程式を用いて、P1に到達する時間を計算することができる:

tを有する
L = 0.5 * (V0 + V1) * t1 => 
t1 = 2 * L/(V1 + V0) = 2 * 10/3 = 6.6666666 

I加速度を計算することができる:

a = (V1 - V0)/(t1 - t0) = (2 - 1)/6.6666666 = 0.15 

私はシグマ関数を定義するためのすべてのデータを持っています:

float sigma (float t) 
{ 
    float speed = V0 + a * t; 
} 

私はanaliticallyこの私が時間t =3後の粒子の以下の速度を期待解決した場合:

Vx = V0 + a * t = 1 + 0.15 * 3 = 1.45 

をその位置は次のようになります。

px = 0.5 * (V0 + Vx) * t = 0.5 * (1 + 1.45) * 3 = 3.675 

しかし、私はそれを計算した場合上記のアルゴリズムの結果、位置は次のようになります。

px = 4.358587 

これは全く異なるfr私が何を期待しているのか

長いポストに申し訳ありません、誰かがそれを読むのに十分な忍耐を持っているなら、私はうれしいでしょう。

私には何が欠けていますか?誰かが私が間違っていることを教えてくれますか?


EDIT: 私は3Dベジエ曲線を試しています。

public Vector3 Bezier(float t) 
{ 
    float a = 1f - t; 
    float a_2 = a * a; 
    float a_3 = a_2 *a; 

    float t_2 = t * t; 

    Vector3 point = (P0 * a_3) + (3f * a_2 * t * T0) + (3f * a * t_2 * T1) + t_2 * t * P1 ; 

    return point; 
} 

及びデリバティブ:このように定義

public Vector3 Derivative(float t) 
{ 
    float a = 1f - t; 
    float a_2 = a * a; 
    float t_2 = t * t; 
    float t6 = 6f*t; 

    Vector3 der = -3f * a_2 * P0 + 3f * a_2 * T0 - t6 * a * T0 - 3f* t_2 * T1 + t6 * a * T1 + 3f * t_2 * P1; 

    return der; 
} 
+0

とアルゴリズムは、t = 6.6666 ...のためにあなたに何を与えるのですか?それは値10、すなわちLか、別の値ですか? – lmsteffan

答えて

1

私の推測では、n=5は、単に当面の問題のために、あなたに十分な精度が得られないということです。一定速度の場合にはOKであるという事実は、一定の加速の場合にも当てはまるわけではない。残念ながら、お客様のニーズとリソースに合ったnの値を提供する妥協案を自分自身で定義する必要があります。あなたが本当に等速パラメータ化を持っている場合

とにかく、X十分な精度で動作します(U(t))を、あなたはそう、この「時間」パラメータt「スペース」(距離)パラメータsの名前を変更することができますあなたが本当に持っているのはX(s)で、あなたが必要とするs(t)のプラグインが必要です:X(s(t))。あなたの場合(一定の加速度)、s(t)= s + u t + a t /2ここでuとaは入力データから簡単に決まります。

1

私はあなたの実装の中にYとDYで示されていない関数のどこかに単にタイプミスがあると思います。私はP0 = 0、T0 = 1、T1 = 9、P1 = 10で一次元カーブを試み、3.6963165でn = 5を得た。これはn = 30で3.675044、n = 100で3.6750002に改善した。

実装が2次元である場合は、P0 =(0,0)、T0 =(1,0)、T1 =(9,0)、P1 =(10,0)で試してください。次に、P0 =(0,0)、T0 =(0,1)、T1 =(0,9)、およびP1 =(0,10)で再度試してください。

Cを使用している場合、^演算子は指数を意味しないことに注意してください。 uの立方体を得るには、pow(u、3)またはu * u * uを使用する必要があります。

各繰り返しでできるだけ多くのものの値を印刷してみてください。ここで私が得たものです:

i=1 
    h=0.6 
    t=0.0 
    u=0.0 
    LengthDY(u)=3.0 
    sigma(t)=1.0 
    k1=0.2 
    sigma(t+h/2)=1.045 
    LengthDY(u+k1/2)=6.78 
    k2=0.09247787 
    LengthDY(u+k2/2)=4.8522377 
    k3=0.12921873 
    sigma(t+h)=1.09 
    LengthDY(u+k3)=7.7258916 
    k4=0.08465043 
    t_new=0.6 
    u_new=0.12134061 
i=2 
    h=0.6 
    t=0.6 
    u=0.12134061 
    LengthDY(u)=7.4779167 
    sigma(t)=1.09 
    k1=0.08745752 
    sigma(t+h/2)=1.135 
    LengthDY(u+k1/2)=8.788503 
    k2=0.0774876 
    LengthDY(u+k2/2)=8.64721 
    k3=0.078753725 
    sigma(t+h)=1.1800001 
    LengthDY(u+k3)=9.722377 
    k4=0.07282171 
    t_new=1.2 
    u_new=0.20013426 
i=3 
    h=0.6 
    t=1.2 
    u=0.20013426 
    LengthDY(u)=9.723383 
    sigma(t)=1.1800001 
    k1=0.072814174 
    sigma(t+h/2)=1.225 
    LengthDY(u+k1/2)=10.584761 
    k2=0.069439456 
    LengthDY(u+k2/2)=10.547299 
    k3=0.069686085 
    sigma(t+h)=1.27 
    LengthDY(u+k3)=11.274727 
    k4=0.06758479 
    t_new=1.8000001 
    u_new=0.26990926 
i=4 
    h=0.6 
    t=1.8000001 
    u=0.26990926 
    LengthDY(u)=11.276448 
    sigma(t)=1.27 
    k1=0.06757447 
    sigma(t+h/2)=1.315 
    LengthDY(u+k1/2)=11.881528 
    k2=0.06640561 
    LengthDY(u+k2/2)=11.871877 
    k3=0.066459596 
    sigma(t+h)=1.36 
    LengthDY(u+k3)=12.375444 
    k4=0.06593703 
    t_new=2.4 
    u_new=0.3364496 
i=5 
    h=0.6 
    t=2.4 
    u=0.3364496 
    LengthDY(u)=12.376553 
    sigma(t)=1.36 
    k1=0.06593113 
    sigma(t+h/2)=1.405 
    LengthDY(u+k1/2)=12.7838 
    k2=0.06594283 
    LengthDY(u+k2/2)=12.783864 
    k3=0.0659425 
    sigma(t+h)=1.45 
    LengthDY(u+k3)=13.0998535 
    k4=0.06641296 
    t_new=3.0 
    u_new=0.4024687 

私は変数のトンをプリントアウトし、その後、手でそれぞれの値を計算し、そして、彼らは同じだことを確認することによって、このようなプログラムの多くをデバッグしてきました。

+0

データありがとうございます。私はもう少し実験をしようとします。実際に私は3Dベジェ曲線を使用しています。コードを使って投稿を編集します。 – Heisenbug

関連する問題