【问题标题】:How to find collision center of two rectangles? Rects can be rotated如何找到两个矩形的碰撞中心?矩形可以旋转
【发布时间】:2012-09-23 18:48:30
【问题描述】:

我刚刚使用 SAT 和this article 实现了碰撞检测作为我的实现的参考。检测按预期工作,但我需要知道两个矩形在哪里发生碰撞。

我需要找到交叉点的中心,即上图中的黑点(但我也没有交叉点区域)。我找到了一些关于此的文章,但它们都涉及避免重叠或某种速度,我不需要这个。

关于矩形的信息是代表它们的四个点,upper rightupper leftlower rightlower left 坐标。我正在尝试找到一种算法,可以为我提供这些点的交集。

我只需要在上面放一张图片。就像两辆车相撞一样,所以我将图像放在碰撞中心的顶部。有什么想法吗?

【问题讨论】:

  • 获得交点中心的一种可能方法是构造 Minkowski 差并查看点 (0, 0)。这适用于任意多边形,但对于您的问题可能过于复杂。看看这个page + interactive example。 (具体关于 Minkowski 差异的部分。)抱歉,我无法提供具体帮助,我现在时间紧迫。
  • 如果我理解正确的话。 Minkowski 差分(或 GJK 算法)会告诉我多边形是否正在碰撞。它在哪里告诉我碰撞点?

标签: algorithm math polygon


【解决方案1】:

这很棘手,因为不规则多边形没有定义的中心。由于您的多边形(在矩形的情况下)保证是凸的,您可能会找到包含碰撞的多边形的角(可以包括原始形状的角或边缘的交叉点)并将它们平均得到 . .. 某物。它可能会模糊地接近您期望的“中心”位置,并且对于正多边形它可能会完全匹配,但它在数学上是否意味着任何东西有点不同。

我一直在数学上摆弄并提出以下问题,它解决了点出现和消失时的平滑问题(当碰撞框的移动导致矩形变为三角形时会发生这种情况,反之亦然)。如果没有这点额外,添加和删除角点会导致质心跳跃。

Here, take this fooplot.

该图显示了 2 个矩形,R 和 B(红色和蓝色)。交叉口扫过一个区域 G(绿色)。未加权和加权中心(均为紫色)通过以下方法计算:

(0.225, -0.45):   Average of corners of G
(0.2077, -0.473): Average of weighted corners of G

多边形的加权角定义为角的坐标,由角的角度的正弦加权。

此多边形有两个 90 度角、一个 59.03 度角和一个 120.96 度角。 (两个非直角的正弦相同,sin(Ɵ) = 0.8574929...

因此,加权中心的坐标为:

( (sin(Ɵ) * (0.3 + 0.6) + 1 - 1)   / (2 + 2 * sin(Ɵ)),  // x
  (sin(Ɵ) * (1.3 - 1.6) + 0 - 1.5) / (2 + 2 * sin(Ɵ)) ) // y
= (0.2077, -0.473)

对于提供的示例,差异不是很明显,但如果 4gon 更接近 3gon,则会有很大的偏差。

【讨论】:

  • 按照我的阅读方式,他要求的是整个区域,而不仅仅是中心点。如果是这种情况,第一个插图会产生误导。
  • >我需要找到交叉点的中心,上图中的黑点。
  • 啊,那我误解了问题。
  • 实际上我需要中心点(或靠近它的东西),但我没有交叉区域。目前我只有每个矩形的四个点,我知道它们是否碰撞。
  • 做一些数学运算来找出相交点,然后用一些逻辑来找出你得到的哪些点是相交区域的边界。
【解决方案2】:

如果您不需要知道该区域的实际坐标,您可以制作两个框架为矩形的CALayers,并使用一个来遮盖另一个。然后,如果您在被遮罩的图像中设置图像,它只会显示在它们重叠的区域。

【讨论】:

  • 有什么方法可以确定重叠区域的中心,以便告诉CALayer把图片放在哪里?
【解决方案3】:

您需要使用线对线相交方程/算法对框的边界进行相交。

http://en.wikipedia.org/wiki/Line-line_intersection

一旦你有了交叉点,你可能会接受这些点的平均值或给定特定方向的中心。中间的问题有点含糊。

编辑:除此之外,您还需要确定两个矩形中的任何一个的角是否在另一个内部(这应该很容易计算,即使是从交叉点)。这应该在计算“平均”中心点时与交点一起添加。

【讨论】:

    【解决方案4】:

    还有另一种方法:通过采样点找到碰撞区域的质心。

    创建以下函数:

    bool IsPointInsideRectangle(Rectangle r, Point p);
    

    定义一个搜索矩形为:

    TopLeft = (MIN(x), MAX(y))
    TopRight = (MAX(x), MAX(y))
    LowerLeft = (MIN(x), MIN(y))
    LowerRight = (MAX(x), MIN(y))
    

    其中 x 和 y 是两个矩形的坐标。

    您现在将定义一个像网格一样划分搜索区域的步骤。我建议你使用 AVG(W,H)/2 ,其中 W 和 H 是搜索区域的宽度和高度。

    然后,如果每个网格点都在碰撞区域内,则迭代网格点:

    IsPointInsideRectangle(rectangle1, point) AND IsPointInsideRectangle(rectangle2, point) 
    

    定义:

    Xi : the ith partition of the mesh in X axis.
    CXi: the count of mesh points that are inside the collision area for Xi.
    

    然后:

    你也可以对 Y 做同样的事情。这是这种方法的一个说明性示例:

    【讨论】:

    • 这似乎是迄今为止最好的方式,因为我不需要太多的精确度。我会尝试并告诉你。
    • 如果第一步的值没有找到任何点,我只需要添加一点尝试:if (points == 0) searchAgainWithStep(1)
    • 我使用 PNPOLY 作为 IsPointInsideRectangle 函数:ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
    • PNPOLY 的东西很好。很高兴你的问题得到了解决,这是一个有趣的问题!
    • 您的解释和绘图真的很有帮助。非常感谢。我希望我能投票更多次你的答案:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多