5

If it was the dist to a point it would be

dist(mouseX, mouseY, x, y)

for

point(x,y)

but how can I calculate dist() from the mouse's current position to

rectMode(CORNERS);
rect(x1,y2,x2,y2);

Thanks

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
Julio Diaz
  • 9,067
  • 19
  • 55
  • 70
  • If `(mouseX, mouseY)` is inside the rectangle, do you want the distance to be 0? Or do you mean distance to the boundary of the rectangle? –  Feb 25 '11 at 01:36
  • @Jan it would be the distance to the boundary of the rectangle – Julio Diaz Feb 25 '11 at 01:37

3 Answers3

6

Something like this should do it:

float distrect(float x, float y, float x1, float y1, float x2, float y2){
  float dx1 = x - x1;
  float dx2 = x - x2;
  float dy1 = y - y1;
  float dy2 = y - y2;

  if (dx1*dx2 < 0) { // x is between x1 and x2
    if (dy1*dy2 < 0) { // (x,y) is inside the rectangle
      return min(min(abs(dx1), abs(dx2)),min(abs(dy1),abs(dy2)));
    }
    return min(abs(dy1),abs(dy2));
  }
  if (dy1*dy2 < 0) { // y is between y1 and y2
    // we don't have to test for being inside the rectangle, it's already tested.
    return min(abs(dx1),abs(dx2));
  }
  return min(min(dist(x,y,x1,y1),dist(x,y,x2,y2)),min(dist(x,y,x1,y2),dist(x,y,x2,y1)));
}

Basically, you need to figure out if the closes point is on one of the sides, or in the corner. This picture may help, it shows the distance of a point from a rectangle for different positions of the point: enter image description here

  • +1 I used your nested min(min()) idea rather than setting min_dist, checking it against a temp min_dist, setting a new min_dist, etc. – gary Feb 25 '11 at 04:26
1

Here's a somewhat interactive program which accomplishes what you're looking for. You can drop it into Processing and run it if you would like.

EDIT: Here's a screenshot:

rectangleDistance.pde

// Declare vars.
int x_click = -20;      // Initializes circle and point off-screen (drawn when draw executes)
int y_click = -20;
float temp = 0.0;
float min_dist = 0.0;
int x1, x2, x3, x4, y1, y2, y3, y4;

// Setup loop.
void setup() {
  size(400, 400);

 // Calculate the points of a 40x40 centered rectangle
  x1 = width/2 - 20; 
  y1 = height/2 - 20;
  x2 = width/2 + 20;
  y2 = y1;
  x3 = x1;
  y3 = height/2 + 20;
  x4 = x2;
  y4 = y3;
}


// Draw loop.
void draw(){
  background(255); 

  // Draws a purple rectangle in the center of the screen.
  rectMode(CENTER);
  fill(154, 102, 200);
  rect(width/2, height/2, 40, 40);

  // Draws an orange circle where the user last clicked.
  ellipseMode(CENTER);
  fill(204, 102, 0);
  ellipse(x_click, y_click, 10, 10);

  // Draws black point where the user last clicked.
  fill(0);
  point(x_click, y_click);

  // Draws min dist onscreen.
  textAlign(CENTER);
  fill(0);
  text("min dist = " + min_dist, width/2, height/2 + 150);  
}


void mousePressed(){
  x_click = mouseX;
  y_click = mouseY;

  // If the click isn't perpendicular to any side of the rectangle, the min dist is a corner.
  if ( ((x_click <= x1) || (x_click >= x2)) && ((y_click <= y1) || (y_click >= y3))  ) {
    min_dist = min(min(dist(x1,y1,x_click,y_click),dist(x2,y2,x_click,y_click)), min(dist(x3,y3,x_click,y_click),dist(x4,y4,x_click,y_click)));

  } else if( (x_click > x1)  && (x_click < x2) && ((y_click < y1) || (y_click > y3)) ) {
    // outside of box, closer to top or bottom
    min_dist = min(abs(y_click - y1), abs(y_click - y3));

  } else if( (y_click > y1) && (y_click < y3) && ((x_click < x1) || (x_click > x2)) ) {
   // outside of box, closer to right left
   min_dist = min(abs(x_click - x1), abs(x_click - x2));
  } else {
    // inside of box, check against all boundaries
    min_dist = min(min(abs(y_click - y1), abs(y_click - y3)),min(abs(x_click - x1), abs(x_click - x2)));
  }
  // Print to console for debugging.
  //println("minimum distance = " + min_dist);

}
gary
  • 4,227
  • 3
  • 31
  • 58
0

This is what I use. If you are only interested in the relative distance there is probably no need to take the square root which should make it slightly quicker.

- (NSInteger) distanceFromRect: (CGPoint) aPoint rect: (CGRect) aRect
{
    NSInteger posX = aPoint.x;
    NSInteger posY = aPoint.y;

    NSInteger leftEdge   = aRect.origin.x;
    NSInteger rightEdge  = aRect.origin.x + aRect.size.width;

    NSInteger topEdge    = aRect.origin.y;
    NSInteger bottomEdge = aRect.origin.y + aRect.size.height;

    NSInteger deltaX = 0;
    NSInteger deltaY = 0;

    if (posX < leftEdge)       deltaX = leftEdge - posX;
    else if (posX > rightEdge) deltaX = posX - rightEdge;

    if (posY < topEdge)         deltaY = topEdge - posY;
    else if (posY > bottomEdge) deltaY = posY - bottomEdge;

    NSInteger distance = sqrt(deltaX * deltaX + deltaY * deltaY);

    return distance;
}