【问题标题】:Line intersection with AABB Rectangle?与AABB矩形线相交?
【发布时间】:2011-04-14 08:40:05
【问题描述】:

最好不使用任何类型的循环,因为这将在游戏中使用。

我希望将一条线与一个任意大小的矩形相交。 但我也希望返回交点。

有可能,我已经做了一些谷歌搜索,但仍然没有解决。

使用 (x1,y1,x2,y2) 定义线。 矩形也有这两个点。

【问题讨论】:

  • 从一个更简单的问题开始。你知道如何将一条无限线与另一条无限线相交吗?
  • 并不是我认为你用苏格拉底的方法学得更好;我明白不是每个人都这样做。相反,我试图衡量您现有知识的水平。如果您不知道如何使两条线相交,那么您可能必须先学习这一点,然后再尝试与更复杂的几何图形相交。
  • 我根本不同意。有时,最好只用代码实现别人的解决方案,验证它是否有效,然后忘记它,而不是学习解决方案背后的理论并自己实现它。你学的不多,但不是每个人都想或需要学习一切。

标签: c# line collision-detection intersection


【解决方案1】:

我建议简单地对构成矩形的每个线段(边缘)进行线段线段交叉检查。这是我很久以前写的一个线段相交检测算法,是从我的一个旧 XNA 项目中挖掘出来的:

// a1 is line1 start, a2 is line1 end, b1 is line2 start, b2 is line2 end
static bool Intersects(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, out Vector2 intersection)
{
    intersection = Vector2.Zero;

    Vector2 b = a2 - a1;
    Vector2 d = b2 - b1;
    float bDotDPerp = b.X * d.Y - b.Y * d.X;

    // if b dot d == 0, it means the lines are parallel so have infinite intersection points
    if (bDotDPerp == 0)
        return false;

    Vector2 c = b1 - a1;
    float t = (c.X * d.Y - c.Y * d.X) / bDotDPerp;
    if (t < 0 || t > 1)
        return false;

    float u = (c.X * b.Y - c.Y * b.X) / bDotDPerp;
    if (u < 0 || u > 1)
        return false;

    intersection = a1 + t * b;

    return true;
}

我将把每个边输入到上述方法中,并将结果作为练习留给读者:)


一年后编辑,现在我上大学并完成了图形课程:

查看Cohen–Sutherland algorithm 以在您有大量线且大多数线不与矩形相交时有效地执行此操作。它使用 9 段网格,您将线的每个端点放置在所述网格的区域中:

使用这个我们可以判断是否不会有任何线交叉:

例如,CD 不会与矩形相交(在第一张图片中以红色显示),因为CD 都在顶行,AB 也不会。对于线可能与矩形相交的那些,我们必须尝试线-线相交。

它们对部分进行编号/标记的方式允许我们简单地执行x AND y != 0(其中xy 是每个线端点的部分的标签)来确定是否不会有交叉点.

使用这种方法意味着我们可以减少很多很多的线交叉点,从而大大加快整个过程。

【讨论】:

  • 这很容易做到。非常感谢。
  • 在上面的代码示例中,这些实际上是叉积,而不是点积。
  • Cohen-Sutherland 算法似乎是关于裁剪和寻找交叉点,而不是有任何交叉点 - 所以这肯定会更慢吗?
  • 嗯,Cohen-Sutherland 算法假设有限空间被划分为 9 个相等的区域(或 3d 中的 27 个区域)。当你的空间是无限的时会发生什么?
  • @MattEsch:我猜你只是让外部 8 (26) 个区域无限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多