Rectangle Intersection Test

11 May 2011 11 May 2011 3 min read Algorithms WPF

For a software project I needed to check whether two rectangles intersect (or overlap). What made my problem complicated was that one of the rectangles could be rotated. While this problem seems to be trivial (to a human being), it’s not that simple to implement. It took me a while to find the right answer.

Intersecting Rectangles

Now, the solution to this problem is called a separating axis test. Basically this means: If I can find an axis (read: line) that separates both rectangles, then they don’t intersect/overlap. (Actually this works for any convex polygon; see below) Of course, if the two rectangles don’t intersect, there are indefinitely many possible separating axes. Fortunately we can use the edges of each rectangle as axes and testing all of the is sufficient.

An axis separating two rectangles

I won’t get into the details of this algorithm here - it’s sufficiently good described in the article mentioned above - but basically you check for each point on which side of the separating axis it is. If all points of the rectangle A are on one side and all of rectangle B are on the other side, then we’ve found a separating axis.

Here’s the implementation of the method testing where a single edge (represented by points x1 and x2) is a separating axis:


/// <summary>
/// Does axis separation test for a convex quadrilateral.
/// </summary>
/// <param name="x1">Defines together with x2 the edge of quad1 to be checked whether
/// its a separating axis.</param>
/// <param name="x2">Defines together with x1 the edge of quad1 to be checked whether
/// its a separating axis.</param>
/// <param name="x3">One of the remaining two points of quad1.</param>
/// <param name="otherQuadPoints">The four points of the other quad.</param>
/// <returns>Returns <c>true</c>, if the specified edge is a separating axis (and the
/// quadrilaterals therefor don't intersect). Returns <c>false</c>, if it's not a
/// separating axis.</returns>
bool DoAxisSeparationTest(Point x1, Point x2, Point x3, Point[] otherQuadPoints)
{
  Vector vec = x2 - x1;
  Vector rotated = new Vector(-vec.Y, vec.X);

  bool refSide = (rotated.X * (x3.X - x1.X)
                + rotated.Y * (x3.Y - x1.Y)) >= 0;

  foreach (Point pt in otherQuadPoints)
  {
    bool side = (rotated.X * (pt.X - x1.X)
               + rotated.Y * (pt.Y - x1.Y)) >= 0;
    if (side == refSide)
    {
      // At least one point of the other quad is one the same side as x3. Therefor
      // the specified edge can't be a separating axis anymore.
      return false;
    }
  }

  // All points of the other quad are on the other side of the edge. Therefor the edge
  // is a separating axis and the quads don't intersect.
  return true;
}

This method is then called for each edge of each rectangle. If the method returns true, the actual intersection test method can return “not intersecting”. If the method returns false for all edges, the rectangles intersect.

The test application

I’ve created an C#/WPF example implementation (under FreeBSD license) that you can download and experiment with.

Rectangle Intersection Test Project (for Visual Studio 2010)

Remarks: The algorithm above works for every convex polygon. Instead of four times two edges you then have n times m edges. For concave polygons, however, this algorithm doesn’t work because there may be no separating axis even though the polygons don’t intersect.