Search code examples
geometrycollision-detection

Circle-Rectangle collision detection (intersection)


How can I tell whether a circle and a rectangle intersect in 2D Euclidean space? (i.e. classic 2D geometry)


Solution

  • There are only two cases when the circle intersects with the rectangle:

    • Either the circle's centre lies inside the rectangle, or
    • One of the edges of the rectangle has a point in the circle.

    Note that this does not require the rectangle to be axis-parallel.

    Some different ways a circle and rectangle may intersect

    (One way to see this: if none of the edges has a point in the circle (if all the edges are completely "outside" the circle), then the only way the circle can still intersect the polygon is if it lies completely inside the polygon.)

    With that insight, something like the following will work, where the circle has centre P and radius R, and the rectangle has vertices A, B, C, D in that order (not complete code):

    def intersect(Circle(P, R), Rectangle(A, B, C, D)):
        S = Circle(P, R)
        return (pointInRectangle(P, Rectangle(A, B, C, D)) or
                intersectCircle(S, (A, B)) or
                intersectCircle(S, (B, C)) or
                intersectCircle(S, (C, D)) or
                intersectCircle(S, (D, A)))
    

    If you're writing any geometry you probably have the above functions in your library already. Otherwise, pointInRectangle() can be implemented in several ways; any of the general point in polygon methods will work, but for a rectangle you can just check whether this works:

    0 ≤ AP·AB ≤ AB·AB and 0 ≤ AP·AD ≤ AD·AD
    

    And intersectCircle() is easy to implement too: one way would be to check if the foot of the perpendicular from P to the line is close enough and between the endpoints, and check the endpoints otherwise.

    The cool thing is that the same idea works not just for rectangles but for the intersection of a circle with any simple polygon — doesn't even have to be convex!