1. 概述

在本篇文章中,我们将探讨一个经典的算法问题:如何判断两个给定的矩形是否重叠。这个问题在图形处理、碰撞检测等场景中非常常见。

我们会从问题定义出发,逐步推导解决方案,并最终用 Java 实现。

2. 问题定义

假设我们有两个矩形 r1r2,我们需要判断它们之间是否存在至少一个公共点。如果存在,则说明这两个矩形发生了重叠。

来看几个示例图:

OverlappingRectangles

注意最后一个例子,虽然 r1r2 的边界没有交集,但由于 r1 完全包含在 r2 内部,因此仍属于“重叠”情况。

3. 初始结构设计

为了解决这个问题,我们首先需要定义一个矩形类。一个矩形可以由其左下角和右上角坐标唯一确定

public class Rectangle {
    private Point bottomLeft;
    private Point topRight;

    // 构造函数、getter/setter 省略

    boolean isOverlapping(Rectangle other) {
        ...
    }
}

其中 Point 是表示二维坐标点的类:

public class Point {
    private int x;
    private int y;

    // 构造函数、getter/setter 省略
}

接下来我们会在 Rectangle 类中实现 .isOverlapping() 方法来判断当前矩形是否与另一个矩形重叠。

4. 解题思路

两个矩形不重叠的情况只有两种:

  1. 其中一个矩形完全位于另一个矩形的上方(即 y 轴方向无交集)
  2. 其中一个矩形完全位于另一个矩形的左侧(即 x 轴方向无交集)

如下图所示:

NonOverlappingRectangles1

❌ 如果以上两个条件都不满足,则说明两个矩形必然有交集,即发生重叠。

我们可以手动画几个图验证这个逻辑。

5. Java 实现

基于上述分析,我们可以写出如下代码:

public boolean isOverlapping(Rectangle comparedRectangle) {
    if (this.topRight.getY() < comparedRectangle.bottomLeft.getY() || 
        this.bottomLeft.getY() > comparedRectangle.topRight.getY()) {
        return false;
    }

    if (this.topRight.getX() < comparedRectangle.bottomLeft.getX() || 
        this.bottomLeft.getX() > comparedRectangle.topRight.getX()) {
        return false;
    }

    return true;
}

该方法会返回 false 如果其中一个矩形完全在另一个的上方或左侧,否则返回 true 表示重叠。

  • 通过比较 y 坐标判断是否上下分离
  • 通过比较 x 坐标判断是否左右分离

5.1. 不考虑边界的判断方式

在实际使用中,我们可能需要区分“边界是否算作重叠”。默认情况下,我们的 .isOverlapping() 方法是把矩形当作闭区间处理的,也就是说,只要边界接触就算重叠。

如果我们想忽略边界(即视为开区间),可以使用下面这个版本:

public boolean isOverlappingWithoutBorders(Rectangle comparedRectangle) {
    if (this.topRight.getY() <= comparedRectangle.bottomLeft.getY() || 
        this.bottomLeft.getY() >= comparedRectangle.topRight.getY()) {
        return false;
    }

    if (this.topRight.getX() <= comparedRectangle.bottomLeft.getX() || 
        this.bottomLeft.getX() >= comparedRectangle.topRight.getX()) {
        return false;
    }

    return true;
}

测试代码如下:

Rectangle rectangle1 = new Rectangle(new Point(0, 0), new Point(5, 14));
Rectangle rectangle2 = new Rectangle(new Point(5, 0), new Point(17, 14));

assertTrue(rectangle1.isOverlapping(rectangle2));                    // true: 边界接触视为重叠
assertFalse(rectangle1.isOverlappingWithoutBorders(rectangle2));     // false: 忽略边界则不重叠

两种方式都符合预期行为。

6. 总结

这篇文章介绍了如何通过坐标比较的方式判断两个矩形是否重叠,分别支持包含边界和不包含边界两种模式。这类算法在游戏开发、UI 布局、图形学等领域经常作为碰撞检测的基础策略使用。

完整源码可以在 GitHub 仓库 中找到。


原始标题:Check if Two Rectangles Overlap in Java