在几何计算与碰撞检测场景中,经常需要求出两个轴对齐矩形的并集面积,并且把交集部分和各自独立部分的面积分开输出。轴对齐矩形指边分别与坐标轴平行的矩形,用左上角和右下角坐标即可完整描述。实现该计算的核心在于正确识别两矩形是否相交,以及相交时如何推导重叠区域。

矩形数据结构与坐标定义
我们用一个简单的类来描述矩形,包含 x1、y1(左下角)和 x2、y2(右上角)。为了降低后续计算复杂度,可以在构造时自动将坐标规范化为左下角小于右上角的形式,避免调用者传参顺序错误导致面积变负。
坐标规范化后,矩形面积计算公式为 (x2 - x1) * (y2 - y1)。如果两个矩形相离或边相切,交集面积为 0;如果部分重叠或完全包含,则交集是一个新的轴对齐矩形。下面先给出矩形类的定义。
class Rect {
int x1, y1, x2, y2;
Rect(int x1, int y1, int x2, int y2) {
// 自动规范化,保证 x1<=x2, y1<=y2
this.x1 = Math.min(x1, x2);
this.y1 = Math.min(y1, y2);
this.x2 = Math.max(x1, x2);
this.y2 = Math.max(y1, y2);
}
int area() {
return (x2 - x1) * (y2 - y1);
}
}
相交判断与交集矩形计算
两个轴对齐矩形相交的充要条件是:在 x 轴方向投影重叠,且在 y 轴方向投影重叠。具体写为 x1_2 <= x2_1 且 x1_1 <= x2_2,y 方向同理。若任一方向不重叠,则两矩形相离或相切,交集为空。
当确认相交后,交集矩形的左下角取两矩形左下角坐标的较大值,右上角取两矩形右上角坐标的较小值。该交集矩形面积即为重叠部分面积。如果一方完全包含另一方,交集矩形就等于被包含的矩形。
static Rect intersect(Rect a, Rect b) {
// 不相交则返回空矩形(面积为0)
if (a.x1 > b.x2 || b.x1 > a.x2 || a.y1 > b.y2 || b.y1 > a.y2) {
return null;
}
int ix1 = Math.max(a.x1, b.x1);
int iy1 = Math.max(a.y1, b.y1);
int ix2 = Math.min(a.x2, b.x2);
int iy2 = Math.min(a.y2, b.y2);
return new Rect(ix1, iy1, ix2, iy2);
}
并集与分离面积输出
并集面积等于 a.area() + b.area() - inter.area()。独立区域面积指去掉交集后各自剩余部分:aOnly = a.area() - inter.area(),bOnly = b.area() - inter.area()。当不相交时,交集为 null,inter.area() 视为 0,此时 aOnly 与 bOnly 就等于各自面积。
下面的方法接收两个矩形,打印并集、交集及独立区域面积。这种分离输出在游戏碰撞响应中很有用,比如计算伤害区域时可区分公共重叠区和单体额外区域。
static void printAreas(Rect a, Rect b) {
Rect inter = intersect(a, b);
int interArea = (inter == null) ? 0 : inter.area();
int unionArea = a.area() + b.area() - interArea;
int aOnly = a.area() - interArea;
int bOnly = b.area() - interArea;
System.out.println("矩形A面积: " + a.area());
System.out.println("矩形B面积: " + b.area());
System.out.println("交集面积: " + interArea);
System.out.println("A独立面积: " + aOnly);
System.out.println("B独立面积: " + bOnly);
System.out.println("并集面积: " + unionArea);
}
完整示例与测试
我们构造三组测试用例:部分重叠、完全包含、相离。通过 main 方法调用 printAreas 观察输出是否符合预期。部分重叠时并集应小于两面积和;包含时交集等于小矩形;相离时交集为 0。
该实现时间复杂度为 O(1),仅做常数次算术与比较,空间复杂度也为 O(1)。可轻松改写为接收 double 坐标以支持浮点精度,或扩展为多个矩形并集的扫描线算法基础。
public class Main {
public static void main(String[] args) {
Rect a = new Rect(0, 0, 4, 4);
Rect b = new Rect(2, 2, 6, 6);
System.out.println("--- 部分重叠 ---");
printAreas(a, b);
Rect c = new Rect(0, 0, 10, 10);
Rect d = new Rect(1, 1, 3, 3);
System.out.println("--- 完全包含 ---");
printAreas(c, d);
Rect e = new Rect(0, 0, 2, 2);
Rect f = new Rect(3, 3, 5, 5);
System.out.println("--- 相离 ---");
printAreas(e, f);
}
// 这里粘贴前面定义的 Rect 类、intersect 和 printAreas 方法
}
常见误区与注意点
一个常见错误是直接用 (a.x2 - b.x1) * (a.y2 - b.y1) 之类公式算交集,未先判断相离情况,导致得到负数面积。必须先用投影重叠判定,再取最大最小坐标。
另一个误区是认为并集面积等于两矩形面积和。只有在互斥时成立,一旦有重叠就必须减去交集,否则统计结果偏大。分离输出能帮开发者在日志中快速发现重叠量,便于调试碰撞盒配置。