两个矩形重叠当且仅当x1

判断两个矩形是否重叠的核心逻辑
在 C++ 中,两个轴对齐矩形(AABB)是否重叠,**不靠面积或中心距离,而靠“分离轴”思想**:只要在 x 或 y 轴上完全分离,就一定不重叠;只有两个方向都未分离,才算重叠。
假设矩形用左上角 (x1, y1) 和右下角 (x2, y2) 表示(常见于 OpenCV、Qt 等),且满足 x1 且 y1 :
- x 方向分离条件:
rectA.x2 - y 方向分离条件:
rectA.y2 - 因此重叠条件是:
!(x 分离 || y 分离)→ 即rectA.x1
用 std::pair 或结构体封装矩形时的写法
避免裸露四个 int 变量带来的可读性与维护问题。推荐定义结构体并重载判断函数:
struct Rect {
int x1, y1, x2, y2;
bool overlaps(const Rect& other) const {
return x1 < other.x2 && other.x1 < x2 &&
y1 < other.y2 && other.y1 < y2;
}
};注意:该实现**默认矩形坐标系 y 向下增长**(如屏幕坐标),若使用数学坐标系(y 向上),需把 y1/y2 含义对调或统一用 top/bottom 字段命名,否则逻辑会反转。
立即学习“C++免费学习笔记(深入)”;
常见坑点:
- 传入参数顺序错误导致
x1 >= x2,应在校验构造函数中 assert 或 normalize - 使用
判断边界接触是否算“重叠”——多数物理引擎/图形库将边接触视为不重叠(即开区间),若需包含接触,改用和>=配合,但务必全局统一
与 cv::Rect 或 QRect 的兼容写法
OpenCV 的 cv::Rect 默认构造为 cv::Rect(x, y, width, height),不是对角点。直接用其 & 操作符更安全:
cv::Rect r1(0, 0, 10, 10); cv::Rect r2(5, 5, 10, 10); cv::Rect intersection = r1 & r2; bool overlap = !intersection.empty(); // empty() 当交集面积为 0 时返回 true
Qt 的 QRect 同理,支持 intersects() 成员函数:
QRect r1(0, 0, 10, 10); QRect r2(5, 5, 10, 10); bool overlap = r1.intersects(r2); // 自动处理坐标归一化和空矩形
优势在于:它们内部已处理了 width/height 为负、空矩形、坐标溢出等边界情况;手写逻辑容易漏掉这些。
浮点矩形与精度问题
若用 float 或 double 表示坐标(如 OpenGL、自定义渲染器),直接比较 可能因浮点误差失效:
- 不要写
a.x2 来判断分离,而应写a.x2 + eps - eps 通常取
1e-6f(float)或1e-9(double),具体取决于坐标量级 - 更稳健的做法是用
std::abs(a.x2 - b.x1) 判断“几乎接触”,再结合业务决定是否视为重叠
例如:
bool overlaps(const RectF& a, const RectF& b, float eps = 1e-6f) {
return a.x1 < b.x2 + eps && b.x1 < a.x2 + eps &&
a.y1 < b.y2 + eps && b.y1 < a.y2 + eps;
}真正难的不是写对公式,而是确认你的坐标系定义、矩形构造方式、以及“边界接触是否算碰撞”这三点是否在所有模块中保持一致——不一致会导致偶发穿透或误触发,极难复现。










