繁体   English   中英

Java 检查两个矩形是否在任何一点重叠

[英]Java check if two rectangles overlap at any point

我有多个矩形和一个特殊矩形:选择矩形。 我想检查每个矩形是否包含至少一个位于选择矩形内的点。 为了清楚起见,这是一张图片:

选择示例

背景:

矩形可以仅由其对角线之一定义。
假设第一个矩形的对角线是 (x1, y1) 到 (x2, y2)
另一个矩形的对角线是 (x3, y3) 到 (x4, y4)

样本

进行:

现在,如果这 4 个条件中的任何一个为真,我们可以得出结论,矩形没有重叠:

  1. x3 > x2 (或)
  2. y3 > y2 (或)
  3. x1 > x4 (或)
  4. y1 > y4


否则,它们会重叠!

在此处输入图片说明

或者:

如果矩形重叠

(x1 < x4) && (x3 < x2) && (y1 < y4) && (y3 < y2)



Leetcode 上的示例解决方案: https ://leetcode.com/problems/rectangle-overlap/discuss/468548/Java-check-if-two-rectangles-overlap-at-any-point

这将发现矩形是否与另一个矩形重叠:

public boolean overlaps (Rectangle r) {
    return x < r.x + r.width && x + width > r.x && y < r.y + r.height && y + height > r.y;
}

我会创建Rectangle 对象,然后使用Rectangle.intersectsRectangle.contains方法来确定它们是否相交或是否包含另一个。

既然你有一个大矩形,那就是选择矩形,这比我想象的要容易。 运行 Rectangle.contains,对于所有未包含的矩形,运行 Rectangle.intersects,你就会得到你想要的东西。

这是另一个更简单的解决方案:

    // Left x 
    int leftX = Math.max(x1, x3);
    // Right x
    int rightX = Math.min(x2, x4);
    // Bottom y
    int botY = Math.max(y1, y3);
    // TopY
    int topY = Math.min(y2, y4);

    if (rightX > leftX && topY > botY)
       return true;

如果第一个实现RectangularShape而第二个是Rectangle2D ,则可以简单地使用RectangularShape.intersects

selectionRectangle.intersects(otherRectangle)

测试 Shape 的内部是否与指定的 Rectangle2D 的内部相交

来自Oracle Java 文档

我有一个 gps 坐标系中多边形的通用实现,这对于矩形(它们是简单的多边形)来说可能有点矫枉过正; 但它会起作用。 如果出于某种原因您不想使用 AWT,那么将方法调整到您的用例应该是相当简单的。

https://github.com/jilesvangurp/geogeometry/blob/master/src/main/java/com/jilesvangurp/geo/GeoGeometry.java#L753 (重叠法)

我在那里做的只是检查多边形是否有其他多边形包含的任何点。

对于点的多边形包含,我有一个简单的算法,可以遍历多边形的边缘以检查点是在 O(n) 内部还是外部。 对于矩形,运行起来应该很便宜。

这种方法的好处是它适用于任何矩形,也适用于旋转的矩形或更复杂的形状。

如果满足以下条件之一,则两个矩形不会重叠。
1) 一个矩形位于另一个矩形的上边缘之上。
2) 一个矩形位于另一个矩形左边缘的左侧。

请注意,矩形可以用两个坐标表示,左上角和右下角。 所以主要给我们以下四个坐标。
l1:第一个矩形的左上角坐标。
r1:第一个矩形的右下坐标。
l2:第二个矩形的左上角坐标。
r2:第二个矩形的右下坐标。

class Point
{
    int x, y;
};

// Returns true if two rectangles (l1, r1) and (l2, r2) overlap
bool doOverlap(Point l1, Point r1, Point l2, Point r2)
{
    // If one rectangle is on left side of other
    if (l1.x > r2.x || l2.x > r1.x)
        return false;

    // If one rectangle is above other
    if (l1.y < r2.y || l2.y < r1.y)
        return false;

    return true;
}

此类假设顺序为left<=right , top<=bottom , x1<=x2 , y1<=y2

public class Rect
{
int left, right, bottom, top;

Rect(int left, int top, int right, int bottom)
{
    this.left = left;
    this.right = right;
    this.top = top;
    this.bottom = bottom;
}

boolean overlap(int x1, int y1, int x2, int y2)
{
    // if one rectangle is to the left or right, then there can be no overlap
    if(x2 < left || right < x1)
        return false;

    // the x values overlap, but the y values may still lie outside the rectangle

    // if one rectangle is above or below, then there can be no overlap
    if(y2 < top || bottom < y1)
        return false;

    // otherwise we must overlap !
    return true;        
}
}

java.awt.Rectangle有一个内置的intersects方法。

import java.awt.Rectangle;
// ...
Rectangle r1 = new Rectangle(
    0 /* top left x */, 0 /* top left y */, 
    5 /* width */, 7 /* height */
);
Rectangle r2 = new Rectangle(4, 5, 3, 3);
System.out.println(r1.intersects(r2)); // true

编辑如已接受的答案中所述,AWT Rectangle 对象通过intersects方法提供此功能。 如果您不想使用 AWT 或出于其他原因,下面是一个变体解决方案。

如果你想重新发明轮子,那么这里有一些东西。 使用您的示例图像,这将测试黑色矩形与蓝色矩形的重叠。 此外,这假设触摸不重叠。

每个矩形将由两个坐标对表示:topLeft 和 bottomRight。

这假设 0, 0 在左上角。

Function xOverlapCheck(black, blue)
{
    // black left side overlaps.
    if ((black.topLeft.x <= blue.bottomRight.x) &&
        (black.topLeft.x >= blue.topLeft.x))
    {
        return true;
    }

    // black right side overlaps.
    if ((black.bottomRight.x <= blue.bottomRight.x) &&
        (black.bottomRight.x >= blue.topLeft.x))
    {
        return true;
    }

    // black fully contains blue.
    if ((black.bottomRight.x >= blue.bottomRight.x) &&
        (black.topLeft.x <= blue.topLeft.x))
    {
        return true;
    }
}


Function yOverlapCheck(black, blue)
{
    // black top side overlaps.
    if ((black.topLeft.y >= blue.topLeft.y) &&
        (black.topLeft.y <= blue.bottomRight.y))
    {
        return true;
    }

    // black bottom side overlaps.
    if ((black.bottomRight.y >= blue.topLeft.y) &&
        (black.bottomRight.y <= blue.bottomRight.y))
    {
        return true;
    }

    // black fully contains blue.
    if ((black.bottomRight.y >= blue.bottomRight.y) &&
        (black.topLeft.y <= blue.topLeft.y))
    {
        return true;
    }
}

当两个函数都返回 true 时,黑色与蓝色重叠。

编辑:使用 <= 和 >= 进行重叠比较。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM