我有多个矩形和一个特殊矩形:选择矩形。我想检查每个矩形是否包含至少一个位于选择矩形内的点。为了清楚起见,这是一张图片:
10 回答
背景:
一个矩形可以仅由其对角线之一定义。
假设第一个矩形的对角线是 (x1, y1) 到 (x2, y2)
而另一个矩形的对角线是 (x3, y3) 到 (x4, y4)
进行中:
现在,如果这 4 个条件中的任何一个为真,我们可以得出结论,矩形不重叠:
- x3 > x2(或)
- y3 > y2 (或)
- x1 > x4(或)
- 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.intersects
andRectangle.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
并且第二个是 a Rectangle2D
,您可以简单地使用RectangularShape.intersects
:
selectionRectangle.intersects(otherRectangle)
测试 Shape 的内部是否与指定的 Rectangle2D 的内部相交
我对 gps 坐标系中的多边形有一个通用的实现,这对于矩形(这是简单的多边形)来说可能有点矫枉过正;但它会起作用。如果出于某种原因您不想使用 AWT,那么将方法调整到您的用例应该是相当简单的。
我在那里做的只是检查多边形是否有其他多边形包含的任何点。
对于点的多边形包含,我有一个简单的算法,它遍历多边形的边缘以检查该点是在 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 时,黑色与蓝色重叠。
编辑:使用 <= 和 >= 进行重叠比较。