Collision detection between circles

February 19, 2009 at 9:21 pm (iPhone development, Uncategorized) (, , , , )

Collision detection can be a little difficult with complex paths like arbitrary bezier objects.  But when the two objects are circles?  piece of cake! Find the center of each circle, then compare the distance between them. If that is less than the sum of the two radii, they collide.

The calculation is from high school geometry, and yes most of you have forgotten it. As apparently, did I. You probably recognize this:

x^2 + y^2 = z^2

and you might even remember what it applies to. When programming on the iPhone, we have x and y in coordinates from the UIView. When making the comparison between the above mentioned distance between points and radii, it’s easier to compare the squares of the respective z values, so we don’t have to compute 2 unnecessary and expensive square roots.

So anyway, I implement said solution, and go about my business. Over the next week or so, I notice that my collision detection is a little bit inaccurate. Not a lot, but a little. One night I decide I’m going to get it pixel perfect, since I should be able to pretty easily.

A few hours later, I give up and call in my wife. You see, she actually does this kind of math all day, every day. Well, not all day every day, but on a regular basis, every week. She’s a structural engineer, and they have to do calcs to make sure your house doesn’t fall over because of an over-imaginative and under-detail-oriented architect.

It turns out, I made a small…tiny mistake in how I formed the final equation. Rather than squaring the sum of the two radii, I squared each one separately, then added them together. That is:

I wrote:

rad_1^2 + rad_2^2

correct:

(rad_1 + rad_2)^2

Very easy to do in code, so watch out for it. It’s a nasty little bug to track down, because the inaccuracy changes based on the size of the circles…which varies in my app.

The final code I ended up with is below:

-(bool)collisionDetect:(DragView*)otherView
{
CGRect m_frame = [self frame];
CGRect o_frame = [otherView frame];

float m_rad = m_frame.size.width / 2;
float o_rad = o_frame.size.width / 2;

CGPoint m_center = m_frame.origin;
m_center.x += m_rad;
m_center.y += m_rad;

CGPoint o_center = o_frame.origin;
o_center.x += o_rad;
o_center.y += o_rad;

CGPoint dt;
dt.x = m_center.x – o_center.x;
dt.y = m_center.y – o_center.y;

float x_sq = dt.x * dt.x;
float y_sq = dt.y * dt.y;

// this is wrong, I screwed up the original calculation
//float mrad_sq = m_rad * m_rad;
//float orad_sq = o_rad * o_rad;

float rad_sq = (o_rad + m_rad) * (o_rad + m_rad);

return (rad_sq) > (x_sq + y_sq);
}

R.

1 Comment

  1. Passel said,

    Great!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: