How do I see if two rectangles intersect in JavaScript or pseudocode?

Update

After a time I decided to redo a complete answer about detecting collision between 2 rotated rectangles: How to detect when rotated rectangles are colliding each other


Original Answer

If you want to check if 2 rotated rectangles collide you have to make projection of one rectangle corner on the axes of the other. If all projections of rectA hit the rectB, and rectB projections hit rectA then the two rectangles collide.

Some projection don't collide here, the 2 rectangles are not collide. enter image description here

The 4 projections hit the other rectangle, the 2 rectangles are collide. enter image description here

I have made a presentation on this JSFiddle for more comprehension.

You can check the function is_collide for more example


Two rectangles are overlapping if both the x and the y areas Overlap. If any of the x co-ordinates overlap the other rectangles, then there will be an over lap.

Along the x axis, either the first point is within the other two rectangles, the second point is within the other two, or two points are on opposite sides of the other points.

function checkRectOverlap(rect1, rect2) {
    /*
     * Each array in parameter is one rectangle
     * in each array, there is an array showing the co-ordinates of two opposite corners of the rectangle
     * Example:
     * [[x1, y1], [x2, y2]], [[x3, y3], [x4, y4]]
     */

    //Check whether there is an x overlap
    if ((rect1[0][0] < rect2[0][0] && rect2[0][0] < rect1[1][0]) //Event that x3 is inbetween x1 and x2
        || (rect1[0][0] < rect2[1][0] && rect2[1][0] < rect1[1][0]) //Event that x4 is inbetween x1 and x2
        || (rect2[0][0] < rect1[0][0] && rect1[1][0] < rect2[1][0])) {  //Event that x1 and x2 are inbetween x3 and x4
        //Check whether there is a y overlap using the same procedure
        if ((rect1[0][1] < rect2[0][1] && rect2[0][1] < rect1[1][1]) //Event that y3 is between y1 and y2
            || (rect1[0][1] < rect2[1][1] && rect2[1][1] < rect1[1][1]) //Event that y4 is between y1 and y2
            || (rect2[0][1] < rect1[0][1] && rect1[1][1] < rect2[1][1])) { //Event that y1 and y2 are between y3 and y4
            return true;
        }
    }
    return false;
}

Check for the cases where the rectangles are definitely not intersecting. If none of these cases are true then the rectangles must intersect. i.e.:

public boolean rectanglesIntersect( 
    float minAx, float minAy, float maxAx, float maxAy,
    float minBx, float minBy, float maxBx, float maxBy ) {
    boolean aLeftOfB = maxAx < minBx;
    boolean aRightOfB = minAx > maxBx;
    boolean aAboveB = minAy > maxBy;
    boolean aBelowB = maxAy < minBy;

    return !( aLeftOfB || aRightOfB || aAboveB || aBelowB );
}

This illustrates the concept but could be made slightly faster by inlining the booleans so as to take advantage of the short-circuiting behavior of ||


A look at the matter from a different site.

The case turns out to be quite simple if we look at the problem (algorithm) from the other side.

It means that instead of answering the question: "Are the rectangles overlap?", we will answer the question: "Are the rectangles do not overlap?".

In the end, both questions resolve the same problem but the answer to the second question is simpler to implement because rectangles do not overlap only when one is under the other or when one is more to the left of the other (it is enough for one of these cases to take place, but of course it may happen that both will happen simultaneously - here a good understanding of the logical condition "or" is important). This reduces many cases that need to be considered on the first question.

The whole matter is also simplified by the use of appropriate variable names:

const areRectanglesOverlap = (rect1, rect2) => {
  let [left1, top1, right1, bottom1] = [rect1[0], rect1[1], rect1[2], rect1[3]],
      [left2, top2, right2, bottom2] = [rect2[0], rect2[1], rect2[2], rect2[3]];
  // The first rectangle is under the second or vice versa
  if (top1 < bottom2 || top2 < bottom1) {
    return false;
  }
  // The first rectangle is to the left of the second or vice versa
  if (right1 < left2 || right2 < left1) {
    return false;
  }
  // Rectangles overlap
  return true;
}

Even if we have a different representation of a rectangle, it is easy to adapt the above function to it by modifying only the section where the variables changes are defined. The further part of the function remains unchanged (of course, the comments are not really needed here, but I added them so that everyone could quickly understand this simple algorithm).

An equivalent but maybe a little less readable form of the above function may look like this:

const areRectanglesOverlap = (rect1, rect2) => {

  let [left1, top1, right1, bottom1] = [...rect1],
      [left2, top2, right2, bottom2] = [...rect2];
  
  return !(top1 < bottom2 || top2 < bottom1 || right1 < left2 || right2 < left1);
}