2012-07-12 21 views
5

Tôi đang sử dụng các đường cong bezier làm đường dẫn cho các phi thuyền không gian của tôi để di chuyển dọc theo khi chúng đến bến tàu tại một trạm. Tôi có một thuật toán đơn giản để tính toán nơi tàu phải có ít thời gian t dọc theo một đường cong Bezier khối:Đường cong Bezier khối: Độ dốc tối đa và tránh va chạm?

public class BezierMovement{ 
    public BezierMovement(){ 
     // start docking straight away in this test version 
     initDocking(); 
    } 

    private Vector3 p0; 
    private Vector3 p1; 
    private Vector3 p2; 
    private Vector3 p3; 

    private double tInc = 0.001d; 
    private double t = tInc; 

    protected void initDocking(){ 

     // get current location 
     Vector3 location = getCurrentLocation(); 

     // get docking point 
     Vector3 dockingPoint = getDockingPoint(); 

     // ship's normalised direction vector 
     Vector3 direction = getDirection(); 

     // docking point's normalised direction vector 
     Vector3 dockingDirection = getDockingDirection(); 

     // scalars to multiply normalised vectors by 
     // The higher the number, the "curvier" the curve 
     float curveFactorShip = 10000.0f; 
     float curveFactorDock = 2000.0f; 

     p0 = new Vector3(location.x,location.y,location.z); 

     p1 = new Vector3(location.x + (direction.x * curveFactorShip), 
         location.y + (direction.y * curveFactorShip), 
         location.z + (direction.z * curveFactorShip)); 

     p2 = new Vector3(dockingPoint.x + (dockingDirection.x * curveFactorDock), 
         dockingPoint.y + (dockingDirection.y * curveFactorDock), 
         dockingPoint.z + (dockingDirection.z * curveFactorDock)); 

     p3 = new Vector3(dockingPoint.x, dockingPoint.y, dockingPoint.z); 


    } 

    public void incrementPosition() { 

     bezier(p0, p1, p2, p3, t, getCurrentLocation()); 

     // make ship go back and forth along curve for testing    
     t += tInc; 

     if(t>=1){ 
      tInc = 0-tInc; 
     } else if(t<0){ 
      tInc = 0-tInc; 
     } 

    } 

    protected void bezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, double t, Vector3 outputVector){ 

     double a = (1-t)*(1-t)*(1-t); 
     double b = 3*((1-t)*(1-t))*t; 
     double c = 3*(1-t)*(t*t); 
     double d = t*t*t; 

     outputVector.x = a*p0.x + b*p1.x + c*p2.x + d*p3.x; 
     outputVector.y = a*p0.y + b*p1.y + c*p2.y + d*p3.y; 
     outputVector.z = a*p0.z + b*p1.z + c*p2.z + d*p3.z; 

    } 
} 

Đường cong khởi điểm là vị trí con tàu vũ trụ, và điểm kết thúc là lối vào vịnh docking (chấm đỏ trên sơ đồ). Tàu vũ trụ có véc tơ chuẩn hóa theo hướng của nó, và vịnh nối có một véc tơ chuẩn hóa khác để biểu thị hướng mà con tàu phải di chuyển để được căn thẳng vào vịnh nối khi nó đến (các vạch màu vàng trên sơ đồ)

Đường màu xanh lá cây là đường dẫn có thể có của tàu vũ trụ và vòng tròn màu tím, bán kính của tàu vũ trụ. Cuối cùng, hộp đen là hộp giới hạn cho trạm.

enter image description here

Tôi có hai vấn đề:

  1. Các tàu vũ trụ được cho là chỉ có thể lần lượt tại radian r mỗi giây
  2. Các tàu vũ trụ không thể bay qua trạm

Tôi giả định rằng điều này được dịch thành:

a). Tìm "các yếu tố đường cong" (độ dài điểm kiểm soát) sẽ cho một con đường mà con tàu không phải quay quá chặt.

b). Tìm vị trí/hướng tàu vũ trụ mà từ đó nó không thể tránh va chạm với trạm (và tạo đường dẫn để hướng dẫn nó ra khỏi trạng thái đó, để nó có thể tiếp tục với phần a))

Tuy nhiên, với cả hai , Tôi đã không có nhiều may mắn tìm một giải pháp. Tôi đã có mã để phát hiện giao lộ giữa vectơ, hộp, điểm và hình cầu, nhưng vẫn chưa có đường cong. Tôi cũng có chức năng để tôi tìm khoảng cách giữa hai điểm.

Bất kỳ trợ giúp sẽ được đánh giá cao nhất

Cảm ơn, James

Trả lời

3

Tìm các nút giao thông chính xác của một Cubic Bezier đường cong liên quan đến việc giải quyết một 5 hoặc mức độ đa thức thứ 6. Các giải pháp khả thi hơn là sử dụng các phương pháp số hoặc chia nhỏ đường cong Bezier.

protected void subdivide(
     Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, 
     Vector3 q0, Vector3 q1, Vector3 q2, Vector3 q3, 
     Vector3 q4, Vector3 q5, Vector3 q6) { 

    q0.x = p0.x; q0.y = p0.y; q0.z = p0.z; 
    q6.x = p3.x; q6.y = p3.y; q6.z = p3.z; 

    q1.x = (p0.x + p1.x) * 0.5; 
    q1.y = (p0.y + p1.y) * 0.5; 
    q1.z = (p0.z + p1.z) * 0.5; 

    q5.x = (p2.x + p3.x) * 0.5; 
    q5.y = (p2.y + p3.y) * 0.5; 
    q5.z = (p2.z + p3.z) * 0.5; 

    double x3 = (p1.x + p2.x) * 0.5; 
    double y3 = (p1.y + p2.y) * 0.5; 
    double z3 = (p1.z + p2.z) * 0.5; 

    q2.x = (q1.x + x3) * 0.5; 
    q2.y = (q1.y + y3) * 0.5; 
    q2.z = (q1.z + z3) * 0.5; 

    q4.x = (x3 + q1.x) * 0.5; 
    q4.y = (y3 + q1.y) * 0.5; 
    q4.z = (z3 + q1.z) * 0.5; 

    q3.x = (q2.x + q4.x) * 0.5; 
    q3.y = (q2.y + q4.y) * 0.5; 
    q3.z = (q2.z + q4.z) * 0.5; 
} 

q1 .. q3 trở thành phân khúc đầu tiên. q3 .. q6 trở thành phân khúc thứ hai.

Chia nhỏ đường cong 2-5 lần và sử dụng các điểm điều khiển làm đường polyline.


Các curvature có thể được tính vào cuối-điểm của từng phân khúc:

protected double curvatureAtStart(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { 
    double dx1 = p1.x - p0.x; 
    double dy1 = p1.y - p0.y; 
    double dz1 = p1.z - p0.z; 

    double A = dx1 * dx1 + dy1 * dy1 + dz1 * dz1; 

    double dx2 = p0.x - 2*p1.x + p2.x; 
    double dy2 = p0.y - 2*p1.y + p2.y; 
    double dz2 = p0.z - 2*p1.z + p2.z; 

    double B = dx1 * dx2 + dy1 * dy2 + dz1 * dz2; 

    double Rx = (dx2 - dx1*B/A)/A*2/3; 
    double Ry = (dy2 - dy1*B/A)/A*2/3; 
    double Rz = (dz2 - dz1*B/A)/A*2/3; 

    return Math.sqrt(Rx * Rx + Ry * Ry + Rz * Rz); 
} 

Để giải quyết Vấn đề 1, chia nhỏ các đường cong một vài lần, và tính toán độ cong tại từng điểm cuối của phân đoạn. Đây sẽ chỉ là một phép tính xấp xỉ, nhưng bạn có thể chia nhỏ một cách có chọn lọc các đoạn có độ cong cao để có được xấp xỉ tốt hơn trong vùng đó.


Để giải quyết Vấn đề 2, bạn có thể chia nhỏ ba đường cong:

  • Một với vận tốc zero ở cả hai điểm cuối (C0). Điều này sẽ tạo ra một đường thẳng.
  • Một với tốc độ không ở điểm cuối đầu tiên, và một ở tốc độ thứ nhất (C1).
  • Một với tốc độ một tại điểm cuối đầu tiên và không ở tốc độ thứ nhất (C2).

Nếu bạn chia nhỏ tất cả các đường cong theo cùng một cách, bạn có thể nhanh chóng đánh giá các điểm kiểm soát của đường cong cuối cùng. Bạn trộn điều khiển-điểm tương ứng, parametrized bởi vận tốc vào cuối-điểm:

C[i] = C0[i] + (C1[i] - C0[i])*v1 + (C2[i] - C0[i])*v2 

Bạn có thể với điều này tìm giá trị tham số-dãy, đến nỗi không phân đoạn (đánh giá là một dòng đoạn thẳng) giao với ga tàu. (v1v2 có thể cao hơn 1.0).

+0

Cảm ơn! và xin lỗi vì mất quá nhiều thời gian để lấy lại cho bạn. Tôi đánh dấu câu hỏi đúng, mặc dù cuối cùng tôi đã đi cho một phương pháp khác nhau, nơi tôi sử dụng một 'điểm phụ' mà tàu đi đến đầu tiên nếu trạm là trong cách, trước khi tiếp tục vào điểm nối. –