【问题标题】:Get points of intersection of 2 Rectangles获取2个矩形的交点
【发布时间】:2026-01-28 18:30:01
【问题描述】:

如何获得 2 个矩形的交点。到目前为止,我已经得到了这个:

module.exports.boxIntersection = function(box1, box2) {
    var xMin1 = box1.x - box1.width;
    var xMin2 = box2.x - box2.width;
    var xMax1 = box1.x + box1.width;
    var xMax2 = box2.x + box2.width;
    var zMin1 = box1.z - box1.length;
    var zMin2 = box2.z - box2.length;
    var zMax1 = box1.z + box1.length;
    var zMax2 = box2.z + box2.length;
    var xMin = Math.max(xMin1, xMin2);
    var xMax = Math.min(xMax1, xMax2);
    if (xMax > xMin) {
        var zMin = Math.max(zMin1, zMin2);
        var zMax = Math.min(zMax1, zMax2);
        if (zMax > zMin) return [xMin, zMin, xMax, zMax];
    } return null;
};

这只会返回 2 个交点。但我需要像这样返回所有交点:

在这种情况下,它应该只返回 2 分:

我在这里看到了这个问题:Get the points of intersection from 2 rectangles

但它只返回 2 分。

编辑: 在矩形与另一个边对齐的情况下,应该只返回位于真正交叉点的点,如下所示:

【问题讨论】:

    标签: javascript geometry collision intersection


    【解决方案1】:

    您链接的答案实际上将矩形“相交”为多边形,作为平面上的多边形点集,并返回结果矩形的左下角和右上角(作为多边形集)。这两个返回的点实际上定义了结果矩形的所有 四个 角。所以,不,它不会“返回两分”。它实际上返回 四个 点。

    为了解决您的问题,您必须决定保留这四点中的哪一点,以及丢弃哪一点。规则很简单:你必须只保留那些与原始矩形的相应顶点不重合的点。您可以简单地以简单而乏味的方式直接检查这一点。八张支票(如果我没有遗漏任何一张),你就完成了。

    或者您可以使用稍微复杂一点的方法。

    假设我们有两个矩形:(x11, y11)-(x12, y12)(x21, y21)-(x22, y22)。矩形被规范化(如链接中所定义)。在计算重叠矩形时,我们仍然使用相同的 min-max 技术,但同时我们还要记住哪个原始矩形提供了极值

    int x1 = max(x11, x21);
    unsigned flags_x1 = (x1 == x11) | ((x1 == x21) << 1);
    
    int y1 = max(y11, y21);
    unsigned flags_y1 = (y1 == y11) | ((y1 == y21) << 1);
    
    int x2 = min(x12, x22);
    unsigned flags_x2 = (x2 == x12) | ((x2 == x22) << 1);
    
    int y2 = min(y12, y22);
    unsigned flags_y2 = (y2 == y12) | ((y2 == y22) << 1);
    

    现在我们检查这些矩形是否有适当的重叠

    if (x1 >= x2 || y1 >= y2)
     /* No overlap. Done */;
    

    但如果存在重叠,我们使用 flags_... 变量仅输出由来自两个不同矩形的极值形成的点

    /* Lower-left */
    if ((flags_x1 & flags_y1) == 0)
      /* Output (x1, y1) as intersection point */;
    
    /* Lower-right */
    if ((flags_x2 & flags_y1) == 0)
      /* Output (x2, y1) as intersection point */;
    
    /* Upper-left */
    if ((flags_x1 & flags_y2) == 0)
      /* Output (x1, y2) as intersection point */;
    
    /* Upper-right */
    if ((flags_x2 & flags_y2) == 0)
      /* Output (x2, y2) as intersection point */;
    

    请注意,如果一个矩形完全位于另一个矩形内,则上述不重叠测试将通过(因为矩形实际上确实重叠),但flags_... 测试将丢弃所有四个顶点。

    像往常一样,可能需要(或不需要)额外的努力来正确处理边界情况,例如触摸矩形(内部或外部触摸)。

    【讨论】:

    • 我在问题中添加了第三个数字。这也适用于那个用例吗?我很抱歉,但我不熟悉答案中的这种语法;
    • @Sidney de Vries:我当前的解决方案将完全按照您的想象处理第三种情况:它不会将内部/外部“触摸”视为交集。
    • 你介意解释一下这个操作吗:if ((flags_x1 & flags_y1) == 0) 还有这个操作符:
    • &lt;&lt; 是按位左移。我使用flags_... 变量中的位 0 和位 1 进行编码,哪个矩形提供了极值(并不是说两者都提供了相同的值 - 我们也必须记住这一点,这就是为什么我使用两个位)。 &amp; 是按位与运算。 ((flags_x1 &amp; flags_y1) == 0) 表示左下极端(x1y1)来自两个不同的矩形(flags_x1flags_y1 中没有共同的1 位)。
    • 此解决方案是否仅限于 C?因为我不能使用 C。我正在寻找一个更简单的伪代码解决方案,其他人也可能从答案中受益。抱歉耽误您的时间