# What is the fastest way to work out 2D bounding box intersection?

Assume that each Box object has the properties x, y, width, height and have their origin at their center, and that neither the objects nor the bounding boxes rotate.

-
Are these axis or object-aligned bounding boxes? – tenpn Jul 16 '10 at 9:48
When you ask this question, you'll surely need to test other types of intersections in the future ;). Therefore I suggest THE LIST about Object/Object intersection. The table provides intersections between all popular object types (boxes, spheres, triangles, cyclinders, cones, ...) in static as well as dynamic situations. – Dave O. Jul 17 '10 at 18:13
Please rephrase Your question to bounding rects. From my point of view box implies a 3d object. – Dave O. Jul 17 '10 at 18:16

(C-ish pseudocode - adapt language optimizations as appropriate)

``````bool DoBoxesIntersect(Box a, Box b) {
return (abs(a.x - b.x) * 2 < (a.width + b.width)) &&
(abs(a.y - b.y) * 2 < (a.height + b.height));
}
``````

In English: On each axis, check to see if the centers of the boxes are close enough that they'll intersect. If they intersect on both axes, then the boxes intersect. If they don't, then they don't.

You can change the <'s to <= if you want to count edge-touching as intersecting. If you want a specific edge-touch-only formula, you can't use == - that will tell you if the corners touch, not if the edges touch. You'd want to do something logically equivalent to `return DoBoxesIntersectOrTouch(a, b) && !DoBoxesIntersect(a, b)`.

It's worth mentioning that you can get a small but significant speed increase by storing the half-width and half-height in addition to (or instead of) the full width and full height. On the other hand, it's rare for 2d bounding box intersection to be the performance bottleneck.

-
Thanks for your answer! I have a feeling abs might be quite slow in Actionscript. When I get some more answers I will benchmark them. – Iain Jul 16 '10 at 9:35
This obviously assumes the boxes are axis-aligned. – tenpn Jul 16 '10 at 9:48
Abs shouldn't be particularly slow - no slower than a conditional, at least, and the only way to do it without abs (that I'm aware of) involves extra conditionals. – ZorbaTHut Jul 16 '10 at 9:51
Yes, it does assume axis-aligned boxes. The structures as described don't have any way of indicating rotation, though, so I felt it was safe. – ZorbaTHut Jul 16 '10 at 9:52
Here are some good tips for speeding up calulations in Actionscript (mainly integer calc): lab.polygonal.de/2007/05/10/bitwise-gems-fast-integer-math I'm posting this, because it also contains a faster replacement for Math.abs(), which tends to slow down things in Actionscript indeed (speaking of performance critical stuff of course). – bummzack Jul 16 '10 at 17:32

This works for two rectangles aligned with the X and Y axis.
Each rectangle has the properties:
"left", the x coordinate of its left side,
"top", the y coordinate of its top side,
"right", the x coordinate of its right side,
"bottom", the y coordinate of its bottom side,

``````function IntersectRect(r1:Rectangle, r2:Rectangle):Boolean {
return !(r2.left > r1.right
|| r2.right < r1.left
|| r2.top > r1.bottom
|| r2.bottom < r1.top);
}
``````

Note that this is designed for a coordinate system in which the +y axis points down and the +x axis is directed to the right (i.e. typical screen/pixel coordinates). To adapt this to a typical cartesian system in which +y is directed upward, the comparisons along the vertical axes would be reversed, e.g.:

``````return !(r2.left > r1.right
|| r2.right < r1.left
|| r2.top < r1.bottom
|| r2.bottom > r1.top);
``````

The idea is to capture all possible conditions upon which the rectangles will not overlap, and then negate the answer to see if they are overlapped. Regardless of the direction of the axes, it's easy to see that two rectangles will not overlap if:

• the left edge of r2 is further right than the right edge of r1

`````` ________     ________
|        |   |        |
|   r1   |   |   r2   |
|        |   |        |
|________|   |________|
``````
• or the right edge of r2 is further left than the left edge of r1

`````` ________     ________
|        |   |        |
|   r2   |   |   r1   |
|        |   |        |
|________|   |________|
``````
• or the top edge of r2 is below the bottom edge of r1

`````` ________
|        |
|   r1   |
|        |
|________|
________
|        |
|   r2   |
|        |
|________|
``````
• or the bottom edge of r2 is above the top edge of r1

`````` ________
|        |
|   r2   |
|        |
|________|
________
|        |
|   r1   |
|        |
|________|
``````

The original function - and an alternative description of why it works - can be found here: http://tekpool.wordpress.com/2006/10/11/rectangle-intersection-determine-if-two-given-rectangles-intersect-each-other-or-not/

-
Surprisingly intuitive and shows once more that when finding the answer is too hard, trying to find the answer to an opposite question might help you out. Thanks! – Lodewijk Jun 26 '14 at 23:05
You should mention that the y axis points down (as in an image). Otherwise the inequalities r2.top > r1.bottom and r2.bottom < r1.top needs to be reversed. – user1443778 Jun 3 '15 at 17:12
@user1443778 good catch! I went ahead and loosely explained the logic behind this algorithm in a coordinate system-agnostic way, too. – Wallacoloo Jun 4 '15 at 5:15

If you want object-aligned bounding boxes, try this tutorial on the seperation axis theorem by metanet: http://www.metanetsoftware.com/technique/tutorialA.html

SAT isn't the fastest solution, but it's relatively simple. You're trying to find a single line (or a plane if 3D) that will seperate your objects. If this line exists it's guarenteed to be paralell to the edge of one of your boxes, so you iterate through all edges testing to see if it seperates the boxes.

This also works for axis-aligned boxes by constraining to just the x/y axis.

-
I wasn't thinking of rotation, but thanks that's an interesting link. – Iain Jul 16 '10 at 12:17

The DoBoxesIntersect above is a good pairwise solution. However, if you have a lot of boxes, you still have an O(N^2) problem, and you might find you need to do something on top of that like what Kaj refers to. (In the 3D collision detection literature, this is known as having both a broad-phase and a narrow-phase algorithm. We'll do something really fast to find all possible pairs of overlaps, and then something more expensive to see if our possible pairs are actual pairs.)

The broad-phase algorithm I've used before is "sweep-and-prune"; for 2D, you'd maintain two sorted lists of the start and end of each box. As long as box movement is not >> box scale from frame to frame, the order of these lists isn't going to change much, and so you can use bubble or insertion sort to maintain it. The book "Real-Time Rendering" has a nice writeup on optimizations you can do, but it boils down to O(N+K) time in the broad phase, for N boxes, K of which overlap, and with excellent real-world performance if you can afford N^2 booleans to keep track of which pairs of boxes are intersecting from frame-to-frame. You then have O(N+K^2) time overall, which is << O(N^2) if you have many boxes but only a few overlaps.

-

``````bool DoBoxesIntersect(Box a, Box b) {
return (abs(a.x - b.x) < (a.width + b.width) / 2) &&
(abs(a.y - b.y) < (a.height + b.height) / 2);
}
``````
-
Actually that arithmetic works fine either way. You can do any arithmetic operation to either side of the < and it doesn't change it (multiplication by a negative means you have to change the less than, though). In that example, the boxes shouldn't collide. If the center of box A is at 1, it spans from -4 to 6. Box b centers at 10, and spans 7.5 to 12.5, there is no collision there... Now, the method that Wallacoloo posted is not only correct, but will run faster on languages that implement short circuiting, since most checks will return false anyway, the short circuiting can cut out after a s – Deleter Aug 11 '10 at 17:34
Yes I realised this when I woke up this morning. Chris bambusaled me with his < > mix up. – Iain Aug 12 '10 at 6:13
Two problems: first, division tends to be significantly slower than multiplication. Second, if the values involved are integers, this might result in some integer truncation issues (a.x = 0, b.x = 9, a.width = 9, b.width = 10: abs(0-9) < (9+10)/2, 9 < 19/2, 9 < 9, function returns false despite the fact that the boxes definitively intersect.) – ZorbaTHut Feb 5 '12 at 1:33

Lot of math here for a very simple problem, assume that we have 4 points determined for a rect, top, left, bottom, right...

In the case of determining whether 2 rects collide we need only look that all possible extremes that would prevent collisions, if none of these are met, then the 2 rects MUST collide, if you want to include boundary collisions, simply replace the > and < with appropriate >= and =<.

``````struct aRect{
float top;
float left;
float bottom;
float right;
};

bool rectCollision(rect a, rect b)
{
return ! ( b.left > a.right || b.right < a.left || b.top < a.bottom || b.bottom > a.top);
}
``````
-

Depending on the problem you try to solve you might be better off keeping track of your object while you move them, ie, keep a list of sorted x start and end positions and one for start and end y positions. If you have to do a LOT of overlap checks and therefore need to optimize, you can use this to your advantage, as you can immediately look up who is ending closes to your left, everyone who's ending is to the left of that can be pruned immediately. Same apply for top, bottom and right.
The bookkeeping costs time of course, so it's more suited for a situation with few moving objects but lots of overlap checks.
Another optionh is spatial hashing, where you bucket the objects based on approximate position (size might put em in multiple buckets), but there again, only if there's a lot of objects, with relatively few of them moving per iteration due to bookkeeping cost.
Basically anything that avoids (n*n)/2 (if you check object a against b you won't have to check b against a obviously) helps more than optimizing bounding box checks. If bounding box checks are a bottleneck, I'd seriously advise to look into alternative solutions to the problem.

-

The distance between centers is not the same as the distance between corners (when one box is inside the other for instance), so IN GENERAL, this solution is the correct one (me thinks).

distance between centers (for, say, x): `abs(x1+1/2*w1 - x2+1/2*w2)` or `1/2 * abs(2*(x1-x2)+(w1-w2)`

Minimum distance is `1/2 w1 + 1/2 w2 or 1/2 (w1+w2)`. the halves cancel so..

``````return
ABS(2*(x1 - x2) + (w1-w2) ) < (w1+w2)) &&
ABS(2*(y1 - y2) + (h1-h2) ) < (h1+h2));
``````
-
What's with the "return" statement in there? – doppelgreener Sep 23 '12 at 11:36