점과 축 정렬 사각형 사이의 거리를 어떻게 계산합니까?


29

x, y 위치, 높이 및 너비 및 임의로 위치가 지정된 2D 직사각형이 근처에 있습니다.

이 점이 특정 거리보다 가까운 경우이 점이 사각형과 충돌하는지 확인하는 방법이 있습니까? 해당 사각형의 바깥쪽에 보이지 않는 반경이 있다고 상상해보십시오. 사각형이 아니기 때문에 이것에 문제가 있습니다!

답변:


26

(x,y)사각형의 중심 이면 점으로부터의 제곱 거리(px,py) 에서 사각형의 경계 계산할 수 있습니다.

dx = max(abs(px - x) - width / 2, 0);
dy = max(abs(py - y) - height / 2, 0);
return dx * dx + dy * dy;

이 제곱 거리가 0이면 점이 사각형에 닿거나 안에 있음을 의미합니다.


6
궁금해 다른 사람, (x, y)에 들어하지 코너, 사각형의 중심
그렉 Rozmarynowycz

2
이전 주석은 유감이지만이 방정식은 사각형이 축 정렬되어 있다고 가정합니까?
BitNinja

1
@BitNinja 네, 그 질문이 가정합니다. 축 정렬되지 않은 경우 가장 빠르고 가장 간단한 알고리즘은 사각형 정보가 저장되는 방법에 따라 다릅니다.
sam hocevar

즉, 포인트는 (4 : 4)이고 직사각형은 너비 / 높이 (5 : 5)로 (5 : 5)에 있습니다. 코드는 점이 사각형에 닿거나 사각형 안에 있다고 주장하지만 분명히 바깥에 있습니다.
LRN

@LRN 너비 / 높이 (5 : 5)를 중심으로 (5 : 5)를 중심으로하는 사각형은 (2.5 : 2.5)에서 (7.5 : 7.5)까지입니다. 점 (4 : 4)은 해당 사각형 안에 있습니다.
sam hocevar

11

직사각형이 축 정렬이라고 가정합니다.

점을 사각형에 "고정"한 다음 고정 점과의 거리를 계산하면됩니다.

Point = (px, py), Rectangle = (rx, ry, rwidth, rheight) // (왼쪽 상단, 치수)

function pointRectDist (px, py, rx, ry, rwidth, rheight)
{
    var cx = Math.max(Math.min(px, rx+rwidth ), rx);
    var cy = Math.max(Math.min(py, ry+rheight), ry);
    return Math.sqrt( (px-cx)*(px-cx) + (py-cy)*(py-cy) );
}

3

이를 위해 반드시 원-사각 충돌을 사용해야합니다. 있다 유사한스택 오버플로에 질문 .

원의 중심이 문제의 지점이되고 반경은 확인하려는 거리가됩니다.


3

점에서 사각형의 가장자리까지의 거리를 알아 내려는 경우 사각형으로 만든 9 개의 영역 각각을 사용하는 것이 가장 빠른 방법 일 수 있습니다.

function pointRectangleDistance(x, y, x1, y1, x2, y2) {
    var dx, dy;
    if (x < x1) {
        dx = x1 - x;
        if (y < y1) {
            dy = y1 - y;
            return Math.sqrt(dx * dx + dy * dy);
        }
        else if (y > y2) {
            dy = y - y2;
            return Math.sqrt(dx * dx + dy * dy);
        }
        else {
            return dx;
        }
    }
    else if (x > x2) {
        dx = x - x2;
        if (y < y1) {
            dy = y1 - y;
            return Math.sqrt(dx * dx + dy * dy);
        }
        else if (y > y2) {
            dy = y - y2;
            return Math.sqrt(dx * dx + dy * dy);
        }
        else {
            return dx;
        }
    }
    else {
        if (y < y1) {
            return y1 - y;
        }
        else if (y > y2) {
            return y - y2;
        }
        else {
            return 0.0; // inside the rectangle or on the edge
        }
    }
}

2

[댓글을 기반으로 수정 된 답변]

아래 이미지의 회색 사각형이 포인트가 10 단위 이내인지 확인하려면 포인트가 다음 중 하나에 있는지 확인하십시오.

  1. 빨간 사각형
  2. 파란색 사각형
  3. 녹색 원 중 하나 (반지름 10)

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

inside=false;

bluerect.x=oldrect.x-10;
bluerect.y=oldrect.y;
bluerect.width=oldrect.width;
bluerect.height=oldrect.height+20;

if(  point.x >=bluerect && point.x <=redrect.x+bluerect.width &&
     point.y >=bluerect && point.y <=redrect.y+bluerect.height){
         //now point is side the blue rectangle
         inside=true;
}

redrect.x=oldrect.x;
redrect.y=oldrect.y-10;
redrect.width=oldrect.width+20;
redrect.height=oldrect.height;

if(  point.x >=redrect&& point.x <=redrect.x+redrect.width &&
     point.y >=redrect&& point.y <=redrect.y+redrect.height){
         //now point is side the redrectangle
         inside=true;
}


d1= distance(point, new point(oldrect.x, oldrect.y)) //calculate distance between point and (oldrect.x, oldrect.y)
d2= distance(point, new point(oldrect.x+10, oldrect.y))
d3= distance(point, new point(oldrect.x, oldrect.y+10))
d4= distance(point, new point(oldrect.x+10, oldrect.y+10))
if (d1 < 10 || d2 <10 || d3 < 10 || d4 <10){
    inside=true;
}

//inside is now true if the point is within 10 units of rectangle

이 접근법은 약간 우아하지 않습니다. 사각형 대칭을 사용하여 4 개의 모서리를 모두 테스트하지 않아도되는 비슷한 방법이 여기설명되어 있습니다 .


대각선 방향으로 이것은 예를 들어 포인트에 대해 잘못된 긍정을 제공합니다. 11 유닛 떨어져 있습니다.
Eric B

업데이트 된 그림은 명백히 잘못되었습니다. 실제로 실제로 오류 사례를 보여주고 올바르게 표시합니다. 초록색 포인트는 10 단위 이상 떨어져 외부 사각형 안에있을 수 있습니다.
Eric B

@EricB, 당신이 지적한 오류를 수정했습니다. downvote를 취소하는 방법은 무엇입니까?
Ken

귀하의 답변은 더 이상 잘못된 결과를 제공하지 않으므로 공감대를 제거했지만 가장 좋은 방법은 아닙니다. 중심이 사각형 안에 있는지, 네 개의 선분이 원과 교차하는지 테스트하는 것이 어떻습니까? 이 새로운 사각형과 원의 구성은 필요하지 않습니다. 답은 점에서 사각형까지의 실제 거리를 제공하지 않습니다.
에릭 B

이 대답은 솔직히 끔찍합니다. 실제로 3 줄의 코드가 필요한 작업에 12 개의 추가, 4 개의 객체 구성, 12 개의 테스트, 4 개의 제곱근?
sam hocevar

-2

다음과 같은 것을 사용할 수 있습니다. 여기에 이미지 설명을 입력하십시오


이 방법은 불필요하게 복잡해 보입니다. 이 문제를 해결하기 위해 x1과 y1을 찾을 필요는 없습니다.
Eric B

실제로, 이것은 주어진 거리 내에서 충돌을 찾아야하는 요구 사항을 만족 시키지도 않습니다. 점이 사각형 내에 있는지 감지하는 것은 나쁜 방법입니다.
Eric B

거리 측정은 이미 암시 적으로 존재합니다. if (d2 <10 * 10) {/ * 10 측정 단위 내 * /}
AlexanderBrevig
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.