Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a 2D rectangle with x, y position, height and width, and a randomly positioned point nearby.

Is there a way to check if this point might collide with the rectangle if it is closer than a certain distance? Imagine an invisible radius outside of that point colliding with said rectangle. I have problems with this simply because it is not a square, it would be so much easier this way!

share|improve this question

6 Answers 6

The squared distance from a point (px,py) to the rectangle's border can be computed this way:

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

If that squared distance is zero, it means the point touches or is inside the rectangle.

share|improve this answer
1  
For anyone else who is wondering, (x, y) is the center of the rectangle, not the corner –  Greg Rozmarynowycz Oct 13 at 21:12
    
Sorry for the old comment, but does this equation assume that the rectangle is axis-aligned? –  BitNinja Oct 25 at 1:13
    
@BitNinja yes, that’s what the question assumes. If it’s not axis-aligned, the fastest/simplest algorithm will depend on how the rectangle information is stored. –  Sam Hocevar Oct 25 at 13:47

I assume your rectangle is Axis-Aligned.

You just have to "clamp" the point into rectangle and then compute the distance from clamped point.

Point = (px, py), Rectangle = (rx, ry, rwidth, rheight) // (top left corner, dimensions)

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) );
}
share|improve this answer

You must use circle-rectangle collisions for this. There's a similar question on Stack Overflow.

Your circle's center would be the point in question, and the radius would be the distance you want to check.

share|improve this answer

[Modified answer based on comments]

If you want to see if the point is within say 10 units if the grey rectangle in the image below, you check if the point is in any one of

  1. red rectangle
  2. Blue rectangle
  3. any one of the green circles (radius 10)

enter image description here

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

This approach is a little inelegant. A similar method which avoids having to test all 4 corners by using rectangle symmetry is documented here on stackoverflow

share|improve this answer
    
In the diagonal direction this will give a false positive to points that are eg. 11 units away. –  Eric B Nov 26 '12 at 15:56
    
The updated picture is blatantly wrong, in fact it actually illustrates the error case and makes it appear correct. That green point could easily be more than 10 units away and be inside that outer rectangle. –  Eric B Nov 26 '12 at 16:15
    
Hey @EricB, I've fixed the error you pointed out, how about undoing your downvote? –  Ken Nov 26 '12 at 17:37
    
Your answer will no longer give strictly incorrect results, so I removed the downvote, but it is also not the best way at all. Why not just test to see if the center is within the rectangle, and if the four line segments intersect the circle? The construction of these new rectangles and circles is just not necessary. Your answer also does not provide the actual distance from the point to the rectangle. –  Eric B Nov 26 '12 at 17:52
    
This answer is honestly awful. 12 additions, 4 object constructions, 12 tests, 4 square roots for a task that actually requires 3 lines of code? –  Sam Hocevar Nov 28 '12 at 12:12

If you're trying to figure out the distance from a point to a rectangle's edge, working with each of the nine regions created by the rectangle might be the fastest way:

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
        }
    }
}
share|improve this answer

You could use something like this: enter image description here

share|improve this answer
    
This method seems unnecessarily complicated. Finding x1 and y1 is not necessary to solve this problem. –  Eric B Nov 26 '12 at 15:59
    
In fact, this doesn't even satisfy the requirement of finding a collision within a given distance. It's just a bad way of detecting if the point is within the rectangle. –  Eric B Nov 26 '12 at 16:06
    
A measure of distance is already implicitly there. if (d2<10*10) {/*within 10 units of measure*/} –  AlexanderBrevig Nov 27 '12 at 12:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.