Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 任意大小凸多边形间碰撞检测算法_C++_Algorithm_2d_Collision Detection - Fatal编程技术网

C++ 任意大小凸多边形间碰撞检测算法

C++ 任意大小凸多边形间碰撞检测算法,c++,algorithm,2d,collision-detection,C++,Algorithm,2d,Collision Detection,我正在研究一个小行星克隆。一切都是2D,用C++编写。 对于小行星,我生成随机的N边多边形。我保证它们是凸的。然后我旋转它们,给它们一个旋转速度,让它们在太空中飞行。这一切都很有效,而且非常漂亮 对于碰撞,我使用的是我自己想到的算法。这可能是个坏主意,如果情况紧急,我可能会放弃这一切,在互联网上找到一个教程 我已经编写并实现了所有内容,碰撞检测工作正常。。。。大多数时候。当屏幕上出现明显的碰撞时,它会随机失效,有时在没有任何东西接触时,它会指示碰撞。要么我的实现出了问题,要么我的算法很糟糕。由于

我正在研究一个小行星克隆。一切都是2D,用C++编写。

对于小行星,我生成随机的N边多边形。我保证它们是凸的。然后我旋转它们,给它们一个旋转速度,让它们在太空中飞行。这一切都很有效,而且非常漂亮

对于碰撞,我使用的是我自己想到的算法。这可能是个坏主意,如果情况紧急,我可能会放弃这一切,在互联网上找到一个教程

我已经编写并实现了所有内容,碰撞检测工作正常。。。。大多数时候。当屏幕上出现明显的碰撞时,它会随机失效,有时在没有任何东西接触时,它会指示碰撞。要么我的实现出了问题,要么我的算法很糟糕。由于我的实现的大小/范围(在多个源文件上),我不想打扰您,只想有人检查我的算法是否正确。在那一点上,我可以进行一次大的虫子搜寻

算法: 对于每个小行星,我有一个函数,输出绘制小行星时每个顶点的位置。对于每一对相邻顶点,我为它们所在的直线生成公式,
y=mx+b
format。然后我从飞船的一个顶点开始,测试那个点,看它是否在小行星内部。我首先插入点的X坐标,并将输出与实际的Y值进行比较。这告诉我点是在直线上方还是下方。然后我对小行星的中心做同样的处理,以确定哪一半的线被认为是小行星的“内部”。然后对每对顶点重复上述步骤。如果我找到一条线,我的点不在小行星中心的同一侧,我知道没有碰撞,并且该点退出检测。因为我的飞船上有3个点,所以我必须测试下一个点。如果所有3个点都提前退出,那么船上的任何点都不会发生碰撞,我们就完成了。如果任何点在所有边上都被小行星所组成的线所约束,则该点位于小行星内部,并设置碰撞标志

我发现这个算法有两个问题:

  • 它不适用于凹多边形,并且
  • 它在坡度未定义的边缘情况下存在问题
  • 我已经确保所有多边形都是凸的,并且已经编写了代码来处理未定义的坡度问题(如果我们除以
    0
    ,doubles应该返回
    NAN
    ,所以测试起来非常简单)


    那么,这是否可行呢?

    这个问题的标准解决方案是使用分离轴定理(SAT)。给定两个凸多边形A和B,算法基本如下:

    for each normal N of the edges of A and B
        intervalA = [min, max] of projecting A on N
        intervalB = [min, max] of projecting B on N
        if intervalA doesn't overlap intervalB
            return did not collide
    return collided
    

    我做了一些类似于计算多边形交点的事情,即查找顶点是否位于给定多边形内

    您的算法是正确的,并且确实不适用于凹多边形。在接近无穷大的坡度处,您选择的线表示也有问题。我选择使用两个向量,一个用于直线方向,另一个用于直线上的参考点。从这些,我可以很容易地导出一个参数化的直线方程,并以各种方式使用它来找到与其他形状的交点

    P = S +  t * D
    
    给定上述关系,直线的任何点p都可以通过其在直线上的坐标t来表示,其中S是参考点,D是方向向量

    由于方向,此表示法可以轻松定义平面的哪些部分是正的,哪些部分是负的(即线的上方和下方)。现在,平面的任何区域都可以定义为多条直线的负或正子平面的交点。因此,您的“多边形中的点”算法可以稍微更改为使用该表示法,添加了所有方向指向顺时针的约束,并测试所有直线的负子平面中的点(因此您不再需要多边形的中心)

    我使用的计算点的边wrt的公式如下:

    (xs - xp) * yd - (ys - yp) * xd
    
    当点p接近S时,此处会出现坡度问题

    可以使用边顶点计算该表示,但为了获得正确的子平面,必须将多边形中的顶点保持压缩顺序


    对于凹多边形,问题有点复杂:简单地说,您必须测试点是否位于两条连续凸边之间。这可以通过检查投影到边缘上的点的坐标来实现,并确保其位于
    0
    长度(边缘)
    之间(假设方向已标准化)。请注意,它归结为检查点是否属于多边形中的三角形。

    我将小行星分解为多个三角形,或者实际使用(随机)三角形构建小行星。所有三角形都以相同的速度、相同的方向移动,以确保小行星保持完整。为了检测碰撞,它将是一个更简单的三角形相交计算,并添加一些优化,以避免两个由n和m个三角形组成的小行星的
    O(n*m)
    复杂性。而且,这将允许凹形和凸形。(三角形可能重叠,这可能会使事情变得更容易)在我开始之前,我实际上是在阅读SAT,因为它似乎是我想要的,但我不能完全围绕着它。你的回答稍微简化了我脑海中的事情,但我必须问:我以为如果所有间隔重叠,就只有碰撞?比如,如果我们找到一个没有重叠的间隔,我们就知道没有碰撞?因为我的小行星一直在旋转,所以我很可能有接近无穷大的斜率。我没有想到会有这么高的数字,我能想象得到