ポイントと軸に揃えられた長方形の間の距離を計算するにはどうすればよいですか?


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;

その二乗距離がゼロの場合、ポイントが長方形に接するか、長方形の内側にあることを意味します。


6
不思議に思っている他の誰のために、(x、y)は長方形の中心ではなく、コーナーで
グレッグRozmarynowycz

2
古いコメントで申し訳ありませんが、この方程式は長方形が軸に沿っていると仮定していますか?
BitNinja 14年

1
@BitNinjaはい、それが質問の前提です。軸に沿っていない場合、最速/最も簡単なアルゴリズムは、長方形情報の保存方法に依存します。
サムホセバー14年

たとえば、ポイントは(4:4)、長方形は(5:5)にあり、幅/高さ(5:5)です。あなたのコードは、ポイントが長方形に触れる、または長方形の内側にあると主張しますが、明らかに外側にあります
-LRN

@LRN(2.5:2.5)から(7.5:7.5)までの幅/高さ(5:5)で(5:5)を中心とする長方形。ポイント(4:4)はその長方形の内側にあります。
サムホセバル

11

私はあなたの長方形が軸に沿っていると仮定します。

ポイントを長方形に「クランプ」し、クランプされたポイントからの距離を計算するだけです。

ポイント=(px、py)、長方形=(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つすべてのコーナーをテストする必要を回避する同様の方法は、stackoverflowでここ文書化されています


対角線方向では、これは、例えば 11ユニット離れています。
エリックB

更新された画像は明らかに間違っており、実際には実際にエラーの事例を示しており、正しく表示されています。その緑色の点は、簡単に10ユニット以上離れていて、その外側の長方形の内側にある可能性があります。
エリックB

@EricBさん、あなたが指摘したエラーを修正しました。あなたのdownvoteを元に戻すのはどうですか?
ケン

あなたの答えが厳密に間違った結果を与えることはもうないので、私は下票を削除しましたが、それはまた最善の方法でもありません。中心が長方形内にあるかどうか、4つの線分が円と交差するかどうかを確認するだけではどうですか?これらの新しい長方形と円の作成は必要ありません。あなたの答えは、ポイントから長方形までの実際の距離も提供しません。
エリックB

この答えは正直、ひどいものです。実際に3行のコードを必要とするタスクに対して、12個の追加、4個のオブジェクト構成、12個のテスト、4個の平方根?
サムホセバー

-2

次のようなものを使用できます。 ここに画像の説明を入力してください


この方法は不必要に複雑に思えます。この問題を解決するためにx1とy1を見つける必要はありません。
エリックB

実際、これは、特定の距離内で衝突を検出する要件さえも満たしていません。これは、ポイントが長方形内にあるかどうかを検出するのに悪い方法です。
エリックB

距離の尺度はすでに暗黙的にそこにあります。if(d2 <10 * 10){/ * 10単位以内* /}
AlexanderBrevig
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.