两个矩形相交当且仅当在x轴和y轴上均重叠,即rect1.left < rect2.right && rect1.right > rect2.left && rect1.top < rect2.bottom && rect1.bottom > rect2.top。

判断两个矩形是否相交的最简逻辑
只要两个矩形在 x 轴和 y 轴上都重叠,它们就相交。反过来说:如果在任一轴上完全分离,就一定不相交。这是所有轴对齐矩形(AABB)碰撞检测的基础,不涉及旋转、浮点误差容忍或图形库封装。
常见错误是写成“四边全部交叉”,或者误用中心点距离——这两种都会漏判或误判。正确做法是用「分离轴定理」的退化形式:只检查两个轴。
- 假设矩形用
left、right、top、bottom表示(y 向下为正,常见于 SDL / WinAPI / 大多数 GUI 坐标系) - 相交条件就是:
rect1.left rect2.left && rect1.top rect2.top - 如果坐标系 y 向上为正(如 OpenGL 纹理坐标),只需把
top/bottom含义对调,逻辑不变
用 std::pair 或结构体传参时的典型坑
很多人把矩形封装成 std::pair<:pair>, std::pair<int>></int></:pair> 或类似嵌套结构,结果比较时搞混 left/right 顺序,或者忘记 first/second 对应的是 x 还是 y。
更稳妥的做法是定义清晰字段名:
立即学习“C++免费学习笔记(深入)”;
struct Rect {
int left, right, top, bottom;
};
bool intersects(const Rect& a, const Rect& b) {
return a.left < b.right && a.right > b.left &&
a.top < b.bottom && a.bottom > b.top;
}
- 别依赖
std::tuple或匿名结构体——读代码时容易看错字段顺序 - 如果矩形用
x、y、w、h表示,务必先转成left= x、right = x + w、top = y、bottom = y + h再判断;直接拿w/h做比较会出错 - 注意:
w和h必须为非负值;若可能为负(比如用户拖拽拉出反向矩形),先归一化:left = std::min(x, x+w); right = std::max(x, x+w);
浮点矩形相交要额外注意什么
用 float 或 double 表示坐标时,相等判断不可靠,但「分离」本身是安全的——因为只要有一个轴严格分离(比如 a.right ),就肯定不相交。
真正要小心的是「刚好贴边」的情况:数学上 a.right == b.left 应算不相交,但浮点计算可能因误差变成 a.right > b.left - eps,导致误判为相交。
- 如果业务要求「贴边不算碰撞」,保留原始比较即可(
和 <code>>已足够鲁棒) - 如果要求「贴边算碰撞」,可引入 epsilon:用
a.right + eps > b.left替代a.right > b.left,但需统一所有四次比较,且eps不能大于最小有效尺寸(比如像素级场景设1e-4f就过大) - 避免用
==判断边界重合——它既不稳定,也不符合碰撞语义
性能与内联注意事项
这个函数极轻量,现代编译器在 -O2 下基本都能自动内联。但如果你把它写成虚函数、通过指针调用、或放在模板参数里层层转发,就可能抑制优化。
- 确保函数定义在头文件中,或加
inline关键字(C++17 起constexpr函数默认内联) - 避免在循环体内反复构造临时
Rect对象——尤其是从std::vector中按索引取数据时,先解包再传参 - 如果批量检测(比如 1000 个矩形两两检测),O(n²) 复杂度下,这一步不是瓶颈;真正的瓶颈往往在内存访问模式——尽量让
Rect对象连续存储,别用指针数组打散
边界条件比想象中多:空矩形(left >= right 或 top >= bottom)、整数溢出(right 超过 INT_MAX)、坐标系混用——这些地方不报错,但结果不可控。










