2013-07-17 2 views
0

/여러 라인 세그먼트로 정의 된 한 쌍의 선이 교차하는지 확인해야합니다. 예를 들어 (0,0), (1,2), (3,1)에 의해 정의 된 선과 (0,2), (2,-1), (4,1)으로 정의 된 선이 교차하는지 확인해야합니다.세그먼트 화 된 선의 교차점 결정

교차가 어디인지를 결정할 필요는 없지만 매우 많은 수의 모서리를 가질 수 있으므로 효율적인 방법이 필요합니다. 두 세그먼트가 교차하는지 확인하기 위해 아래 코드를 사용하고 있지만 더 긴 길이의 라인에서는 비효율적입니다. 또한 선은 그래프의 가장자리이며 알려진 최대 길이로 제한됩니다.

static bool IsOnSegment(float xi, float yi, float xj, float yj, 
        float xk, float yk) { 
    return (xi <= xk || xj <= xk) && (xk <= xi || xk <= xj) && 
    (yi <= yk || yj <= yk) && (yk <= yi || yk <= yj); 
} 

static char ComputeDirection(float xi, float yi, float xj, float yj, 
         float xk, float yk) { 
    float a = (xk - xi) * (yj - yi); 
    float b = (xj - xi) * (yk - yi); 
    return a < b ? -1 : a > b ? 1 : 0; 
} 

// Do line segments (x1, y1)--(x2, y2) and (x3, y3)--(x4, y4) intersect?/
bool DoLineSegmentsIntersect(float x1, float y1, float x2, float y2, 
         float x3, float y3, float x4, float y4) { 
char d1 = ComputeDirection(x3, y3, x4, y4, x1, y1); 
char d2 = ComputeDirection(x3, y3, x4, y4, x2, y2); 
char d3 = ComputeDirection(x1, y1, x2, y2, x3, y3); 
char d4 = ComputeDirection(x1, y1, x2, y2, x4, y4); 
return (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && 
     ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) || 
    (d1 == 0 && IsOnSegment(x3, y3, x4, y4, x1, y1)) || 
    (d2 == 0 && IsOnSegment(x3, y3, x4, y4, x2, y2)) || 
    (d3 == 0 && IsOnSegment(x1, y1, x2, y2, x3, y3)) || 
    (d4 == 0 && IsOnSegment(x1, y1, x2, y2, x4, y4)); 
} 
+3

가능한 중복 어떻게 두 선분이 교차하는지 감지합니까?] (http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect) – hivert

+0

그 질문은 두 개의 단일 세그먼트가 교차 하는지를 결정하는 함수를주었습니다. 그러나 세그먼트의 경로를 고려하고 다른 세그먼트와 교차점을 찾아야합니다 통로. –

+0

* (0,0), (1.2) 및 (3,1) *로 정의 된 선; 이것은 2 개의 선분 또는 삼각형의 합집합입니까? –

답변

0

당신은 약간 O((n+k)logn) 시간과 O(n+k) 공간에서 모든 k 교차점을 계산하는 Bentley-Ottmann Algorithm을 변경합니다.

제안 된 수정 - Bentley-Ottmann 알고리즘은 세그먼트 집합을 가져 와서 모든 교차점을보고합니다. 세그먼트 선을 세그먼트 세트로 분할하고이 세트를 알고리즘의 입력으로 제공합니다. 교차가 발견되면 교차 세그먼트가 동일한 분할 선에 속하는지 여부를 확인하십시오. 그렇지 않다면 세그먼트 화 된 선의 교차점을 찾은 것입니다.

교차로 수가 매우 큰 경우 복잡도는 O(n^2)이됩니다. 최악의 경우는 얽힌 뱀처럼 보이는 두 개의 분할 선입니다. 적어도 O(N) 개의 의사 교차가 있음을 기억하십시오. 각 분할 선은 O(length) 의사 교차점을 생성하고 lenght1 + lenght2 = N으로 생성합니다. 여기서 N은 총 세그먼트 수입니다. O (N) 의사 교차가 있습니다. 가짜 교차로는 Bentley-Ottmann 알고리즘에 의해 감지 될 수있는 교차점이지만 고려하지 않아야합니다.

구현 힌트 - Bentley-Ottmann 정렬 지점을 기반으로하는 스윕 라인 algo에 기반한 알고리즘 - (X, Y) 쌍. 이제 트리플 (X, Y, segmentsLineID)을 정렬해야합니다. 귀하의 경우 모든 트리플은 (X, Y, 1) 또는 (X, Y, 2)

관련 문제