AABB重叠判断的正确逻辑是:两个矩形在x轴和y轴上的投影必须同时重叠才相交,任一轴无交集即分离;核心是分离轴定理的简化应用,通过比较min/max边界(如a.min.x < b.max.x && b.min.x < a.max.x)高效判定,支持边界接触且避免中心法等易错方式。

什么是AABB重叠判断的正确逻辑
AABB(Axis-Aligned Bounding Box)重叠判断本质是:两个矩形都与坐标轴对齐时,**只要在x轴和y轴上各自投影有交集,就一定重叠**;反之,只要任一轴上投影无交集,就一定不重叠。这是最高效、最可靠的判断方式,不需要求交点或面积。
常见错误是写成“四边全在对方内部”或“中心距离小于半宽半高”,这两种逻辑在矩形相切或一角刚好接触时会误判——AABB重叠定义包含边界接触(即 min1 这种闭区间交集)。
C++中用std::max和std::min实现简洁判断
假设每个矩形用左上角 (x, y) 和宽高 w、h 表示(y轴向下),那么右下角为 (x + w, y + h)。判断逻辑直接套用区间交集公式:
bool intersects(const Rect& a, const Rect& b) {
return std::max(a.x, b.x) <= std::min(a.x + a.w, b.x + b.w) &&
std::max(a.y, b.y) <= std::min(a.y + a.h, b.y + b.h);
}
-
std::max(a.x, b.x)是两矩形x方向左边界的最大值(即交集左界) -
std::min(a.x + a.w, b.x + b.w)是两矩形x方向右边界最小值(即交集右界) - 当左界 ≤ 右界时,x方向有交集;y方向同理
- 两个方向都有交集,才返回
true
坐标系方向不同会导致y轴比较逻辑翻转
如果y轴向上(如OpenGL或数学常用坐标系),矩形通常用 bottom 和 height 定义,此时y方向的“上边界”是 y + h,但“下边界”是 y,和y向下时一样——所以只要统一用“最小y”和“最大y”参与比较,逻辑不变。
立即学习“C++免费学习笔记(深入)”;
更稳妥的做法是显式提取边界:
float a_min_x = a.x;
float a_max_x = a.x + a.w;
float a_min_y = std::min(a.y, a.y + a.h); // 确保是下边界
float a_max_y = std::max(a.y, a.y + a.h); // 确保是上边界
// 同理处理b...
return std::max(a_min_x, b_min_x) <= std::min(a_max_x, b_max_x) &&
std::max(a_min_y, b_min_y) <= std::min(a_max_y, b_max_y);
- 避免依赖隐含坐标方向假设
- 若矩形结构体已封装
left、right、top、bottom字段,直接用它们更安全 - 注意浮点数比较:若涉及浮点坐标,建议加
EPS容差,但AABB通常用整数或定点坐标,==和足够可靠
容易被忽略的边界情况:零宽/零高矩形和NaN输入
标准AABB重叠定义中,宽或高为0的矩形视为一条线段或一个点,仍可参与判断。但若代码中未做预处理,a.w == 0 会导致 a.x + a.w == a.x,此时x方向交集条件退化为 std::max(a.x, b.x) ,逻辑依然成立。
- 真正要检查的是:输入是否为
NaN或无穷大——这会让std::max/std::min返回未定义结果 - 如果业务允许退化矩形,无需额外过滤;否则应在调用前断言
a.w >= 0 && a.h >= 0 - 不要用面积是否大于0来代替重叠判断:面积为0的矩形仍可能与其他矩形“接触”,而AABB重叠包含接触
实际项目里,这个判断常被内联、去分支化(比如用 std::clamp 或位运算),但对绝大多数场景,上面的双条件 && 写法足够清晰且无性能隐患。


















