两个轴对齐矩形重叠当且仅当在x轴和y轴上投影均重叠;即left1 < right2 && left2 < right1 && top1 < bottom2 && top2 < bottom1。

用分离轴定理快速判断矩形重叠
两个轴对齐矩形(AABB)是否重叠,最可靠且高效的方法是:**检查它们在 x 轴和 y 轴上是否都存在重叠区间**。只要任一轴不重叠,整体就不重叠——这是分离轴定理在 2D 轴对齐情况下的直接应用。
别去算交点、别转角度、别调用图形库的碰撞函数。C++ 原生比较就能搞定,时间复杂度 O(1),无分支预测风险。
- 假设矩形用
left、right、top、bottom表示(y 向下为正,常见于 GUI 或 SDL),则重叠条件是:left1 - 若用
x、y、width、height表示(y 向上为正,如 OpenGL 纹理坐标),先转成边界再判断:right = x + width,bottom = y - height(注意 y 方向符号) - 务必确保
left 且 <code>top ;若矩形可能被用户拖拽翻转(如框选),需先归一化:<code>std::minmax(left, right)
避免浮点精度导致的误判
当矩形坐标是 float 或 double 时,直接用 == 或 判断边界相等会出问题——比如两个矩形“刚好贴边”,理论上不重叠,但因计算误差可能被判定为重叠或不重叠。
- 关键不是加 epsilon,而是明确业务语义:**“贴边”算不算重叠?** 大多数场景(如 UI 布局、碰撞检测)应定义为「不重叠」,所以用严格不等式
和 <code>>即可 - 若需包含“接触即重叠”,改用
和 <code>>=,但必须同步保证所有矩形数据已做 round-to-nearest 或 floor/ceil 对齐(尤其来自像素坐标时) - 不要对
float边界做std::abs(a - b) 再判断相等——这会让逻辑变成三态(重叠 / 接触 / 分离),反而增加后续分支处理成本
用 std::pair 或结构体封装提升可读性
裸写四个变量名(l1, r1, t1, b1)极易传错顺序,也难维护。C++17 起推荐用命名结构体,而非 std::tuple 或 std::pair<:pair...></:pair...>。
立即学习“C++免费学习笔记(深入)”;
struct Rect {
float left, right, top, bottom;
bool overlaps(const Rect& other) const {
return left < other.right && other.left < right &&
top < other.bottom && other.top < bottom;
}
};
- 成员变量顺序固定为
left/right/top/bottom,和 CSS box model 一致,降低团队理解成本 - 把判断逻辑收进成员函数,避免外部重复写四组比较;若需支持不同坐标系(如 y 向上),可加模板参数或枚举标识
- 不建议用
std::array<float></float>—— 语义丢失,a[0]是什么?没人能一眼看懂
注意 SDL2 / Qt / OpenCV 等库的坐标约定差异
不同库对矩形的定义方式不同,直接套用同一套判断逻辑会出错。重点不是“哪个对”,而是“你当前用的 API 返回的是什么”。
- SDL2 的
SDL_Rect是{x, y, w, h},且 y 向下为正,所以top = y,bottom = y + h;别误以为y是 top - Qt 的
QRect默认 y 向上为正,但top()返回最小 y 值(即上边界),bottom()返回最大 y 值(即下边界)——它内部已帮你归一化,可直接用intersects(),但自己实现时仍要确认其top()是否真等于y - OpenCV 的
cv::Rect是{x, y, width, height},y 向下为正,y是 top,y + height是 bottom;但注意其area()为正,说明 width/height 恒 ≥ 0
最稳妥的做法:拿到矩形数据后,立刻转成你统一的 Rect 结构体,再调用 overlaps()。中间多一次赋值,远比后期 debug 坐标翻转问题省时间。


















