직사각형에서 직사각형으로의 빠른 교차


81

두 개의 직사각형이 교차하는지 테스트하는 빠른 방법은 무엇입니까?


인터넷 검색 결과이 한 줄짜리 (WOOT!)가 나왔지만 Javascript로 작성하는 방법을 이해하지 못하고 고대 C ++ 형식으로 작성된 것 같습니다.

struct
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT; 

bool IntersectRect(const RECT * r1, const RECT * r2)
{
    return ! ( r2->left > r1->right
        || r2->right < r1->left
        || r2->top > r1->bottom
        || r2->bottom < r1->top
        );
}

5
복사 / 붙여 넣기에 오타가있는 것
같습니다

5
원본 기사에 오타가 있습니다. r2->right left말이되지 않습니다. HTML 이스케이프 문제로 인해 손상되었을 수 있습니다.
Marcelo Cantos

42
위의 코드가 "현대적인"형태의 C ++에서 어떻게 다를 것이라고 생각하는지 궁금합니다.
jamesdlin 2010 년

3
누락 된 문자는 <html 이스케이프로 인한 기호 라고 확신합니다 .
devios1

1
@jamesdlin 함수를 구조체의 멤버 함수로 만들고 하나의 매개 변수를 사용합니다. 둘째, 일반적으로 const * 대신 const &를 사용합니다. 일부 Win32 매크로를 사용하는 대신 템플릿을 사용하여 int, long 및 double 버전을 모두 가질 수 있습니다. (RECT는 형식 이름이 아닌 이름없는 구조체의 인스턴스가되기 때문에 컴파일되지 않습니다.) 예제 : ideone.com/bnzwl3
Sebastian Wahl

답변:


142

이것이 그 코드를 JavaScript로 번역하는 방법입니다. 주석이 제안한대로 코드와 기사에 오타가 있습니다. 구체적 r2->right left이어야 r2->right < r1->left하고 r2->bottom top있어야 r2->bottom < r1->top작동하려면 함수.

function intersectRect(r1, r2) {
  return !(r2.left > r1.right || 
           r2.right < r1.left || 
           r2.top > r1.bottom ||
           r2.bottom < r1.top);
}

테스트 케이스 :

var rectA = {
  left:   10,
  top:    10,
  right:  30,
  bottom: 30
};

var rectB = {
  left:   20,
  top:    20,
  right:  50,
  bottom: 50
};

var rectC = {
  left:   70,
  top:    70,
  right:  90,
  bottom: 90
};

intersectRect(rectA, rectB);  // returns true
intersectRect(rectA, rectC);  // returns false

추가 / 확인하기 위해-이것은 30px x 30px 인 rectB를 제외하고 20px x 20px 인 세 개의 상자를 테스트하는 것입니다
verenion

6
R1 및 R2가 동일한 경우 intersectRect 함수는 거짓 반환
zumalifeguard

환상적인 Eloquent 구현. 그것을 사랑하십시오! +1, 내 게임에 완벽하게 작동했습니다.
Unome 2014 년

1
@zumalifeguard 왜 그렇게 생각하세요?
Minix

이 기능은 정말 천재적입니다. 나는 그것을 결코 생각하지 않았을 것입니다. 대신에 두 상자를 교차 시키려고 노력했을 것입니다.
nikk wong

69
function intersect(a, b) {
  return (a.left <= b.right &&
          b.left <= a.right &&
          a.top <= b.bottom &&
          b.top <= a.bottom)
}

이것은가 top일반적으로보다 작다고 가정합니다 bottom(즉, y좌표가 아래쪽으로 증가 함).


훌륭하고 작동하는 솔루션이지만 모든 조건을 평가해야하므로 약간 느려 야합니다. 다른 솔루션은 조건 중 하나가 참으로 평가되는 즉시 수행됩니다.
Gigo

21
이것은 조건 중 하나가 거짓으로 평가되는 즉시 수행됩니다. 즉, 다른 것과 똑같은 경우입니다.
DS.

3
부정 동작을 제거하므로 더 좋습니다.
Discipol 2013 년

4
+1, 수락 된 답변보다 훨씬 깔끔합니다. 반 개방 범위를 사용하는 경우 (예 : 직사각형에는 상단과 왼쪽이 포함되지만 많은 그래픽 시스템에서 일반적으로 사용되는 하단과 오른쪽은 포함되지 않음)로 변경 <=하면 <작동합니다.
Jules

=각 조건에 대해 제거 할 수 있고 사각형이 테두리에서 "접촉" 할 수 있기 때문에이 솔루션을 좋아합니다 .
prograhammer

19

이것이 .NET Framework가 Rectangle.Intersect를 구현하는 방법입니다.

public bool IntersectsWith(Rectangle rect)
{
  if (rect.X < this.X + this.Width && this.X < rect.X + rect.Width && rect.Y < this.Y + this.Height)
    return this.Y < rect.Y + rect.Height;
  else
    return false;
}

또는 정적 버전 :

public static Rectangle Intersect(Rectangle a, Rectangle b)
{
  int x = Math.Max(a.X, b.X);
  int num1 = Math.Min(a.X + a.Width, b.X + b.Width);
  int y = Math.Max(a.Y, b.Y);
  int num2 = Math.Min(a.Y + a.Height, b.Y + b.Height);
  if (num1 >= x && num2 >= y)
    return new Rectangle(x, y, num1 - x, num2 - y);
  else
    return Rectangle.Empty;
}

6

또 다른 간단한 방법입니다. (이것은 y 축이 아래쪽으로 증가한다고 가정합니다.)

function intersect(a, b) {
  return Math.max(a.left, b.left) < Math.min(a.right, b.right) &&
          Math.max(a.top, b.top) < Math.min(a.bottom, b.bottom);
}

위의 조건에서 4 개의 숫자 (최대 및 최소)도 교차점을 제공합니다.



0

큰 사각형 안에있는 작은 사각형을 감지하기 위해 여러 가지 방법을 사용했습니다. 이것은 nodejs 방법이며 너비 / 높이를 사용하지만 쉽게 조정할 수 있습니다.

            isIntersectingRect: function (r1, r2) {
              var quickCheck = (r1.x <= r2.x + r2.w &&
                      r2.x <= r1.x + r1.w &&
                      r1.y <= r2.y + r2.h &&
                      r2.y <= r1.y + r1.h)
              if (quickCheck) return true;
              var x_overlap = Math.max(0, Math.min(r1.x + r1.w, r2.x + r2.w) - Math.max(r1.x, r2.x));
              var y_overlap = Math.max(0, Math.min(r1.y + r1.h, r2.y + r2.h) - Math.max(r1.y, r2.y));
              var overlapArea = x_overlap * y_overlap;
              return overlapArea == 0;
            }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.