快速矩形到矩形的交点


81

测试2个矩形是否相交的快速方法是什么?


在网上搜索时发现了这种单行代码(WOOT!),但我不知道如何用Java脚本编写它,它似乎是用C ++的古老形式编写的。

struct
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT; 

bool IntersectRect(const RECT * r1, const RECT * r2)
{
    return ! ( r2->left > r1->right
        || r2->right < r1->left
        || r2->top > r1->bottom
        || r2->bottom < r1->top
        );
}

5
我认为您在复制/粘贴操作中有错字
fmark 2010年

5
原始文章有错字。r2->right left没有道理。由于HTML转义问题,它可能已损坏。
马塞洛·坎托斯

42
我很好奇您认为上面的代码在C ++的“现代”形式中会有什么不同。
jamesdlin'5

3
我确定缺少的字符是<由于html转义引起的符号。
devios1 2011年

1
@jamesdlin,您可以使用一个参数将函数作为结构的成员函数。其次,通常使用const&代替const *。您可能会使用模板同时具有int,long和double版本,而不是使用某些Win32宏...(它也不会编译,因为RECT最终是未命名结构的实例,而不是类型名。) :ideone.com/bnzwl3
塞巴斯蒂安·瓦尔

Answers:


142

这就是将代码转换为JavaScript的方式。请注意,正如注释所建议的那样,您的代码和本文的代码中都有一个错字。该功能r2->right left应该r2->right < r1->left并且r2->bottom top应该具体r2->bottom < r1->top起作用。

function intersectRect(r1, r2) {
  return !(r2.left > r1.right || 
           r2.right < r1.left || 
           r2.top > r1.bottom ||
           r2.bottom < r1.top);
}

测试用例:

var rectA = {
  left:   10,
  top:    10,
  right:  30,
  bottom: 30
};

var rectB = {
  left:   20,
  top:    20,
  right:  50,
  bottom: 50
};

var rectC = {
  left:   70,
  top:    70,
  right:  90,
  bottom: 90
};

intersectRect(rectA, rectB);  // returns true
intersectRect(rectA, rectC);  // returns false

只是要添加/确认-这是测试三个20px x 20px的盒子,除了rectB 30px x 30px之外
verenion 2013年

6
如果r1和r2相同,则intersectRect函数将返回false
zumalifeguard 2013年

出色的口才实施。爱它!+1,非常适合我的游戏。
Unome 2014年

1
@zumalifeguard你为什么这么认为?
Minix

这个功能真是天才。我永远不会想到这一点,相反,我会尝试使两个盒子相交。
尼克·黄

69
function intersect(a, b) {
  return (a.left <= b.right &&
          b.left <= a.right &&
          a.top <= b.bottom &&
          b.top <= a.bottom)
}

假设top通常小于bottom(即y坐标向下增加)。


良好且可行的解决方案,但应慢一些,因为必须评估所有条件。条件之一为真时,立即执行另一种解决方案。
Gigo 2013年

21
条件之一为假时,也会立即执行此操作。即与另一种情况完全相同。
DS。

3
这样比较好,因为它消除了否定操作。
Discipol

4
+1,比接受的答案整齐。如果使用半开范围(即矩形包括顶部和左侧,但不包括底部和右侧,这在许多图形系统中很常见),则更<=改为<应该有效。
2013年

我喜欢此解决方案,因为我可以=针对每个条件删除,并且它允许矩形在边界上“接触”。
prograhammer

19

.NET Framework就是这样实现Rectangle.Intersect

public bool IntersectsWith(Rectangle rect)
{
  if (rect.X < this.X + this.Width && this.X < rect.X + rect.Width && rect.Y < this.Y + this.Height)
    return this.Y < rect.Y + rect.Height;
  else
    return false;
}

或静态版本:

public static Rectangle Intersect(Rectangle a, Rectangle b)
{
  int x = Math.Max(a.X, b.X);
  int num1 = Math.Min(a.X + a.Width, b.X + b.Width);
  int y = Math.Max(a.Y, b.Y);
  int num2 = Math.Min(a.Y + a.Height, b.Y + b.Height);
  if (num1 >= x && num2 >= y)
    return new Rectangle(x, y, num1 - x, num2 - y);
  else
    return Rectangle.Empty;
}

6

另一个更简单的方法。(假设y轴向下增加)。

function intersect(a, b) {
  return Math.max(a.left, b.left) < Math.min(a.right, b.right) &&
          Math.max(a.top, b.top) < Math.min(a.bottom, b.bottom);
}

上面条件中的4个数字(最大值和最小值)也给出了交点。



0

我使用了多种方法来检测大矩形内的小矩形。这是一个nodejs方法,使用width / height,但可以轻松进行调整。

            isIntersectingRect: function (r1, r2) {
              var quickCheck = (r1.x <= r2.x + r2.w &&
                      r2.x <= r1.x + r1.w &&
                      r1.y <= r2.y + r2.h &&
                      r2.y <= r1.y + r1.h)
              if (quickCheck) return true;
              var x_overlap = Math.max(0, Math.min(r1.x + r1.w, r2.x + r2.w) - Math.max(r1.x, r2.x));
              var y_overlap = Math.max(0, Math.min(r1.y + r1.h, r2.y + r2.h) - Math.max(r1.y, r2.y));
              var overlapArea = x_overlap * y_overlap;
              return overlapArea == 0;
            }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.