我正在尝试编写一个C ++程序,它从用户那里获取以下输入来构造矩形(2到5之间):高度,宽度,x-pos,y-pos。所有这些矩形都将平行于x和y轴存在,即它们的所有边都将具有0或无穷大的斜率。
我试图实现this问题中提到的内容,但我运气不好。
我目前的实施方案如下:
// Gets all the vertices for Rectangle 1 and stores them in an array -> arrRect1
// point 1 x: arrRect1[0], point 1 y: arrRect1[1] and so on...
// Gets all the vertices for Rectangle 2 and stores them in an array -> arrRect2
// rotated edge of point a, rect 1
int rot_x, rot_y;
rot_x = -arrRect1[3];
rot_y = arrRect1[2];
// point on rotated edge
int pnt_x, pnt_y;
pnt_x = arrRect1[2];
pnt_y = arrRect1[3];
// test point, a from rect 2
int tst_x, tst_y;
tst_x = arrRect2[0];
tst_y = arrRect2[1];
int value;
value = (rot_x * (tst_x - pnt_x)) + (rot_y * (tst_y - pnt_y));
cout << "Value: " << value;
但是我不确定(a)我是否已经实现了我正确链接的算法,或者我是否确切地解释了这个?
有什么建议吗?
答案 0 :(得分:659)
if (RectA.Left < RectB.Right && RectA.Right > RectB.Left &&
RectA.Top > RectB.Bottom && RectA.Bottom < RectB.Top )
或使用笛卡尔坐标
(X1为左坐标,X2为右坐标,从左到右增加,Y1为顶部坐标,Y2为底部坐标,从下到上增加)......
if (RectA.X1 < RectB.X2 && RectA.X2 > RectB.X1 &&
RectA.Y1 > RectB.Y2 && RectA.Y2 < RectB.Y1)
注意:对于所有具有编辑权限的用户。请停止使用此信息。
假设您有Rect A和Rect B. 证据是矛盾的。四个条件中的任何一个都保证不存在重叠:
非重叠的条件是
Cond1 Or Cond2 Or Cond3 Or Cond4
因此,重叠的充分条件恰恰相反。
Not (Cond1 Or Cond2 Or Cond3 Or Cond4)德摩根定律说
Not (A or B or C or D)
与Not A And Not B And Not C And Not D
相同
所以使用De Morgan,我们有
Not Cond1 And Not Cond2 And Not Cond3 And Not Cond4
这相当于:
RectA.Left < RectB.Right
]和RectA.Right > RectB.Left
]和RectA.Top > RectB.Bottom
]和RectA.Bottom < RectB.Top
] 注1 :很明显,同样的原则可以扩展到任意数量的维度。
注意2 :计算一个像素的重叠也应该相当明显,将该边界上的<
和/或>
更改为<=
或>=
注3 :当使用笛卡尔坐标(X,Y)时,这个答案基于标准代数笛卡尔坐标(x从左到右增加,Y从下到上增加)。显然,计算机系统可能会以不同方式机械化屏幕坐标(例如,从上到下增加Y,或从右到左增加X),语法将需要相应调整/
答案 1 :(得分:111)
struct rect
{
int x;
int y;
int width;
int height;
};
bool valueInRange(int value, int min, int max)
{ return (value >= min) && (value <= max); }
bool rectOverlap(rect A, rect B)
{
bool xOverlap = valueInRange(A.x, B.x, B.x + B.width) ||
valueInRange(B.x, A.x, A.x + A.width);
bool yOverlap = valueInRange(A.y, B.y, B.y + B.height) ||
valueInRange(B.y, A.y, A.y + A.height);
return xOverlap && yOverlap;
}
答案 2 :(得分:26)
struct Rect
{
Rect(int x1, int x2, int y1, int y2)
: x1(x1), x2(x2), y1(y1), y2(y2)
{
assert(x1 < x2);
assert(y1 < y2);
}
int x1, x2, y1, y2;
};
bool
overlap(const Rect &r1, const Rect &r2)
{
// The rectangles don't overlap if
// one rectangle's minimum in some dimension
// is greater than the other's maximum in
// that dimension.
bool noOverlap = r1.x1 > r2.x2 ||
r2.x1 > r1.x2 ||
r1.y1 > r2.y2 ||
r2.y1 > r1.y2;
return !noOverlap;
}
答案 3 :(得分:21)
更容易检查矩形是否完全在另一个之外,所以如果它是
左边的......
(r1.x + r1.width < r2.x)
或在右边...
(r1.x > r2.x + r2.width)
或顶部...
(r1.y + r1.height < r2.y)
或在底部...
(r1.y > r2.y + r2.height)
第二个矩形的,它不可能与它碰撞。因此,要有一个函数返回一个布尔说明天气与矩形相撞,我们只需通过逻辑OR组合条件并否定结果:
function checkOverlap(r1, r2) : Boolean
{
return !(r1.x + r1.width < r2.x || r1.y + r1.height < r2.y || r1.x > r2.x + r2.width || r1.y > r2.y + r2.height);
}
仅在触摸时已收到肯定结果,我们可以更改“&lt;”和“&gt;”通过“&lt; =”和“&gt; =”。
答案 4 :(得分:6)
问自己相反的问题:我怎样才能确定两个矩形是否完全不相交?显然,矩形B左侧的矩形A不相交。如果A完全在右边。同样,如果A完全高于B或完全低于B.在任何其他情况下,A和B相交。
以下内容可能存在错误,但我对该算法非常有信心:
struct Rectangle { int x; int y; int width; int height; };
bool is_left_of(Rectangle const & a, Rectangle const & b) {
if (a.x + a.width <= b.x) return true;
return false;
}
bool is_right_of(Rectangle const & a, Rectangle const & b) {
return is_left_of(b, a);
}
bool not_intersect( Rectangle const & a, Rectangle const & b) {
if (is_left_of(a, b)) return true;
if (is_right_of(a, b)) return true;
// Do the same for top/bottom...
}
bool intersect(Rectangle const & a, Rectangle const & b) {
return !not_intersect(a, b);
}
答案 5 :(得分:6)
假设您已经定义了矩形的位置和大小,如下所示:
我的C ++实现是这样的:
class Vector2D
{
public:
Vector2D(int x, int y) : x(x), y(y) {}
~Vector2D(){}
int x, y;
};
bool DoRectanglesOverlap( const Vector2D & Pos1,
const Vector2D & Size1,
const Vector2D & Pos2,
const Vector2D & Size2)
{
if ((Pos1.x < Pos2.x + Size2.x) &&
(Pos1.y < Pos2.y + Size2.y) &&
(Pos2.x < Pos1.x + Size1.x) &&
(Pos2.y < Pos1.y + Size1.y))
{
return true;
}
return false;
}
根据上图给出的示例函数调用:
DoRectanglesOverlap(Vector2D(3, 7),
Vector2D(8, 5),
Vector2D(6, 4),
Vector2D(9, 4));
if
块内的比较如下所示:
if ((Pos1.x < Pos2.x + Size2.x) &&
(Pos1.y < Pos2.y + Size2.y) &&
(Pos2.x < Pos1.x + Size1.x) &&
(Pos2.y < Pos1.y + Size1.y))
↓
if (( 3 < 6 + 9 ) &&
( 7 < 4 + 4 ) &&
( 6 < 3 + 8 ) &&
( 4 < 7 + 5 ))
答案 6 :(得分:3)
这是使用C ++检查两个矩形是否重叠的非常快速的方法:
return std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right)
&& std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom);
它的工作原理是计算相交矩形的左右边界,然后进行比较:如果右边界等于或小于左边界,则表示相交为空,因此矩形不重叠;否则,它将使用顶部和底部边框再次尝试。
与传统的4种比较方法相比,此方法的优势是什么?关于现代处理器的设计方式。它们具有称为分支预测的功能,当比较结果始终相同时效果很好,但否则会造成巨大的性能损失。但是,在没有分支指令的情况下,CPU的性能很好。通过计算相交的边界,而不是对每个轴进行两次单独的检查,我们节省了两个分支,每对一个。
如果第一个比较很有可能是假的,那么这四个比较方法可能会胜过这个方法。但是,这非常罕见,因为这意味着第二个矩形通常位于第一个矩形的左侧,而不是在右侧或与其重叠;通常,您需要检查第一个矩形的两边的矩形,这通常会使分支预测的优势失效。
根据矩形的预期分布,可以进一步改进此方法:
return std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom)
&& std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right);
return std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right)
& std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom);
(请注意,将&&
更改为单个&
)
答案 7 :(得分:3)
以下是在Java API中的完成方式:
public boolean intersects(Rectangle r) {
int tw = this.width;
int th = this.height;
int rw = r.width;
int rh = r.height;
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
return false;
}
int tx = this.x;
int ty = this.y;
int rx = r.x;
int ry = r.y;
rw += rx;
rh += ry;
tw += tx;
th += ty;
// overflow || intersect
return ((rw < rx || rw > tx) &&
(rh < ry || rh > ty) &&
(tw < tx || tw > rx) &&
(th < ty || th > ry));
}
答案 8 :(得分:2)
struct Rect
{
Rect(int x1, int x2, int y1, int y2)
: x1(x1), x2(x2), y1(y1), y2(y2)
{
assert(x1 < x2);
assert(y1 < y2);
}
int x1, x2, y1, y2;
};
//some area of the r1 overlaps r2
bool overlap(const Rect &r1, const Rect &r2)
{
return r1.x1 < r2.x2 && r2.x1 < r1.x2 &&
r1.y1 < r2.y2 && r2.x1 < r1.y2;
}
//either the rectangles overlap or the edges touch
bool touch(const Rect &r1, const Rect &r2)
{
return r1.x1 <= r2.x2 && r2.x1 <= r1.x2 &&
r1.y1 <= r2.y2 && r2.x1 <= r1.y2;
}
答案 9 :(得分:2)
在问题中,您链接到矩形处于任意旋转角度时的数学。但是,如果我理解问题中的角度,我会解释所有矩形彼此垂直。
知道重叠公式的区域是一般的:
使用示例:
1 2 3 4 5 6 1 +---+---+ | | 2 + A +---+---+ | | B | 3 + + +---+---+ | | | | | 4 +---+---+---+---+ + | | 5 + C + | | 6 +---+---+
1)将所有x坐标(左右)收集到一个列表中,然后对其进行排序并删除重复项
1 3 4 5 6
2)将所有y坐标(顶部和底部)收集到一个列表中,然后对其进行排序并删除重复项
1 2 3 4 6
3)通过唯一x坐标之间的间隙数创建一个二维数组*唯一y坐标之间的间隙数。
4 * 4
4)将所有矩形绘制到此网格中,增加其出现的每个单元格的数量:
1 3 4 5 6 1 +---+ | 1 | 0 0 0 2 +---+---+---+ | 1 | 1 | 1 | 0 3 +---+---+---+---+ | 1 | 1 | 2 | 1 | 4 +---+---+---+---+ 0 0 | 1 | 1 | 6 +---+---+
5)当您绘制矩形时,它很容易拦截重叠。
答案 10 :(得分:1)
不要将坐标视为指示像素的位置。把它们想象成像素之间。这样,2x2矩形的面积应为4,而不是9。
bool bOverlap = !((A.Left >= B.Right || B.Left >= A.Right)
&& (A.Bottom >= B.Top || B.Bottom >= A.Top));
答案 11 :(得分:1)
假设两个矩形是矩形A和矩形B.让中心为A1和B1(A1和B1的坐标很容易找到),高度为Ha和Hb,宽度为Wa和Wb,让dx是A1和B1之间的宽度(x)距离,dy是A1和B1之间的高度(y)距离。
现在我们可以说我们可以说A和B重叠:当时
if(!(dx > Wa+Wb)||!(dy > Ha+Hb)) returns true
答案 12 :(得分:1)
最简单的方法是
/**
* Check if two rectangles collide
* x_1, y_1, width_1, and height_1 define the boundaries of the first rectangle
* x_2, y_2, width_2, and height_2 define the boundaries of the second rectangle
*/
boolean rectangle_collision(float x_1, float y_1, float width_1, float height_1, float x_2, float y_2, float width_2, float height_2)
{
return !(x_1 > x_2+width_2 || x_1+width_1 < x_2 || y_1 > y_2+height_2 || y_1+height_1 < y_2);
}
首先要记住,在计算机中,坐标系统是颠倒的。 x轴与数学相同,但y轴向下增加,向上减小。 如果从中心绘制矩形。 如果x1坐标大于x2加上它的一半widht。那意味着他们会相互接触一半。并以相同的方式向下+高度的一半。它会碰撞..
答案 13 :(得分:0)
我有一个非常简单的解决方案
让x1,y1 x2,y2,l1,b1,l2分别成为坐标,长度和广度
考虑条件((x2
现在这些矩形重叠的唯一方法是,如果x1,y1的对角点位于另一个矩形内,或者类似于x2的点对角线,y2将位于另一个矩形内。这正是上述条件所暗示的。
答案 14 :(得分:0)
A和B是两个矩形。 C是它们的覆盖矩形。
four points of A be (xAleft,yAtop),(xAleft,yAbottom),(xAright,yAtop),(xAright,yAbottom)
four points of A be (xBleft,yBtop),(xBleft,yBbottom),(xBright,yBtop),(xBright,yBbottom)
A.width = abs(xAleft-xAright);
A.height = abs(yAleft-yAright);
B.width = abs(xBleft-xBright);
B.height = abs(yBleft-yBright);
C.width = max(xAleft,xAright,xBleft,xBright)-min(xAleft,xAright,xBleft,xBright);
C.height = max(yAtop,yAbottom,yBtop,yBbottom)-min(yAtop,yAbottom,yBtop,yBbottom);
A and B does not overlap if
(C.width >= A.width + B.width )
OR
(C.height >= A.height + B.height)
它会照顾所有可能的情况。
答案 15 :(得分:0)
这是来自Java编程简介 - 综合版的练习3.28。代码测试两个矩形是否为indenticle,一个是否在另一个内部以及一个是否在另一个之外。如果这些条件都不满足则两者重叠。
** 3.28(几何:两个矩形)编写一个程序,提示用户输入 中心x-,y-坐标,宽度和两个矩形的高度并确定 第二个矩形是在第一个矩形内部还是与第一个矩形重叠,如图所示 在图3.9中。测试您的程序以涵盖所有情况。 以下是样本运行:
输入r1的中心x-,y坐标,宽度和高度:2.5 4 2.5 43 输入r2的中心x-,y坐标,宽度和高度:1.5 5 0.5 3 r2在r1里面
输入r1的中心x-,y坐标,宽度和高度:1 2 3 5.5 输入r2的中心x-,y坐标,宽度和高度:3 4 4.5 5 r2重叠r1
输入r1的中心x-,y坐标,宽度和高度:1 2 3 3 输入r2的中心x-,y坐标,宽度和高度:40 45 3 2 r2与r1不重叠
import java.util.Scanner;
public class ProgrammingEx3_28 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out
.print("Enter r1's center x-, y-coordinates, width, and height:");
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double w1 = input.nextDouble();
double h1 = input.nextDouble();
w1 = w1 / 2;
h1 = h1 / 2;
System.out
.print("Enter r2's center x-, y-coordinates, width, and height:");
double x2 = input.nextDouble();
double y2 = input.nextDouble();
double w2 = input.nextDouble();
double h2 = input.nextDouble();
w2 = w2 / 2;
h2 = h2 / 2;
// Calculating range of r1 and r2
double x1max = x1 + w1;
double y1max = y1 + h1;
double x1min = x1 - w1;
double y1min = y1 - h1;
double x2max = x2 + w2;
double y2max = y2 + h2;
double x2min = x2 - w2;
double y2min = y2 - h2;
if (x1max == x2max && x1min == x2min && y1max == y2max
&& y1min == y2min) {
// Check if the two are identicle
System.out.print("r1 and r2 are indentical");
} else if (x1max <= x2max && x1min >= x2min && y1max <= y2max
&& y1min >= y2min) {
// Check if r1 is in r2
System.out.print("r1 is inside r2");
} else if (x2max <= x1max && x2min >= x1min && y2max <= y1max
&& y2min >= y1min) {
// Check if r2 is in r1
System.out.print("r2 is inside r1");
} else if (x1max < x2min || x1min > x2max || y1max < y2min
|| y2min > y1max) {
// Check if the two overlap
System.out.print("r2 does not overlaps r1");
} else {
System.out.print("r2 overlaps r1");
}
}
}
答案 16 :(得分:0)
bool Square::IsOverlappig(Square &other)
{
bool result1 = other.x >= x && other.y >= y && other.x <= (x + width) && other.y <= (y + height); // other's top left falls within this area
bool result2 = other.x >= x && other.y <= y && other.x <= (x + width) && (other.y + other.height) <= (y + height); // other's bottom left falls within this area
bool result3 = other.x <= x && other.y >= y && (other.x + other.width) <= (x + width) && other.y <= (y + height); // other's top right falls within this area
bool result4 = other.x <= x && other.y <= y && (other.x + other.width) >= x && (other.y + other.height) >= y; // other's bottom right falls within this area
return result1 | result2 | result3 | result4;
}
答案 17 :(得分:0)
对于那些使用中心点和半尺寸的矩形数据的人来说,而不是典型的x,y,w,h或x0,y0,x1,x1,这里有你怎么做它:
#include <cmath> // for fabsf(float)
struct Rectangle
{
float centerX, centerY, halfWidth, halfHeight;
};
bool isRectangleOverlapping(const Rectangle &a, const Rectangle &b)
{
return (fabsf(a.centerX - b.centerX) <= (a.halfWidth + b.halfWidth)) &&
(fabsf(a.centerY - b.centerY) <= (a.halfHeight + b.halfHeight));
}
答案 18 :(得分:0)
事实证明,如果我们从另一侧看问题(算法),这个案例很简单。
这意味着,我们将回答问题:“矩形不重叠吗?”,而不是回答“矩形是否重叠?”。
最后,两个问题都解决了相同的问题,但第二个问题的答案更易于实现,因为矩形仅在一个位于另一个下方时或一个位于另一个下方时才重叠。 (对于其中一种情况就足够了,但是当然可能会同时发生两种情况-在这里,对逻辑条件“或”的良好理解很重要) 。这样可以减少许多需要在第一个问题上考虑的情况。
使用适当的变量名也可以简化整个过程:
#include<bits/stdc++.h>
struct Rectangle
{
// Coordinates of the top left corner of the rectangle and width and height
float x, y, width, height;
};
bool areRectanglesOverlap(Rectangle rect1, Rectangle rect2)
{
// Declaration and initialization of local variables
// if x and y are the top left corner of the rectangle
float left1, top1, right1, bottom1, left2, top2, right2, bottom2;
left1 = rect1.x;
top1 = rect1.y;
right1 = rect1.x + rect1.width;
bottom1 = rect1.y - rect1.height;
left2 = rect2.x;
top2 = rect2.y;
right2 = rect2.x + rect2.width;
bottom2 = rect2.y - rect2.height;
// The main part of the algorithm
// The first rectangle is under the second or vice versa
if (top1 < bottom2 || top2 < bottom1)
{
return false;
}
// The first rectangle is to the left of the second or vice versa
if (right1 < left2 || right2 < left1)
{
return false;
}
// Rectangles overlap
return true;
}
即使如果我们有不同的矩形表示形式,也可以通过仅修改定义了变量更改的部分来使上面的函数很容易地适应它。保持不变(当然,这里实际上并不需要注释,但我添加了注释,以便每个人都可以快速理解此简单算法)。
等效的 ,但上面功能的形式的可读性可能看起来像这样:
bool areRectanglesOverlap(Rectangle rect1, Rectangle rect2)
{
float left1, top1, right1, bottom1, left2, top2, right2, bottom2;
left1 = rect1.x;
top1 = rect1.y;
right1 = rect1.x + rect1.width;
bottom1 = rect1.y - rect1.height;
left2 = rect2.x;
top2 = rect2.y;
right2 = rect2.x + rect2.width;
bottom2 = rect2.y - rect2.height;
return !(top1 < bottom2 || top2 < bottom1 || right1 < left2 || right2 < left1);
}
答案 19 :(得分:0)
struct point { int x, y; };
struct rect { point tl, br; }; // top left and bottom right points
// return true if rectangles overlap
bool overlap(const rect &a, const rect &b)
{
return a.tl.x <= b.br.x && a.br.x >= b.tl.x &&
a.tl.y >= b.br.y && a.br.y <= b.tl.y;
}
答案 20 :(得分:0)
我已经实现了C#版本,很容易转换为C ++。
public bool Intersects ( Rectangle rect )
{
float ulx = Math.Max ( x, rect.x );
float uly = Math.Max ( y, rect.y );
float lrx = Math.Min ( x + width, rect.x + rect.width );
float lry = Math.Min ( y + height, rect.y + rect.height );
return ulx <= lrx && uly <= lry;
}
答案 21 :(得分:-1)
这个答案应该是最重要的答案:
如果矩形重叠,则重叠区域将大于零。现在让我们找到重叠区域:
如果它们重叠,那么overlap-rect的左边缘将是max(r1.x1, r2.x1)
,右边缘将是min(r1.x2, r2.x2)
。因此重叠的长度为min(r1.x2, r2.x2) - max(r1.x1, r2.x1)
所以该区域将是:
area = (max(r1.x1, r2.x1) - min(r1.x2, r2.x2)) * (max(r1.y1, r2.y1) - min(r1.y2, r2.y2))
如果area = 0
则不重叠。
简单不是吗?
答案 22 :(得分:-1)
“如果你执行减去对应于两个面向每个矩形的顶点的x或y坐标,如果结果是相同的符号,那么两个矩形不会重叠轴”(对不起,我不确定我的翻译是正确的)
来源:http://www.ieev.org/2009/05/kiem-tra-hai-hinh-chu-nhat-chong-nhau.html
答案 23 :(得分:-1)
用于确定矩形是否相互接触或重叠的Java代码
<强> ... 强>
for ( int i = 0; i < n; i++ ) {
for ( int j = 0; j < n; j++ ) {
if ( i != j ) {
Rectangle rectangle1 = rectangles.get(i);
Rectangle rectangle2 = rectangles.get(j);
int l1 = rectangle1.l; //left
int r1 = rectangle1.r; //right
int b1 = rectangle1.b; //bottom
int t1 = rectangle1.t; //top
int l2 = rectangle2.l;
int r2 = rectangle2.r;
int b2 = rectangle2.b;
int t2 = rectangle2.t;
boolean topOnBottom = t2 == b1;
boolean bottomOnTop = b2 == t1;
boolean topOrBottomContact = topOnBottom || bottomOnTop;
boolean rightOnLeft = r2 == l1;
boolean leftOnRight = l2 == r1;
boolean rightOrLeftContact = leftOnRight || rightOnLeft;
boolean leftPoll = l2 <= l1 && r2 >= l1;
boolean rightPoll = l2 <= r1 && r2 >= r1;
boolean leftRightInside = l2 >= l1 && r2 <= r1;
boolean leftRightPossiblePlaces = leftPoll || rightPoll || leftRightInside;
boolean bottomPoll = t2 >= b1 && b2 <= b1;
boolean topPoll = b2 <= b1 && t2 >= b1;
boolean topBottomInside = b2 >= b1 && t2 <= t1;
boolean topBottomPossiblePlaces = bottomPoll || topPoll || topBottomInside;
boolean topInBetween = t2 > b1 && t2 < t1;
boolean bottomInBetween = b2 > b1 && b2 < t1;
boolean topBottomInBetween = topInBetween || bottomInBetween;
boolean leftInBetween = l2 > l1 && l2 < r1;
boolean rightInBetween = r2 > l1 && r2 < r1;
boolean leftRightInBetween = leftInBetween || rightInBetween;
if ( (topOrBottomContact && leftRightPossiblePlaces) || (rightOrLeftContact && topBottomPossiblePlaces) ) {
path[i][j] = true;
}
}
}
}
<强> ... 强>