GJK算法

GJK算法最初用来求三维空间中凸多面体的距离(即最近距离),也因此经常用来做碰撞检测(距离是否为0)。后被推广到n维空间中求凸包之间的距离,此处用来求二维平面上2个凸多边形的距离。
    GJK算法首先要解决计算Minkowski和的问题。所谓Minkowski和,指A、B两个集合,令A+B={x+y,其中x属于A,y属于B}即二者的Minkowski和。类似的可以定义负集与Minkowski差。
    若A、B为凸多边形,顶点个数分别是n、m,则他们的Minkowski和一定是凸多边形且至多有n+m个顶点。

GJK算法


     左上为多边形A、B,假设黑点为原点,三个图分别表示-B、A+B与A-B。A、B之间的点对距离即||x - y||,其中x属于A,y属于B;而A、B之间的距离就是||x-y||的最小值。因此,A、B之间的距离就是其Minkowski差A-B中的最小元素,这个最小指的是模最小,实际上就是距离原点的距离。因此,2个凸多边形的距离转化为点到凸多边形的距离,点指的是原点,凸多边形指的是原题中的2个凸包的Minkowski差。

    Minkowski和的算法如下,将A、B的边按逆时针方向拆成向量(顺时针实际上也可以),如上图可以得到6个向量。将这些向量按极角排序,然后依次首尾相连即可得到凸包。该算法找自英文维基,感谢谷歌,感谢CCTV(关它P事)。

    上述算法只是得到了和的形状与相对位置(因为首尾相连时出发的基点是原点),实际上该凸包还需做一个平移才能得到正确的坐标。如果排序时极角是取0~360度范围(NOTE:不必显示的求出极角,用先象限后叉积的方法排序),则求出A、B各自的最下最左点,将其坐标相加作为出发的基点即可。

    求出Minkowski差之后(求差与求和本质是一样的),剩下的就是求点到凸多边形的距离,这个问题又转化为求点到边的距离。一个凸多边形有n条边,点到这n条边的距离的最小值就是点到凸多边形的距离。而且,点到边的距离是具有确定单调性的,因此运气好的话不需要求出所有边的距离,只需扫描到极小值即可。点到边的距离也就是点到线段的距离,利用叉积计算、点积进行判断,很容易求得。

    上述算法其实不是GJK算法,因为所求为凸多边形,而GJK算法可以用来求曲线凸包之间的距离(此情况下是一个数值逼近过程)。简单描述一下GJK的迭代过程,除了初始情况下,每一步迭代时均已求得凸包边缘上的3个点构成一个三角形Tk,然后求指定点p距离Tk最近的点,记作q,再将凸包投影到pq。qp方向上最远的投影点所对应的凸包上的点记作w,最后将Tk的3个点舍去1个,然后加上w形成新的Tk+1。最开始的3个点哪里来的?似乎可以随便选边缘上的3个点,最后应该可能也许大概一定可以迭代到结果,只是影响迭代次数而已。

    上述GJK算法来自《计算机图形学几何工具算法详解》中译本,此书的某些算法有问题,可能是翻译的问题。

   用GJK算法的Minkowski和可以解决POJ3608。凸多边形的距离也可以使用旋转卡壳法解决,但GJK算法应该更容易实现一些。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GJK算法(Gilbert-Johnson-Keerthi算法)是一种用于求解凸体相交的算法,其用途广泛应用在物理引擎、碰撞检测和计算机图形学等领域。 GJK算法的基本思想是通过迭代逼近的方式,在高维空间中找到两个凸体是否相交的最近点对,从而确定它们是否相交。具体来说,GJK算法分为三个主要步骤: 1. 初始化:选择两个初始点,一个位于第一个凸体上,一个位于第二个凸体上。这两个点可以是凸体的顶点、边界上的任意一点。 2. 迭代逼近:根据Minkowski差集(两个凸体的差集)形成的新凸体,找到离原点最近的点。该最近点必然位于Minkowski差集的边界上,可以通过求解凸包或者线段相交等方法来寻找。 3. 更新凸体:如果最近点距离原点足够小,说明两个凸体相交;否则,将最近点加入到Minkowski差集,进行下一轮迭代逼近。 由于GJK算法通过在高维空间中进行求解,虽然只需要两个凸体的形状信息,但能够得到相交的最近点对,进而支持接触深度、碰撞法向量等额外的信息。此外,GJK算法具有高效、可扩展性好等优点,因此被广泛应用于各种实时计算几何问题中。 总之,GJK算法是一种高效的求解凸体相交的算法,通过迭代逼近的方式找到相交的最近点对,其具有应用广泛的优势,可用于物理引擎、碰撞检测和计算机图形学等领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值