[algorithm] 두 직사각형의 교차를 감지하는 알고리즘?

두 사각형이 교차하는지 감지하는 알고리즘을 찾고 있습니다 (하나는 임의의 각도로, 다른 하나는 수직 / 수평 선으로 만).

하나의 모서리가 다른 ALMOST에 있는지 테스트합니다. 사각형이 십자형을 형성하면 실패합니다.

수직선에 특별한 경우가 필요한 선의 기울기를 사용하지 않는 것이 좋습니다.



답변

표준 방법은 분리 축 테스트를 수행하는 것입니다 (Google 검색을 수행하십시오).

한마디로 :

  • 두 객체를 분리하는 선을 찾을 수 있으면 두 객체가 교차하지 않습니다. 예를 들어, 객체의 객체 / 모든 포인트는 선의 다른면에 있습니다.

재미있는 점은 두 사각형의 모든 가장자리를 확인하는 것으로 충분하다는 것입니다. 사각형이 겹치지 않으면 가장자리 중 하나가 분리 축이됩니다.

2D에서는 경사를 사용하지 않고도이 작업을 수행 할 수 있습니다. 가장자리는 단순히 두 꼭짓점의 차이로 정의됩니다. 예 :

  edge = v(n) - v(n-1)

90도 회전시켜 수직을 얻을 수 있습니다. 2D에서는 다음과 같이 쉽습니다.

  rotated.x = -unrotated.y
  rotated.y =  unrotated.x

삼각법이나 경사가 없습니다. 벡터를 단위 길이로 정규화 할 필요도 없습니다.

점이 선의 한쪽 또는 다른쪽에 있는지 테스트하려면 내적을 사용할 수 있습니다. 표지판은 당신이 어느쪽에 있는지 알려줍니다 :

  // rotated: your rotated edge
  // v(n-1) any point from the edge.
  // testpoint: the point you want to find out which side it's on.

  side = sign (rotated.x * (testpoint.x - v(n-1).x) +
               rotated.y * (testpoint.y - v(n-1).y);

이제 사각형 A의 모든 점을 사각형 B의 가장자리와 반대로 테스트하십시오. 분리되는 모서리를 찾으면 물체가 교차하지 않습니다 (B의 다른 모든 점이 테스트중인 모서리의 다른쪽에있는 경우 아래 그림 참조). 분리 모서리가 없으면 직사각형이 교차하거나 하나의 직사각형이 다른 직사각형에 포함됩니다.

이 테스트는 볼록 다각형 btw ..

수정 : 분리 에지를 식별하기 위해 한 직사각형의 모든 포인트를 다른 에지의 각 에지에 대해 테스트하는 것만으로는 충분하지 않습니다. 후보 에지 E (아래)는 A의 모든 점이 E의 동일한 반평면에 있으므로 분리 에지로 식별됩니다. 그러나 B의 정점 Vb1 및 Vb2 때문에 분리 에지가 아닙니다. 그 반평면에도 있습니다. 그렇지 않은 경우에만 분리 된 가장자리 였을 것입니다
http://www.iassess.com/collision.png


답변

기본적으로 다음 그림을보십시오.

두 상자가 충돌하면 선 A와 B가 겹칩니다.

이 작업은 X 축과 Y 축 모두에서 수행해야하며 사각형이 충돌하려면 겹치게해야합니다.

gamasutra.com 에는 질문에 대한 답변 이있는 좋은 기사가 있습니다 (사진은 기사에 있음). 5 년 전에 비슷한 알고리즘을 수행했으며 나중에 여기에 게시 할 코드 스 니펫을 찾아야합니다

개정 : 분리 축 정리 개의 볼록 형상한다고 하지 오버랩 분액 축이 존재하는 경우 (도시 된 바와 같이 돌기 즉 하나 하지 중첩). 따라서 “분리 축이 존재합니다”=> “겹침 없음”. 이것은 이중의 의미가 아니므로 대화를 결론 지을 수 없습니다.


답변

m_pGladiator의 답변이 옳으며 선호합니다.
분리 축 테스트 는 사각형 겹침을 감지하는 가장 단순하고 표준적인 방법입니다. 투영 간격이 겹치지 않는 선을 분리 축 이라고합니다 . Nils Pipenbrinck의 솔루션이 너무 일반적입니다. 사용도트 제품 을 하여 한 모양이 다른 가장자리의 한쪽에 완전히 있는지 여부를 확인합니다. 이 솔루션은 실제로 n-edge 볼록 다각형을 유도 할 수 있습니다. 그러나 두 사각형에는 최적화되지 않았습니다.

m_pGladiator의 대답의 핵심은 두 축 (x와 y)에서 두 개의 직사각형 투영을 확인해야한다는 것입니다. 두 개의 투영이 겹치면이 두 사각형이 겹쳤다 고 말할 수 있습니다. 따라서 m_pGladiator의 답변에 대한 위의 의견은 잘못되었습니다.

간단한 상황에서 두 개의 사각형이 회전하지 않으면 구조가있는 사각형이 나타납니다.

struct Rect {
    x, // the center in x axis
    y, // the center in y axis
    width,
    height
}

직사각형 A, B의 이름을 rectA, rectB로 지정합니다.

    if Math.abs(rectA.x - rectB.x) < (Math.abs(rectA.width + rectB.width) / 2)
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(rectA.height + rectB.height) / 2))
    then
        // A and B collide
    end if

두 사각형 중 하나가 회전되면 x 및 y 축에서 사각형의 투영을 결정하기 위해 약간의 노력이 필요할 수 있습니다. 다음과 같이 struct RotatedRect를 정의하십시오.

struct RotatedRect : Rect {
    double angle; // the rotating angle oriented to its center
}

차이점은 너비 ‘가 이제 약간 다른 방법입니다. rectA의 경우 Math.sqrt(rectA.width*rectA.width + rectA.height*rectA.height) * Math.cos(rectA.angle)
widthA’: rectB의 경우 widthB ‘:Math.sqrt(rectB.width*rectB.width + rectB.height*rectB.height) * Math.cos(rectB.angle)

    if Math.abs(rectA.x - rectB.x) < (Math.abs(widthA' + widthB') / 2)
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(heightA' + heightB') / 2))
    then
        // A and B collide
    end if

GDC (Game Development Conference 2007) PPT www.realtimecollisiondetection.net/pubs/GDC07_Ericson_Physics_Tutorial_SAT.ppt를 참조 할 수 있음


답변

Cocoa에서는 selectedArea rect가 회전 된 NSView의 frame rect와 교차하는지 여부를 쉽게 감지 할 수 있습니다. 다각형, 법선 등을 계산할 필요조차 없습니다. NSView 서브 클래스에 이러한 메소드를 추가하십시오. 예를 들어, 사용자는 NSView 슈퍼 뷰에서 영역을 선택한 다음 selectedArea rect를 전달하는 DoesThisRectSelectMe 메소드를 호출합니다. API convertRect :가 해당 작업을 수행합니다. NSView를 클릭하여 선택하면 동일한 트릭이 작동합니다. 이 경우 단순히 아래와 같이 hitTest 메소드를 대체하십시오. API convertPoint : 해당 작업을 수행합니다. 😉

- (BOOL)DoesThisRectSelectMe:(NSRect)selectedArea
{
    NSRect localArea = [self convertRect:selectedArea fromView:self.superview];

    return NSIntersectsRect(localArea, self.bounds);
}


- (NSView *)hitTest:(NSPoint)aPoint
{
    NSPoint localPoint = [self convertPoint:aPoint fromView:self.superview];
    return NSPointInRect(localPoint, self.bounds) ? self : nil;
}


답변

한 사각형의 선이 다른 사각형의 선과 교차하는지 확인하십시오. 순진한 선분 교차점을 쉽게 코딩 할 수 있습니다.

더 빠른 속도가 필요한 경우 선분 교차점 (스윕 라인)을위한 고급 알고리즘이 있습니다. http://en.wikipedia.org/wiki/Line_segment_intersection을 참조하십시오


답변

하나의 해결책은 No Fit Polygon이라는 것을 사용하는 것입니다. 이 다각형은 두 개의 다각형 (개념적으로 하나를 다른 주위로 미끄러짐)으로 계산되며 다각형이 상대 오프셋을 기준으로 겹치는 영역을 정의합니다. 이 NFP가 있으면 두 다각형의 상대 오프셋으로 지정된 점으로 포함 테스트를 수행하면됩니다. 이 포함 테스트는 빠르고 쉽습니다. 먼저 NFP를 만들어야합니다.

웹에서 No Fit Polygon을 검색하고 볼록 다각형에 대한 알고리즘을 찾을 수 있는지 확인하십시오 (오목 다각형이 있으면 훨씬 복잡해집니다). 아무것도 찾을 수 없다면 howard dot J dot에서 gmail dot com으로 이메일을 보내주십시오.


답변

다음은 가능한 모든 사례를 처리 할 것이라고 생각합니다. 다음 테스트를 수행하십시오.

  1. 사각형 1의 꼭짓점은 사각형 2 안에 있고 그 반대도 마찬가지입니다. 다른 사각형 안에있는 정점을 찾을 때마다 검색과 교차하고 중지한다고 결론을 내릴 수 있습니다. 하나의 사각형이 다른 사각형 안에 완전히 들어갑니다.
  2. 위의 테스트가 결정적이지 않으면 1 직사각형의 각 라인과 다른 직사각형의 각 라인의 교차점을 찾으십시오. 교차점이 발견되면 해당 4 점에 의해 생성 된 가상의 사각형 내부에 있는지 확인하십시오. 그러한 요점이 발견되면 그것들이 교차하고 검색을 중단한다는 결론을 내립니다.

위의 두 테스트에서 false를 반환하면이 두 사각형이 겹치지 않습니다.