Hãy nói rằng tôi có một Bezier curveB(u)
, nếu tôi tăng u
tham số với một tốc độ không đổi Tôi không có được một tốc độ di chuyển costant dọc theo đường cong, bởi vì mối quan hệ giữa u
tham số và điểm thu được đánh giá đường cong không phải là tuyến tính.Bezier Curves Cubic: di chuyển với tốc thống nhất
Tôi đã đọc và triển khai article của David Eberly. Nó giải thích làm thế nào để di chuyển ở tốc độ không đổi dọc theo một đường cong tham số.
Giả sử tôi có một hàm F(t)
mà mất như là đầu vào một giá trị thời gian t
và một chức năng tốc độ sigma
mà trả về giá trị tốc độ lúc t
, tôi có thể có được một tốc độ di chuyển costant dọc theo đường cong, thay đổi thông số t với một tốc độ không đổi : B(F(t))
Cốt lõi của bài viết tôi đang sử dụng là chức năng sau:
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;
}
Nó cho phép tôi để có được những thông số đường cong u
tính bằng thời gian cung cấp t
và hàm sigma. Bây giờ chức năng hoạt động tốt khi sigma tốc độ là chi phí. Nếu sigma đại diện cho một sự tăng tốc đồng đều, tôi nhận được các giá trị sai từ nó.
Dưới đây là ví dụ về đường cong Bezier thẳng, trong đó P0 và P1 là các điểm điều khiển, T0 T1 tiếp tuyến. Các đường cong được định nghĩa:
[x,y,z]= B(u) =(1–u)3P0 + 3(1–u)2uT0 + 3(1–u)u2T1 + u3P2
Hãy nói rằng tôi muốn biết vị trí dọc theo đường cong lúc t = 3
. Nếu tôi một vận tốc không đổi:
float sigma(float t)
{
return 1f;
}
và các dữ liệu sau:
V0 = 1;
V1 = 1;
t0 = 0;
L = 10;
tôi analitically có thể tính toán vị trí:
px = v0 * t = 1 * 3 = 3
Nếu tôi giải quyết phương trình tương tự sử dụng spline Bezier của tôi và thuật toán ở trên với n =5
Tôi nhận được:
px = 3.002595;
Xem xét số lượng xấp xỉ giá trị khá chính xác (tôi đã thực hiện rất nhiều thử nghiệm về điều đó. Tôi bỏ qua chi tiết nhưng Bezier thực hiện đường cong của tôi là tốt và chiều dài của đường cong chính nó được tính toán khá chính xác bằng cách sử dụng Gaussian Quadrature).
Bây giờ Nếu tôi cố gắng xác định sigma là hàm tăng tốc đồng đều, tôi nhận được kết quả không tốt. Hãy xem xét các dữ liệu sau:
V0 = 1;
V1 = 2;
t0 = 0;
L = 10;
tôi có thể tính toán thời gian một hạt sẽ đạt P1 sử dụng phương trình chuyển động tuyến tính:
L = 0.5 * (V0 + V1) * t1 =>
t1 = 2 * L/(V1 + V0) = 2 * 10/3 = 6.6666666
Có t
tôi có thể tính toán khả năng tăng tốc:
a = (V1 - V0)/(t1 - t0) = (2 - 1)/6.6666666 = 0.15
Tôi có tất cả dữ liệu để xác định hàm sigma của mình:
float sigma (float t)
{
float speed = V0 + a * t;
}
Nếu tôi analitically giải quyết này tôi mong đợi vận tốc sau của một hạt sau thời gian t =3
:
Vx = V0 + a * t = 1 + 0.15 * 3 = 1.45
và vị trí sẽ là:
px = 0.5 * (V0 + Vx) * t = 0.5 * (1 + 1.45) * 3 = 3.675
Nhưng nếu tôi tính toán nó với alorithm ở trên, kết quả vị trí:
px = 4.358587
hoàn toàn khác fr om những gì tôi đang mong đợi.
Xin lỗi vì bài đăng dài, nếu có ai đủ kiên nhẫn để đọc nó, tôi sẽ rất vui.
Bạn có gợi ý gì không? Tôi đang thiếu gì? Bất kỳ ai cũng có thể cho tôi biết tôi đang làm gì sai?
EDIT: Tôi đang thử với đường cong 3D Bezier. Định nghĩa theo cách này:
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;
}
và đạo hàm:
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;
}
và thuật toán cung cấp cho bạn gì cho t = 6.6666 ...? Có phải đó là giá trị 10, tức là L hoặc một giá trị khác không? – lmsteffan