라인 충돌에서 2D 라인을 감지하는 방법?


13

나는 물리학이 흥미롭고 멋지지만 수학에 약간 뒤쳐진 플래시 액션 스크립트 게임 개발자입니다.

참고로 이것은 내가 만들고있는 것과 비슷한 게임입니다 : Untangled flash game

나는이 얽힌 게임을 거의 논리의 완성으로 만들었다. 그러나 두 선이 교차 할 때 서로 다른 색을 나타내려면 교차되거나 '얽힌'선이 필요합니다. 빨간.

선분 충돌 을 감지하는 알고리즘을 제안 할 수 있다면 정말 일종의 사람들 일 것 입니다. 나는 기본적으로 '산술'보다 '시각적으로'생각하는 것을 좋아하는 사람입니다 :)

편집 : 아이디어를보다 명확하게 전달하기 위해 몇 가지 다이어그램을 추가하고 싶습니다.

교차로 없음 교차로 없음 교차점 교차로 없음

추신 : 나는 기능을하려고합니다.

private function isIntersecting(A:Point, B:Point, C:Point, D:Point):Boolean

미리 감사드립니다.


6
이 문제의 실망이 아닌 시각적 인 설명이지만,이 알고리즘이며 자신의 수학을 읽고 자신을 가져올 수있는 경우는 메이크업 감각을 수행 local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d 그것은 할 수있다 벡터 수학이 약하면 무겁습니다. 이해합니다-시각적 설명도 선호합니다. 나중에 이것을 낙서 할 시간을 찾으려고하지만, 예술적으로 관심이있는 누군가가이 링크를보고 내가하기 전에 시간이 있다면, 그것을 찾아 가십시오!
Anko

답변:


18

나는 이 알고리즘을 구현 한 다음과 같은 방법을 사용 한다 . C #에 있지만 ActionScript로 변환하는 것은 쉽지 않습니다.

bool IsIntersecting(Point a, Point b, Point c, Point d)
{
    float denominator = ((b.X - a.X) * (d.Y - c.Y)) - ((b.Y - a.Y) * (d.X - c.X));
    float numerator1 = ((a.Y - c.Y) * (d.X - c.X)) - ((a.X - c.X) * (d.Y - c.Y));
    float numerator2 = ((a.Y - c.Y) * (b.X - a.X)) - ((a.X - c.X) * (b.Y - a.Y));

    // Detect coincident lines (has a problem, read below)
    if (denominator == 0) return numerator1 == 0 && numerator2 == 0;

    float r = numerator1 / denominator;
    float s = numerator2 / denominator;

    return (r >= 0 && r <= 1) && (s >= 0 && s <= 1);
}

그러나 알고리즘에는 미묘한 문제가 있습니다. 두 줄이 일치하지만 겹치지 않는 경우입니다. 이 경우 알고리즘은 여전히 ​​인터 섹 티오 인을 반환합니다. 이 경우에 관심이 있다면 stackoverflow에 대한이 답변에 더 복잡한 버전 있다고 생각 합니다.

편집하다

이 알고리즘에서 결과를 얻지 못했습니다. 죄송합니다.

이상하다, 나는 그것을 테스트했고 위에서 설명한 단일 사례를 제외하고는 나를 위해 일하고있다. 위에 게시 한 것과 똑같은 버전을 사용하여 테스트 드라이브로 가져갈 때 다음 결과를 얻었습니다.

여기에 이미지 설명을 입력하십시오


이 알고리즘에서 결과를 얻지 못했습니다. 죄송합니다.
Vishnu

4
@Vish 어떤 문제가 있었습니까? 게시하기 전에이 정확한 알고리즘 사본을 테스트했으며 설명 된 단일 사례를 제외하고 완벽하게 작동했습니다.
David Gouveia

그런 다음 다시 시도해 보도록하겠습니다. 곧 알려 드리겠습니다. 고마워요, 어쨌든 :)
Vishnu

1
@DavidGouveia 덕분에 알고리즘에서 원하는 결과를 얻었습니다.
Vishnu

1
글쎄,하지만 지금은 또 다른 문제가 있습니다 :)! 빨간색과 녹색의 교차 선을 만들어야합니다. 교차로가 잘 작동합니다. 그러나 내가 지금 이해했듯이 (수학적으로는 아니지만) 단순한 if-else는 교차 및 비교 차 선에 빨간색과 녹색 선을 넣는 것과 같이 작동하지 않습니다. 드래그하는 노드에는 왼쪽과 오른쪽 선이 있습니다. 따라서 교차되지 않은 선의 색을 다시 녹색으로 변경하는 동안 어딘가에 문제가 발생했습니다. 나도 다른 조건이 필요하다고 생각합니다. 흠, 어쨌든 톤 덕분에 나는 이것을 정답으로 표시하고 있습니다.
Vishnu

4

사단없이! 따라서 정밀도 나 0으로 나누는 문제는 없습니다.

선분 1은 A에서 B로 선분 2는 C에서 D로

선은 끝나지 않는 선이며 선 세그먼트는 해당 선의 정의 된 부분입니다.

두 경계 상자가 교차하는지 확인하십시오. 교차가없는 경우-> 교차하지 않습니다! (계산 완료, false 반환)

선분 1이 선분 2에 걸리고 선분 2가 선분 1에 있는지 (즉, 선분 1이 선분 2에 의해 정의 된 선의 양쪽에 있는지) 확인하십시오.

모든 점을 -A로 변환하여 만들 수 있습니다 (즉, A가 오리고 (0,0)에 있도록 두 줄을 이동합니다).

그런 다음 점 C와 D가 0,0에서 B로 정의 된 선의 다른 측면에 있는지 확인합니다.

//Cross Product (hope I got it right here)
float fC= (B.x*C.y) - (B.y*C.x); //<0 == to the left, >0 == to the right
float fD= (B.x*D.y) - (B.y*D.x);

if( (fc<0) && (fd<0)) //both to the left  -> No Cross!
if( (fc>0) && (fd>0)) //both to the right -> No Cross!

아직 "십자가 없음"을 얻지 못한 경우 A, B 대 C, D가 아니라 C, D 대 A, B (동일한 계산, A와 C, B, D 만 교체)를 계속 사용하십시오. "아니 십자가!" 그런 다음 교차로가 있습니다!

교차 제품에 대한 정확한 계산을 검색 하고 방법을 설명하는 이 블로그 게시물 을 찾았 습니다.


1
죄송하지만 벡터 수학에 익숙하지 않습니다.이 알고리즘을 구현했지만 결과가 없습니다. 죄송합니다!
Vishnu

1
코드를 보여줄 수 있다면 우리가 도와 줄 수 있습니까?
Valmond

좋은! 그러나 연결이 끊어졌습니다
clabe45

교차점을 얻기 위해 여기에 추가 할 수있는 것이 있습니까?
SeanRamey 2016 년

1

나는 Gamemaker Studio 게임에 필요하다고 말하고 싶습니다.

///scr_line_collision(x1,y1,x2,y2,x3,y3,x4,y4)

var denominator= ((argument2 - argument0) * (argument7 - argument5)) - ((argument3 - argument1) * (argument6 - argument4));
var numerator1 = ((argument1 - argument5) * (argument6 - argument4)) - ((argument0 - argument4) * (argument7 - argument5));
var numerator2 = ((argument1 - argument5) * (argument2 - argument0)) - ((argument0 - argument4) * (argument3 - argument1));

// Detect coincident lines
if (denominator == 0) {return (numerator1 == 0 && numerator2 == 0)}

var r = numerator1 / denominator;
var s = numerator2 / denominator;

return ((r >= 0 && r <= 1) && (s >= 0 && s <= 1));

코드의 기능을 설명하면이 답변이 실제로 향상 될 수 있다고 생각합니다.
TomTsagk

1

이 경우 허용 된 답변이 잘못된 답변을 제공했습니다.

x1 = 0;
y1 = 0;
x2 = 10;
y2 = 10;

x3 = 10.1;
y3 = 10.1;
x4 = 15;
y4 = 15;

이 선들은 분명히 교차하지 않지만 "정답"의 기능에 따라 선이 교차합니다.

이것이 내가 사용하는 것입니다 :

function do_lines_intersect(px1,py1,px2,py2,px3,py3,px4,py4) {
  var ua = 0.0;
  var ub = 0.0;
  var ud = (py4 - py3) * (px2 - px1) - (px4 - px3) * (py2 - py1);


  if (ud != 0) {
    ua = ((px4 - px3) * (py1 - py3) - (py4 - py3) * (px1 - px3)) / ud;
    ub = ((px2 - px1) * (py1 - py3) - (py2 - py1) * (px1 - px3)) / ud;
        if (ua < 0.0 || ua > 1.0 || ub < 0.0 || ub > 1.0) ua = 0.0;
  }

  return ua;
}

0을 반환 = 선이 교차하지 않습니다

> 0 = 라인이 교차하는 것을 반환


질문에 답변하기 위해 업데이트 :

이 코드를 직접 만들지 않았습니다. 5 살이 넘었고 원래 출처가 무엇인지 모르겠습니다. 그러나..

반환 값은 첫 줄의 교차 위치 (잘 설명하지 못함)입니다. 교차점을 계산하려면 다음과 같이 lerp를 사용할 수 있습니다.

l = do_lines_intersect(...)
if (l > 0) {
    intersect_pos_x = l * (px2-px1);
    intersect_pos_y = l * (py2-py1);
} else {
    // lines do not cross
}

(나는 이것을 테스트하지 않았다)


교차점을 반환하는 버전이 있습니까?
SeanRamey 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.