当前位置:  开发笔记 > 编程语言 > 正文

确定两个矩形是否相互重叠?

如何解决《确定两个矩形是否相互重叠?》经验,为你挑选了6个好方法。

我正在尝试编写一个C++程序,它从用户那里获取以下输入来构造矩形(2到5之间):高度,宽度,x-pos,y-pos.所有这些矩形将平行于x轴和y轴存在,即它们的所有边都将具有0或无穷大的斜率.

我试图实现这个问题中提到的但我没有太多运气.

我目前的实现如下:

// 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)我是否实现了我正确链接的算法,或者我是否确实如何解释这个?

有什么建议?



1> Charles Bret..:
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.如果A的左边缘位于B的右边缘的右边,那么A就完全在B的右边

COND2.如果A的右边缘位于B左边缘的左边,那么A则完全在B的左边

COND3.如果A的上边缘低于B的下边缘,则A完全低于B

COND4.如果A的下边缘高于B的上边缘,那么A完全高于B

所以非重叠的条件是

Cond1 Or Cond2 Or Cond3 Or Cond4

因此,重叠的充分条件恰恰相反.

Not (Cond1 Or Cond2 Or Cond3 Or Cond4)

De Morgan的法律说
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

这相当于:

A的左边缘位于B的右边缘,[ RectA.Left < RectB.Right]和

A的右边缘到B的左边缘,[ RectA.Right > RectB.Left]和

A高于B的底部,[ RectA.Top > RectB.Bottom]和

A的底部位于B的顶部[ RectA.Bottom < RectB.Top]

注1:很明显,同样的原则可以扩展到任意数量的维度.
注2:计算一个像素的重叠,将该边界<和/或>边界更改为a <=或a 也应该是相当明显的>=.
注3:当使用笛卡尔坐标(X,Y)时,这个答案基于标准代数笛卡尔坐标(x从左到右增加,Y从下到上增加).显然,在计算机系统可能以不同方式机械化屏幕坐标的情况下(例如,从上到下增加Y,或从右到左增加X),语法将需要相应地调整/


如果您很难想象其工作原理,我在http://silentmatt.com/intersection.html上创建了一个示例页面,您可以在其中拖动矩形并查看比较.
不,答案是正确的,如上所述.它基于标准笛卡尔坐标的使用.如果您使用的是其他系统(Y从上到下增加),请进行适当的调整.
我不得不在最后两次比较中交换<和>以使其工作
@MatthewCrumley对你链接上的A.Y1 B.Y1,不应该反转GT<标志吗?
你不觉得你在使用硬约束吗?如果两个矩形恰好在那边相互重叠怎么办?你不应该考虑<=,> = ??
我认为最简单的方法是查看下面的解决方案并应用DeMorgan定律.

2> e.James..:
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;
}


最简单,最干净的答案.
+1.也以明显的方式扩展到N维.

3> David Norman..:
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;
}



4> Björn Kechel..:

更容易检查一个矩形是否完全在另一个之外,所以如果它是

在左边...

(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);
}

仅在触摸时已经收到肯定结果,我们可以通过"<="和"> ="更改"<"和">".


并对其应用德摩根定律。

5> coryan..:

问自己相反的问题:我怎样才能确定两个矩形是否完全不相交?显然,矩形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);
}



6> hkBattousai..:

假设您已经定义了矩形的位置和大小,如下所示:

在此输入图像描述

我的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    ))

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有