简体   繁体   English

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

[英]Determine if two rectangles overlap each other?

I am trying to write a C++ program that takes the following inputs from the user to construct rectangles (between 2 and 5): height, width, x-pos, y-pos.我正在尝试编写一个 C++ 程序,它从用户那里获取以下输入来构造矩形(2 到 5 之间):高度、宽度、x-pos、y-pos。 All of these rectangles will exist parallel to the x and the y axis, that is all of their edges will have slopes of 0 or infinity.所有这些矩形都将平行于 x 轴和 y 轴存在,也就是说,它们的所有边都将具有 0 或无穷大的斜率。

I've tried to implement what is mentioned in this question but I am not having very much luck.我试图实现这个问题中提到的内容,但我运气不佳。

My current implementation does the following:我当前的实现执行以下操作:

// 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;  

However I'm not quite sure if (a) I've implemented the algorithm I linked to correctly, or if I did exactly how to interpret this?但是,我不太确定 (a) 我是否已经正确实现了链接到的算法,或者我是否确实如何解释它?

Any suggestions?有什么建议?

if (RectA.Left < RectB.Right && RectA.Right > RectB.Left &&
     RectA.Top > RectB.Bottom && RectA.Bottom < RectB.Top ) 

or, using Cartesian coordinates或者,使用笛卡尔坐标

(With X1 being left coord, X2 being right coord, increasing from left to right and Y1 being Top coord, and Y2 being Bottom coord, increasing from bottom to top -- if this is not how your coordinate system [eg most computers have the Y direction reversed], swap the comparisons below ) ... (X1 是左坐标,X2 是右坐标,从左到右增加,Y1 是顶坐标,Y2 是底坐标,从底到顶增加——如果这不是你的坐标系[例如大多数计算机都有Y 方向反转],交换下面的比较)...

if (RectA.X1 < RectB.X2 && RectA.X2 > RectB.X1 &&
    RectA.Y1 > RectB.Y2 && RectA.Y2 < RectB.Y1) 

Say you have Rect A, and Rect B. Proof is by contradiction.假设你有矩形 A 和矩形 B。证明是矛盾的。 Any one of four conditions guarantees that no overlap can exist :四个条件中的任何一个都保证不存在重叠

  • Cond1.条件 1。 If A's left edge is to the right of the B's right edge, - then A is Totally to right Of B如果 A 的左边缘在 B 右边缘的右侧,那么 A 完全在 B 的右侧
  • Cond2.条件 2。 If A's right edge is to the left of the B's left edge, - then A is Totally to left Of B如果 A 的右边缘在 B 左边缘的左边,那么 A 完全在 B 的左边
  • Cond3.条件 3。 If A's top edge is below B's bottom edge, - then A is Totally below B如果 A 的顶部边缘低于 B 的底部边缘, - 那么 A 完全低于 B
  • Cond4.条件 4。 If A's bottom edge is above B's top edge, - then A is Totally above B如果 A 的底边高于 B 的顶边, - 那么 A 完全高于 B

So condition for Non-Overlap is所以非重叠的条件是

NON-Overlap => Cond1 Or Cond2 Or Cond3 Or Cond4

Therefore, a sufficient condition for Overlap is the opposite.因此,Overlap 的充分条件是相反的。

Overlap => NOT (Cond1 Or Cond2 Or Cond3 Or Cond4)

De Morgan's law says德摩根定律说
Not (A or B or C or D) is the same as Not A And Not B And Not C And Not D Not (A or B or C or D)Not A And Not B And Not C And Not D
so using De Morgan, we have所以使用德摩根,我们有

Not Cond1 And Not Cond2 And Not Cond3 And Not Cond4

This is equivalent to:这相当于:

  • A's Left Edge to left of B's right edge, [ RectA.Left < RectB.Right ], and A 的左边缘到 B 的右边缘的左侧,[ RectA.Left < RectB.Right ],和
  • A's right edge to right of B's left edge, [ RectA.Right > RectB.Left ], and A 的右边缘到 B 的左边缘的右侧,[ RectA.Right > RectB.Left ],以及
  • A's top above B's bottom, [ RectA.Top > RectB.Bottom ], and A 的顶部高于 B 的底部,[ RectA.Top > RectB.Bottom ],以及
  • A's bottom below B's Top [ RectA.Bottom < RectB.Top ] A 的底部低于 B 的顶部 [ RectA.Bottom < RectB.Top ]

Note 1 : It is fairly obvious this same principle can be extended to any number of dimensions.注 1 :很明显,同样的原则可以扩展到任意数量的维度。
Note 2 : It should also be fairly obvious to count overlaps of just one pixel, change the < and/or the > on that boundary to a <= or a >= .注意 2 :计算一个像素的重叠也应该是相当明显的,将该边界上的<和/或>更改为<=>=
Note 3 : This answer, when utilizing Cartesian coordinates (X, Y) is based on standard algebraic Cartesian coordinates (x increases left to right, and Y increases bottom to top).注 3 :这个答案,当使用笛卡尔坐标 (X, Y) 时基于标准代数笛卡尔坐标(x 从左到右增加,Y 从下到上增加)。 Obviously, where a computer system might mechanize screen coordinates differently, (eg, increasing Y from top to bottom, or X From right to left), the syntax will need to be adjusted accordingly/显然,如果计算机系统可能会以不同的方式机械化屏幕坐标(例如,从上到下增加 Y,或从右到左增加 X),则需要相应地调整语法/

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

It is easier to check if a rectangle is completly outside the other, so if it is either检查一个矩形是否完全在另一个矩形之外更容易,所以如果它是

on the left...在左边...

(r1.x + r1.width < r2.x)

or on the right...或者在右边...

(r1.x > r2.x + r2.width)

or on top...或者在上面...

(r1.y + r1.height < r2.y)

or on the bottom...或者在底部...

(r1.y > r2.y + r2.height)

of the second rectangle, it cannot possibly collide with it.的第二个矩形,它不可能与它碰撞。 So to have a function that returns a Boolean saying weather the rectangles collide, we simply combine the conditions by logical ORs and negate the result:因此,要获得一个返回布尔值的函数,表示矩形发生碰撞,我们只需通过逻辑 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);
}

To already receive a positive result when touching only, we can change the "<" and ">" by "<=" and ">=".为了仅在触摸时已经收到肯定的结果,我们可以将“<”和“>”更改为“<=”和“>=”。

Suppose that you have defined the positions and sizes of the rectangles like this:假设您已经定义了矩形的位置和大小,如下所示:

在此处输入图片说明

My C++ implementation is like this:我的 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;
}

An example function call according to the given figure above:根据上图给出的示例函数调用:

DoRectanglesOverlap(Vector2D(3, 7),
                    Vector2D(8, 5),
                    Vector2D(6, 4),
                    Vector2D(9, 4));

The comparisons inside the if block will look like below: 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    ))

Ask yourself the opposite question: How can I determine if two rectangles do not intersect at all?问自己相反的问题:如何确定两个矩形是否根本不相交? Obviously, a rectangle A completely to the left of rectangle B does not intersect.显然,完全位于矩形 B 左侧的矩形 A 不相交。 Also if A is completely to the right.同样,如果 A 完全向右。 And similarly if A is completely above B or completely below B. In any other case A and B intersect.同样,如果 A 完全高于 B 或完全低于 B。在任何其他情况下,A 和 B 相交。

What follows may have bugs, but I am pretty confident about the algorithm:下面的内容可能有错误,但我对算法非常有信心:

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

This is a very fast way to check with C++ if two rectangles overlap:如果两个矩形重叠,这是使用 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);

It works by calculating the left and right borders of the intersecting rectangle, and then comparing them: if the right border is equal to or less than the left border, it means that the intersection is empty and therefore the rectangles do not overlap;它的工作原理是计算相交矩形的左右边界,然后比较它们:如果右边界等于或小于左边界,则表示相交为空,因此矩形不重叠; otherwise, it tries again with the top and bottom borders.否则,它会再次尝试使用顶部和底部边框。

What is the advantage of this method over the conventional alternative of 4 comparisons?与传统的 4 次比较替代方法相比,这种方法有什么优势? It's about how modern processors are designed.这是关于现代处理器的设计方式。 They have something called branch prediction, which works well when the result of a comparison is always the same, but have a huge performance penalty otherwise.他们有一种叫做分支预测的东西,当比较的结果总是相同的时候它工作得很好,但否则会有巨大的性能损失。 However, in the absence of branch instructions, the CPU performs quite well.但是,在没有分支指令的情况下,CPU 的表现相当不错。 By calculating the borders of the intersection instead of having two separate checks for each axis, we're saving two branches, one per pair.通过计算交点的边界而不是对每个轴进行两次单独的检查,我们节省了两个分支,每对一个。

It is possible that the four comparisons method outperforms this one, if the first comparison has a high chance of being false.如果第一个比较很可能是错误的,那么四次比较方法可能会优于这个方法。 That is very rare, though, because it means that the second rectangle is most often on the left side of the first rectangle, and not on the right side or overlapping it;不过,这种情况非常罕见,因为这意味着第二个矩形通常位于第一个矩形的左侧,而不是右侧或与其重叠; and most often, you need to check rectangles on both sides of the first one, which normally voids the advantages of branch prediction.大多数情况下,您需要检查第一个矩形两侧的矩形,这通常会抵消分支预测的优势。

This method can be improved even more, depending on the expected distribution of rectangles:此方法可以进一步改进,具体取决于矩形的预期分布:

  • If you expect the checked rectangles to be predominantly to the left or right of each other, then the method above works best.如果您希望选中的矩形主要位于彼此的左侧或右侧,那么上述方法效果最佳。 This is probably the case, for example, when you're using the rectangle intersection to check collisions for a game, where the game objects are predominantly distributed horizontally (eg a SuperMarioBros-like game).例如,当您使用矩形交集检查游戏的碰撞时,可能就是这种情况,其中游戏对象主要是水平分布的(例如,类似 SuperMarioBros 的游戏)。
  • If you expect the checked rectangles to be predominantly to the top or bottom of each other, eg in an Icy Tower type of game, then checking top/bottom first and left/right last will probably be faster:如果您希望选中的矩形主要位于彼此的顶部或底部,例如在冰塔类型的游戏中,那么首先检查顶部/底部和最后左侧/右侧可能会更快:
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);
  • If the probability of intersecting is close to the probability of not intersecting, however, it's better to have a completely branchless alternative:如果相交的概率接近于不相交的概率,那么最好有一个完全无分支的替代方案:
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);

(Note the change of && to a single & ) (注意将&&更改为单个&

Here's how it's done in the Java API:下面是它在 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));
}

In the question, you link to the maths for when rectangles are at arbitrary angles of rotation.在这个问题中,您链接到矩形处于任意旋转角度时的数学。 If I understand the bit about angles in the question however, I interpret that all rectangles are perpendicular to one another.但是,如果我理解问题中关于角度的一点,我会解释所有矩形都相互垂直。

A general knowing the area of overlap formula is:一般知道重叠面积公式是:

Using the example:使用示例:

1   2   3   4   5   6

1  +---+---+
   |       |   
2  +   A   +---+---+
   |       | B     |
3  +       +   +---+---+
   |       |   |   |   |
4  +---+---+---+---+   +
               |       |
5              +   C   +
               |       |
6              +---+---+

1) collect all the x coordinates (both left and right) into a list, then sort it and remove duplicates 1)将所有x坐标(左右)收集到一个列表中,然后对其进行排序并删除重复项

1 3 4 5 6

2) collect all the y coordinates (both top and bottom) into a list, then sort it and remove duplicates 2)将所有y坐标(顶部和底部)收集到一个列表中,然后对其进行排序并删除重复项

1 2 3 4 6

3) create a 2D array by number of gaps between the unique x coordinates * number of gaps between the unique y coordinates. 3) 通过唯一 x 坐标之间的间隙数 * 唯一 y 坐标之间的间隙数创建一个二维数组。

4 * 4

4) paint all the rectangles into this grid, incrementing the count of each cell it occurs over: 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) As you paint the rectangles, its easy to intercept the overlaps. 5) 在绘制矩形时,很容易截取重叠部分。

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

Lets say the two rectangles are rectangle A and rectangle B. Let their centers be A1 and B1 (coordinates of A1 and B1 can be easily found out), let the heights be Ha and Hb, width be Wa and Wb, let dx be the width(x) distance between A1 and B1 and dy be the height(y) distance between A1 and B1.假设这两个矩形是矩形 A 和矩形 B。 设它们的中心为 A1 和 B1(A1 和 B1 的坐标很容易找到),设高度为 Ha 和 Hb,宽度为 Wa 和 Wb,设 dx 为A1 和 B1 之间的宽度(x)距离和 dy 是 A1 和 B1 之间的高度(y)距离。

Now we can say we can say A and B overlap: when现在我们可以说我们可以说 A 和 B 重叠:当

if(!(dx > Wa+Wb)||!(dy > Ha+Hb)) returns true

Easiest way is最简单的方法是

/**
 * 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);
}

first of all put it in to your mind that in computers the coordinates system is upside down.首先要记住,在计算机中坐标系是颠倒的。 x-axis is same as in mathematics but y-axis increases downwards and decrease on going upward.. if rectangle are drawn from center. x 轴与数学中的相同,但 y 轴向下增加,向上减少。如果从中心绘制矩形。 if x1 coordinates is greater than x2 plus its its half of widht.如果 x1 坐标大于 x2 加上其宽度的一半。 then it means going half they will touch each other.那么这意味着走一半他们会互相接触。 and in the same manner going downward + half of its height.并以同样的方式向下+一半高度。 it will collide..会碰撞。。

Don't think of coordinates as indicating where pixels are.不要将坐标视为指示像素所在的位置。 Think of them as being between the pixels.将它们视为在像素之间。 That way, the area of a 2x2 rectangle should be 4, not 9.这样,2x2 矩形的面积应该是 4,而不是 9。

bool bOverlap = !((A.Left >= B.Right || B.Left >= A.Right)
               && (A.Bottom >= B.Top || B.Bottom >= A.Top));

I have a very easy solution我有一个非常简单的解决方案

let x1,y1 x2,y2 ,l1,b1,l2,be cordinates and lengths and breadths of them respectively让 x1,y1 x2,y2 ,l1,b1,l2,be 分别为它们的坐标和长度和宽度

consider the condition ((x2考虑条件 ((x2

now the only way these rectangle will overlap is if the point diagonal to x1,y1 will lie inside the other rectangle or similarly the point diagonal to x2,y2 will lie inside the other rectangle.现在,这些矩形重叠的唯一方式是,x1,y1 的对角线点是否位于另一个矩形内,或者类似地,x2,y2 的对角线点将位于另一个矩形内。 which is exactly the above condition implies.这正是上述条件所暗示的。

A and B be two rectangle. A和B是两个矩形。 C be their covering rectangle. 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) 

It takes care all possible cases.它会处理所有可能的情况。

If the rectangles overlap then the overlap area will be greater than zero.如果矩形重叠,则重叠面积将大于零。 Now let us find the overlap area:现在让我们找到重叠区域:

If they overlap then the left edge of overlap-rect will be the max(r1.x1, r2.x1) and right edge will be min(r1.x2, r2.x2) .如果它们重叠,那么重叠矩形的左边缘将是max(r1.x1, r2.x1) ,右边缘将是min(r1.x2, r2.x2) So the length of the overlap will be min(r1.x2, r2.x2) - max(r1.x1, r2.x1)所以重叠的长度将是min(r1.x2, r2.x2) - max(r1.x1, r2.x1)

So the area will be:所以该区域将是:

area = (max(r1.x1, r2.x1) - min(r1.x2, r2.x2)) * (max(r1.y1, r2.y1) - min(r1.y2, r2.y2))

If area = 0 then they don't overlap.如果area = 0则它们不重叠。

Simple isn't it?是不是很简单?

I have implemented a C# version, it is easily converted to C++.我已经实现了一个 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;
}

This is from exercise 3.28 from the book Introduction to Java Programming- Comprehensive Edition.这是来自 Java 编程简介 - 综合版一书的练习 3.28。 The code tests whether the two rectangles are indenticle, whether one is inside the other and whether one is outside the other.代码测试两个矩形是否为齿形,一个矩形是否在另一个矩形内,一个矩形是否在另一个矩形外部。 If none of these condition are met then the two overlap.如果这些条件都不满足,则两者重叠。

**3.28 (Geometry: two rectangles) Write a program that prompts the user to enter the center x-, y-coordinates, width, and height of two rectangles and determines whether the second rectangle is inside the first or overlaps with the first, as shown in Figure 3.9. **3.28(几何:两个矩形)编写一个程序,提示用户输入两个矩形的中心 x、y 坐标、宽度和高度,并确定第二个矩形是在第一个矩形内部还是与第一个矩形重叠,如图 3.9 所示。 Test your program to cover all cases.测试您的程序以涵盖所有情况。 Here are the sample runs:以下是示例运行:

Enter r1's center x-, y-coordinates, width, and height: 2.5 4 2.5 43 Enter r2's center x-, y-coordinates, width, and height: 1.5 5 0.5 3 r2 is inside r1输入 r1 的中心 x、y 坐标、宽度和高度:2.5 4 2.5 43 输入 r2 的中心 x、y 坐标、宽度和高度:1.5 5 0.5 3 r2 在 r1 内

Enter r1's center x-, y-coordinates, width, and height: 1 2 3 5.5 Enter r2's center x-, y-coordinates, width, and height: 3 4 4.5 5 r2 overlaps r1输入 r1 的中心 x、y 坐标、宽度和高度:1 2 3 5.5 输入 r2 的中心 x、y 坐标、宽度和高度:3 4 4.5 5 r2 与 r1 重叠

Enter r1's center x-, y-coordinates, width, and height: 1 2 3 3 Enter r2's center x-, y-coordinates, width, and height: 40 45 3 2 r2 does not overlap 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");
    }

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

For those of you who are using center points and half sizes for their rectangle data, instead of the typical x,y,w,h, or x0,y0,x1,x1, here's how you can do it:对于那些在矩形数据中使用中心点和半尺寸的人,而不是典型的 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)); 
}
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;
}

就这么简单……

   bool Intersect = RectA.IntersectsWith(RectB);

"If you perform subtraction x or y coordinates corresponding to the vertices of the two facing each rectangle, if the results are the same sign, the two rectangle do not overlap axes that" (i am sorry, i am not sure my translation is correct) “如果您对每个矩形的两个顶点对应的 x 或 y 坐标执行减法,如果结果相同,则两个矩形不重叠轴”(对不起,我不确定我的翻译是否正确)

在此处输入图片说明

Source: http://www.ieev.org/2009/05/kiem-tra-hai-hinh-chu-nhat-chong-nhau.html资料来源: http : //www.ieev.org/2009/05/kiem-tra-hai-hinh-chu-nhat-c​​hong-nhau.html

Java code to figure out if Rectangles are contacting or overlapping each other用于确定矩形是否相互接触或重叠的 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;
            }
        }
    }
}

... ...

A look at the matter from a different site. 从另一个站点看问题。

The case turns out to be quite simple if we look at the problem (algorithm) from the other side . 如果我们从另一侧看问题(算法),则情况非常简单

It means that instead of answering the question: "Are the rectangles overlap?", we will answer the question: "Are the rectangles do not overlap?". 这意味着我们将回答问题:“矩形重叠吗?”,而不是回答“矩形是否重叠?”的问题。

In the end, both questions resolve the same problem but the answer to the second question is simpler to implement because rectangles do not overlap only when one is under the other or when one is more to the left of the other (it is enough for one of these cases to take place, but of course it may happen that both will happen simultaneously - here a good understanding of the logical condition "or" is important). 最后,两个问题都解决了相同的问题,但是第二个问题的答案更易于实现,因为矩形仅在一个位于另一个下方或一个位于另一个左侧时才重叠(对于一个矩形就足够了)发生这些情况,但是当然可能会同时发生-在这里,对逻辑条件“或”的良好理解很重要)。 This reduces many cases that need to be considered on the first question. 这减少了许多在第一个问题上需要考虑的情况。

The whole matter is also simplified by the use of appropriate variable names : 使用适当的变量名也可以简化整个过程:

#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;
}

Even if we have a different representation of a rectangle, it is easy to adapt the above function to it by modifying only the section where the variables changes are defined. 即使我们有不同的矩形表示形式,也可以通过仅修改定义了变量更改的部分来使上面的函数适应于它。 The further part of the function remains unchanged (of course, the comments are not really needed here, but I added them so that everyone could quickly understand this simple algorithm). 函数的其他部分保持不变(当然,这里实际上并不需要注释,但我添加了注释,以便每个人都可以快速理解此简单算法)。

An equivalent but maybe a little less readable form of the above function may look like this: 以上功能等效 形式,但可读性较低可能看起来像这样:

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

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

相关问题 无法确定两个正方形/矩形是否相交 - Can't determine if two squares/rectangles are intersecting each other 确定两个矩形相交的面积 - Determine the area of the intersection of two rectangles 检查两个矩形是否重叠或边缘是否接触 - Check if two rectangles overlap or the edges touch 如何计算两个矩形的重叠百分比? - How can you calculate the percentage overlap of two rectangles? 为什么矩形/条形不相互交换? - Why are the rectangles/bars not swapping with each other? Ncurses 和 gdb 屏幕在调试时重叠。 所以我想把两个屏幕分开 - Ncurses and gdb screens overlap at debug time. So I want to split the two screens with each other 调整窗口大小时,如何防止两个以上的组件相互重叠? - How to prevent two for more components to overlap each other when resizing window? 如何检查两个或更多个时间段在c ++中是否相互重叠? - How to check if two or more time periods overlap each other in c++? 如何确定两个隐式转换序列优先于重载解析? - How to determine two implicit conversion sequences preferred than each other for overload resolution? 如何确定一组矩形是否包含两个有重叠区域的人? - how to determine whether a set of rectangles contain two who have overlapped area?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM