2012-07-12 2 views
5

나는 우주선이 정거장에서 선착장으로 들어올 때 함께 여행하는 경로로 베지에 곡선을 사용하고 있습니다.입방체 베 지어 곡선 : 최대 기울기 및 충돌 회피?

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; 

    } 
} 

곡선의 시작점이 우주선의 위치 및 끝 지점 도킹 베이의 입구 (빨간색 점 : 나는 배는 차 베 지어 곡선을 따라 시간 t에서 있어야 할 곳에 계산하는 간단한 알고리즘을 다이어그램에서). 우주선은 방향에 대해 정규화 된 벡터를 가지고 있으며, 도킹 베이는 우주선이 도착할 때 도킹 베이에 똑바로 정렬되도록 우주선이 이동해야하는 방향을 나타내는 다른 정규화 된 벡터를 가지고 있습니다 (다이어그램의 노란색 선)

녹색 선은 우주선의 가능한 경로이며 보라색 원, 우주선의 반지름입니다. 마지막으로 블랙 박스는 스테이션의 경계 상자입니다.

enter image description here

나는 두 가지 문제가 있습니다

우주선은 초
  • 역을 통해 비행 할 수 없습니다 우주선 당 R 라디안에서 우회전 할 수 있어야하는데

    이 내용은 다음과 같이 번역됩니다.

    a). 배가 너무 세게 굴릴 필요가없는 경로를 제공하는 "곡선 인자"(제어점 길이)를 찾는 것.

    b). 역과의 충돌을 피할 수없는 우주선 위치/방향 찾기 (그리고 그 상태에서 인도 할 수있는 경로를 만들어서 a 부분을 얻을 수 있음)

    그러나이 두 가지를 모두 사용하면 , 나는 많은 행운을 찾지 못했다. 벡터, 상자, 점 및 구 사이의 교차점을 감지하는 코드가 있지만 베 지어 커브는 아직 없습니다. 두 점 사이의 거리를 찾을 수있는 함수도 있습니다.

    어떤 도움을 대부분의 5 번째 또는 6 차 다항식을 해결하는 것을 포함

    감사합니다, 제임스

  • 답변

    3

    는 큐빅 베 지어 곡선의 정확한 교차점을 찾기 감상 할 수있다. 더 실현 가능한 솔루션은 수치 방법을 사용하거나 베 지어 곡선을 세분화하는 것입니다.

    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은 첫 번째 세그먼트가된다. q3 .. q6이 두 번째 세그먼트가됩니다.

    커브를 2-5 번 세분하고 제어점을 폴리 라인으로 사용하십시오.


    curvature

    각각의 세그먼트의 엔드 포인트에서 계산 될 수있다 :

    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); 
    } 
    

    문제 1 해결 곡선 몇 번을 세분화하고있는 곡률을 계산하도록 각 세그먼트의 끝점. 이것은 근사치 일 뿐이지 만 높은 곡률을 가진 세그먼트를 선택적으로 세분하여 그 영역에서 더 좋은 근사를 얻을 수 있습니다.


    는 세 개의 곡선을 나눌 수 문제 2를 해결하려면 두 엔드 포인트에서 속도가 0 인

    • 하나 (C0). 이렇게하면 직선이됩니다.
    • 첫 번째 끝점에서 속도가 0이고 두 번째 끝에서 속도가 0 인 점 (C1).
    • 첫 번째 끝점에서 속도 1이고 두 번째 끝점에서 0입니다 (C2).

    동일한 방법으로 모든 커브를 세분화하면 최종 커브의 조절 점을 빠르게 평가할 수 있습니다. (직선 세그먼트로 평가) 더 세그먼트가 교차하지 않도록, 당신이 함께 유효 파라미터 범위를 찾을 수

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

    : 당신은 최종 지점에서 속도에 의해 매개 변수화 해당 컨트롤 포인트를 혼합 역. (v1v2은 1.0 이상이 될 수 있음).

    +0

    감사합니다. 그리고 오랫동안 당신에게 돌아 가기 위해 오랫동안 복용하는 것에 대해 유감스럽게 생각합니다. 나는 정확한 질문을 표시했다. 그러나 결국 다른 방법으로 갔다. 나는 스테이션이 도킹 포인트로 계속 가기 전에 배가 먼저가는 '측면 포인트'를 사용한다. –