如何查看两个矩形在JavaScript或伪代码中是否相交?

时间:2013-04-14 22:30:17

标签: javascript geometry rectangles

我有两个矩形,无论它们是否相交,我都必须在函数中返回。

它们由[ x0, y0, x1, y1 ]对表示,代表矩形的左上角和右下角。或者,你的解决方案可能是[ x0, y0, width, height ],如果它更简单,我可以调整我的函数的参数输入。

我试图查看矩形A中的两个角中是否有任何一个包含在矩形B中,但如果A大于B且B部分包含在A中,则表示它不重叠。现在我可以尝试A和B,但这似乎是一种糟糕的做事方式。

我无法预先制作一个大网格并占据矩形的矩形,因为不知道矩形是什么样的。我只能说它们是无符号整数,最小值为0,最大值未知。

5 个答案:

答案 0 :(得分:10)

如果要检查2个旋转的矩形是否发生碰撞,则必须在另一个的轴上投影一个矩形角。 如果rectA的所有投影都击中了rectB,并且rectB投影击中了rectA,则两个矩形会发生碰撞。

有些投影不会碰撞,2个矩形不会碰撞。 enter image description here

4个投影击中另一个矩形,2个矩形相撞。 enter image description here

我已就此JSFiddle做了一个演示,以便更加理解。

您可以查看函数is_collide以获取更多示例

答案 1 :(得分:8)

检查矩形绝对不相交的情况。如果这些情况都不成立则矩形必须相交。即:

public boolean rectanglesIntersect( 
    float minAx, float minAy, float maxAx, float maxAy,
    float minBx, float minBy, float maxBx, float maxBy ) {
    boolean aLeftOfB = maxAx < minBx;
    boolean aRightOfB = minAx > maxBx;
    boolean aAboveB = minAy > maxBy;
    boolean aBelowB = maxAy < minBy;

    return !( aLeftOfB || aRightOfB || aAboveB || aBelowB );
}

这说明了这个概念,但可以通过内联布尔值来加快速度,以便利用||的短路行为

答案 2 :(得分:4)

如果x和y区域重叠,则两个矩形重叠。如果x坐标中的任何一个与其他矩形重叠,则会有一圈重叠。

沿x轴,第一个点在另外两个矩形内,第二个点在另外两个内,或者两个点位于其他两个点的相对两侧。

function checkRectOverlap(rect1, rect2) {
    /*
     * Each array in parameter is one rectangle
     * in each array, there is an array showing the co-ordinates of two opposite corners of the rectangle
     * Example:
     * [[x1, y1], [x2, y2]], [[x3, y3], [x4, y4]]
     */

    //Check whether there is an x overlap
    if ((rect1[0][0] < rect2[0][0] && rect2[0][0] < rect1[1][0]) //Event that x3 is inbetween x1 and x2
        || (rect1[0][0] < rect2[1][0] && rect2[1][0] < rect1[1][0]) //Event that x4 is inbetween x1 and x2
        || (rect2[0][0] < rect1[0][0] && rect1[1][0] < rect2[1][0])) {  //Event that x1 and x2 are inbetween x3 and x4
        //Check whether there is a y overlap using the same procedure
        if ((rect1[0][1] < rect2[0][1] && rect2[0][1] < rect1[1][1]) //Event that y3 is between y1 and y2
            || (rect1[0][1] < rect2[1][1] && rect2[1][1] < rect1[1][1]) //Event that y4 is between y1 and y2
            || (rect2[0][1] < rect1[0][1] && rect1[1][1] < rect2[1][1])) { //Event that y1 and y2 are between y3 and y4
            return true;
        }
    }
    return false;
}

答案 3 :(得分:3)

给矩形1带点UL1和LR1,矩形2带点UR2和LR2 -

检查UL1是否在r2中或LR1是否在r2中(图中的情况1和情况2)。最后检查UR2 / LR2中的一个是否在r1中(图中的情况3)。

通过检查x和y是否在矩形的x和y范围的最小值和最大值之间来检查点是否在矩形中。

清除?

enter image description here

蓝色为R1,紫色为R2

答案 4 :(得分:1)

从另一个站点看这件事。

事实证明,如果我们从另一侧看问题(算法),这个案例很简单。

这意味着,我们将回答问题:“矩形重叠吗?”,而不是回答“矩形是否重叠?”。

最后,两个问题都解决了相同的问题,但第二个问题的答案更易于实现,因为矩形仅在一个位于另一个下方时或一个位于另一个下方时才重叠。 (对于其中一种情况就足够了,但是当然可能会同时发生两种情况-在这里,对逻辑条件“或”的良好理解很重要) 。这样可以减少许多需要在第一个问题上考虑的情况。

使用适当的变量名也可以简化整个过程:

const areRectanglesOverlap = (rect1, rect2) => {
  let [left1, top1, right1, bottom1] = [rect1[0], rect1[1], rect1[2], rect1[3]],
      [left2, top2, right2, bottom2] = [rect2[0], rect2[1], rect2[2], rect2[3]];
  // 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;
}

即使如果我们有不同的矩形表示形式,也可以通过仅修改定义了变量更改的部分来使上面的函数很容易地适应它。保持不变(当然,这里实际上并不需要注释,但我添加了注释,以便每个人都可以快速理解此简单算法)。

等效的 ,但上面功能的形式的可读性可能看起来像这样:

const areRectanglesOverlap = (rect1, rect2) => {

  let [left1, top1, right1, bottom1] = [...rect1],
      [left2, top2, right2, bottom2] = [...rect2];

  return !(top1 < bottom2 || top2 < bottom1 || right1 < left2 || right2 < left1);
}