Circle/Box Intersection
While thinking of the collision system for the game I'm writing, I decided I'll be using circles and boxes. All entities will use bounding circles ( either one or a set of circles to better describe the shape ) whereas the level static geometry will be using boxes for easier editing.
This led me to the need of solving circle/box collisions since circle/circle collisions are the easiest thing ever. The target game being a vertical space shmup one can easily figure out we're only going to check collisions between circles and AABB ( axis aligned bounding box ).
Let's try and define a
So, a
Ok, so where do we start ?
Algorithm
We'll get the angle between circle and box, project a line from the box centerpoint onto the rectangle at the given angle and finally check if the distance between the center points is lower than or equal to the sum of the circle's radius and box's calculated "radius" for given angle.
Getting the angle between the objects :
Findind the "radius" of a box at a specified angle :
What we're doing here is to make use of right angle triangles and calculate hypotenuse ( the box "radius" ).
Are you done ? No, we're not, there's one more case we need to cover. An image worths a thousand words.

As we can see, even though the sum of radii is smaller than the distance between the objects' center, the objects are colliding and we are missing this collision. The to fix this is to get the closest corner to the circle and check whether it is inside the circle or not. This will guarantee we will not miss any collisions.
Finding the closest corner and checking whether inside circle or not :
Checking if a point lies inside a circle or not :
Speeding it up
What can we do to speed up the collision detection routine ? We can early find all collisions in which the center of the circle is inside the box :
Source code
As I wanted to test the algorithm, I chose to code it in PHP. For the implementation download this file.
This led me to the need of solving circle/box collisions since circle/circle collisions are the easiest thing ever. The target game being a vertical space shmup one can easily figure out we're only going to check collisions between circles and AABB ( axis aligned bounding box ).
Let's try and define a
Circle and a Box :class Circle {
public:
Circle( float centerX, float centerY, floar r )
: x( centerX ), y( centerY ), radius( r ) {
}
float x;
float y;
float radius;
};
class Box {
public:
Box( float centerX, float centerY, floar w, float h )
: x( centerX ), y( centerY ), width( w ), height( h ) {
halfWidth = w / 2.0;
halfHeight = h / 2.0;
}
float x;
float y;
float width;
float height;
float halfWidth;
float halfHeight;
};
So, a
Circle is defined by a center position and a radius whereas we define the Box by a centerpoint, a width and a height. halfWidth and halfHeight will only make our life easier later on.Ok, so where do we start ?
Algorithm
We'll get the angle between circle and box, project a line from the box centerpoint onto the rectangle at the given angle and finally check if the distance between the center points is lower than or equal to the sum of the circle's radius and box's calculated "radius" for given angle.
Getting the angle between the objects :
float distX = circle.x - box.x;
float distY = circle.y - box.y;
float angle = atan2( distY, distX );
if ( angle < 0 ) {
angle += 2.0*PI; // we want angle in [0,2*PI]
}
Findind the "radius" of a box at a specified angle :
class Box {
float alpha;
// find the diagonale bottom right angle
// call this when setting width or height
void calculateAlpha() {
alpha = atan2( halfHeight / halfWidth );
}
...
// calculate the "radius" of a rectangle at an angle
// theta must be in radians and must belong [0,2*PI]
float getRadius( float theta ) {
if ( theta < alpha || theta >= ( 2.0*PI - alpha ) ) {
return halfWidth / cos( theta );
}
if ( theta < ( PI - alpha ) ) {
return halfHeight / cos( theta - PI/2.0 );
}
if ( theta < ( PI + alpha ) ) {
return halfWidth / cos( theta - PI );
}
// no need for the extra if since we have covered
// all the other posibilities
// if ( theta < ( 2.*PI - alpha ) ) {
return halfHeight / cos( theta - 3.0*PI/2.0 );
//}
}
};
What we're doing here is to make use of right angle triangles and calculate hypotenuse ( the box "radius" ).
Hypotenuse = adjacent side / cos( adjacent angle )All we have to do now is to check the distance between objects' centers with respect to the sum of "radii".
float dist = sqrt( distX*distX + distY*distY );
float reamining = dist - circle.radius
- box.getRadius( angle );
if ( remaining <= 0 )
{
// the box and circle collide
// do something meaningful
}
Are you done ? No, we're not, there's one more case we need to cover. An image worths a thousand words.

Finding the closest corner and checking whether inside circle or not :
float cornerX = ( angle > 3.0*PI/2.0 || angle < PI/2.0 ) ?
box.x + box.halfWidth : box.x - box->halfWidth;
float cornerY = ( angle >= 0 && angle <= PI ) ?
box.y + box.halfHeight : box.y - box.halfHeight;
if ( circle.isPointInside( cornerX, cornerY ) ) {
// we definitely have a collision
}
// if we got to this point it means
// our shapes don't collide
Checking if a point lies inside a circle or not :
class Circle {
...
bool isPointInside( float x, float y ) {
float distX = x - this->x;
float distY = y - this->y;
float squareR = distX*distX + distY*distY;
return ( squareR <= this->squareRadius ) ? true : false;
}
};
Speeding it up
What can we do to speed up the collision detection routine ? We can early find all collisions in which the center of the circle is inside the box :
// circle center inside the box ?
if ( box.isPointInside( circle.x, circle.y ) ) {
// collision detected
// do not follow the rest of tests
}
Source code
As I wanted to test the algorithm, I chose to code it in PHP. For the implementation download this file.