【问题标题】:How do I see if two rectangles intersect in JavaScript or pseudocode?如何在 JavaScript 或伪代码中查看两个矩形是否相交?
【发布时间】:2013-04-14 22:30:16
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我编辑了您的问题,将“二维数组”更改为“矩形”。我想这就是你的意思,是吗?
  • 是的,我谈到了我的特殊网格问题,但现在正如你所说,使用矩形来描述这个更有意义,谢谢。

标签: javascript geometry rectangles


【解决方案1】:

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

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

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

【讨论】:

  • 一点改进:return maxAx &gt;= minBx &amp;&amp; minAx &lt;= maxBx &amp;&amp; minAy &lt;= maxBy &amp;&amp; maxAy &gt;= minBy
【解决方案2】:

更新

一段时间后,我决定重做一个关于检测 2 个旋转矩形之间碰撞的完整答案:How to detect when rotated rectangles are colliding each other


原答案

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

这里有些投影没有碰撞,两个矩形没有碰撞。

4 个投影碰到另一个矩形,这 2 个矩形发生碰撞。

我已经在这个JSFiddle 上做了一个演示,以便进一步理解。

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

【讨论】:

【解决方案3】:

从另一个网站看问题。

如果我们从另一面看问题(算法),这个案例其实很简单

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

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

整个问题也通过使用适当的变量名来简化

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

即使如果我们有一个不同的矩形表示,也很容易通过仅修改定义变量更改的部分来使上述函数适应它。函数的进一步部分保持不变不变(当然这里cmets并不是真的需要,但是我添加了它们是为了让大家快速理解这个简单的算法)。

上述函数的等效,但可读性可能稍差形式可能如下所示:

const areRectanglesOverlap = (rect1, rect2) => {

  let [left1, top1, right1, bottom1] = [...rect1],
      [left2, top2, right2, bottom2] = [...rect2];
  
  return !(top1 < bottom2 || top2 < bottom1 || right1 < left2 || right2 < left1);
}

【讨论】:

  • jsfiddle.net/pm87tf04 为什么这个例子返回 false。矩形二在矩形一内。
  • @Danny,这是因为您的输入数据不会创建矩形。注意top 在这两种情况下都是0,但bottom 在两种情况下都大于零(分别为32),这与top 应该是的基本假设相矛盾大于bottom。请检查:console.log(areRectanglesOverlap([0,3,1,0], [0,2,1,0]));
【解决方案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;
}

【讨论】:

    【解决方案5】:

    给出矩形 1 的点 UL1 和 LR1 以及矩形 2 的点 UR2 和 LR2 -

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

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

    清除?

    蓝色是R1,紫色是R2

    【讨论】:

    • 我认为这不包括两个矩形形成一个加号的情况(其中一个矩形的角点都没有落在另一个矩形内)。
    • 我必须像案例 3 一样测试蓝色是否在紫色范围内
    • @simhumileco 请不要编辑我的答案,除非你有什么要补充的。
    • 好的,@Hogan 我认为由于我的更改,您的好答案会更好(更具可读性),但如果您不喜欢这些更改,我很抱歉。请不要生我的气:)
    • @simhumileco -- 不要生气,只是不要认为随机粗体更清晰。
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多