2016-10-25 12 views
0

두 개의 3d 라인 세그먼트의 교차 부분을 얻기 위해이 코드를 작성했습니다.3d 라인 교차 코드가 제대로 작동하지 않습니다.

이 코드의 결과는 정확하지 않으며 교점은 항상 두 줄에있는 것은 아닙니다.

나는 혼란스럽고 내가 뭘 잘못하고 있는지 확신 할 수 없다.

--dir = direction 
--p1,p2 = represents the line 
function GetIntersection(dirStart, dirEnd, p1, p2) 
    local s1_x, s1_y, s2_x, s2_y = dirEnd.x - dirStart.x, dirEnd.z - dirStart.z, p2.x - p1.x, p2.z - p1.z 
    local div = (-s2_x * s1_y) + (s1_x * s2_y) 

    if div == 0 then return nil end 
    local s = (-s1_y * (dirStart.x - p1.x) + s1_x * (dirStart.z - p1.z))/div 
    local t = (s2_x * (dirStart.z - p1.z) - s2_y * (dirStart.x - p1.x))/div 

    if (s >= 0 and s <= 1 and t >= 0 and t <= 1) and (Vector(dirStart.x + (t * s1_x), 0, dirStart.z + (t * s1_y)) or nil) then 
     local v = Vector(dirStart.x + (t * s1_x),0,dirStart.z + (t * s1_y)) 
     return v 
    end 
end 
+0

이 코드는 무엇을 의도합니까? 이것은 2D와 3D 케이스의 이상한 혼합입니다! – MBo

+0

예상되는 결과와 함께 실패한 특정 테스트를 제공 할 수 있습니까? –

답변

1

이 3D 두 스큐 라인 사이의 거리를 찾을 수 델파이 코드의 예는 다음과 같습니다

여기 내 코드입니다. 당신의 목적을 위해서 그 결과가 충분히 작 으면 (교차가 존재할 때), s와 t 매개 변수가 범위 0..1에 있는지 확인해야합니다. 매개 변수를 사용하여 점을 계산하십시오.

이 접근 방법의 수학 식은 다음과 같습니다. 에 설명 된 '짧은 라인 ...'Paul Bourke page

VecDiff의 섹션 벡터 차 함수, 도트 ID 스칼라 제품 기능

function LineLineDistance(const L0, L1: TLine3D; var s, t: Double): Double; 
var 
    u: TPoint3D; 
    a, b, c, d, e, det, invdet:Double; 
begin 
    u := VecDiff(L1.Base, L0.Base); 
    a := Dot(L0.Direction, L0.Direction); 
    b := Dot(L0.Direction, L1.Direction); 
    c := Dot(L1.Direction, L1.Direction); 
    d := Dot(L0.Direction, u); 
    e := Dot(L1.Direction, u); 
    det := a * c - b * b; 
    if det < eps then 
    Result := -1 
    else begin 
    invdet := 1/det; 
    s := invdet * (b * e - c * d); 
    t := invdet * (a * e - b * d); 

    Result := Distance(PointAtParam(L0, s), PointAtParam(L1, t)); 
    end; 
end; 
0

는 지금까지 내가 말할 수있는 코드가 좋은 경우. 나는 이것을 자바 스크립트에서 https://jsfiddle.net/SalixAlba/kkrc9kcf/

으로 구현했으며 생각할 수있는 모든 경우에 대해 작동하는 것으로 보입니다. 내가 한 유일한 변경 사항은 루아가 아닌 자바 스크립트에서 동작하도록 변경하는 것입니다. 최종 조건이 주석 처리되었습니다.

function GetIntersection(dirStart, dirEnd, p1, p2) { 
    var s1_x = dirEnd.x - dirStart.x; 
    var s1_y = dirEnd.z - dirStart.z; 
    var s2_x = p2.x - p1.x; 
    var s2_y = p2.z - p1.z; 
    var div = (-s2_x * s1_y) + (s1_x * s2_y); 

    if (div == 0) 
    return new Vector(0,0); 

    var s = (-s1_y * (dirStart.x - p1.x) + s1_x * (dirStart.z - p1.z))/div; 
    var t = (s2_x * (dirStart.z - p1.z) - s2_y * (dirStart.x - p1.x))/div; 

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { 
     //and (Vector(dirStart.x + (t * s1_x), 0, dirStart.z + (t * s1_y)) or nil) then 
     var v = new Vector(
     dirStart.x + (t * s1_x), 
     dirStart.z + (t * s1_y)); 
     return v; 
    } 
    return new Vector(0,0); 
} 

수학적으로는 의미가 있습니다. A, B 및 C, D가 두 줄이면. s1 = B-A, s2 = C-D 라하자. 선 AB의 점은 A + ts1로 주어지고 점 CD의 점은 C + ss2로 주어진다. 교점을 위해 우리는

A + t S1 = C + S S2

또는

(AC) + t S1 = S에 대한 S S2

하면 두 식은, t는에 의해 발견 필요 벡터 (S1)와 (S2)의 각각에 2 차원 외적 복용

(AC)^S1 + t S1^S1 = S S2^S1 (AC)^S2 + t S1^S2 = S S2^S2

rec Alling은 S1^S1 = S2^S2 = 0 S2^S1 = - S1^S2 우리가 얻을

(AC)^(S1) = S (S2)^(S1) (AC)^S2 + t S1^S2 = 0

이는 s와 t를 구하기 위해 풀 수 있습니다. 이것은 방정식과 일치합니다.