快速矩形到矩形交集

IT技术 javascript c++ language-agnostic graphics
2021-01-24 14:03:36

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


网上一搜就找到了这个单行(WOOT!),但我不明白如何用Javascript编写它,它似乎是用一种古老的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
        );
}
6个回答

这就是将代码转换为 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
@zumalifeguard 你为什么这么认为?
2021-03-15 14:03:36
如果 r1 和 r2 相同,intersectRect 函数将返回 false
2021-03-29 14:03:36
只是为了添加/确认 - 这是测试三个 20px x 20px 的盒子,除了 rectB,它是 30px x 30px
2021-04-01 14:03:36
这个功能太天才了。我从来没有想过,相反,我会尝试让两个盒子相交。
2021-04-06 14:03:36
神奇的eloquent实施。爱它!+1,非常适合我的游戏。
2021-04-12 14:03:36
function intersect(a, b) {
  return (a.left <= b.right &&
          b.left <= a.right &&
          a.top <= b.bottom &&
          b.top <= a.bottom)
}

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

我喜欢这个解决方案,因为我可以删除=每个条件的 ,它允许矩形在边框上“触摸”。
2021-03-16 14:03:36
好的和有效的解决方案,但应该慢一点,因为必须评估所有条件。一旦其中一个条件评估为真,另一个解决方案就会完成。
2021-03-31 14:03:36
这更好,因为它消除了否定动作。
2021-04-02 14:03:36
+1,比接受的答案更整洁。如果使用半开范围(即矩形包括顶部和左侧但不包括底部和右侧,这在许多图形系统中很常见),更改<=<应该可以工作。
2021-04-03 14:03:36
一旦其中一个条件评估为假,也会立即执行此操作。即在与另一个完全相同的情况下。
2021-04-05 14:03:36

这就是 .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;
}

另一种更简单的方法。(这假设 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 个数字(最大值和最小值)也给出了交点。

这有一个你可以使用的 Rect 类型。它已经是 JavaScript。

https://dxr.mozilla.org/mozilla-beta/source/toolkit/modules/Geometry.jsm

<= 给出一个高度为 0 的矩形。对我的目的没有用。
2021-03-22 14:03:36
对于矩形 A(0,0,100,100) 和 B(100,100,100,100),此代码将返回 false。我认为应该是 <= 而不是 <
2021-03-27 14:03:36