返回
探索碰撞检测的奥秘:GJK 算法详解
见解分享
2024-01-26 23:34:51
碰撞检测:GJK 算法——2D
引言
碰撞检测是计算机图形学和游戏开发中的基石,它使虚拟世界中的物体能够逼真地相互作用。在本文中,我们将深入探讨 GJK(Gilbert-Johnson-Keerthi)算法,这是一种广泛用于狭义相交检测的强大算法。我们将重点关注 GJK 算法的二维版本,并通过 Python 实现和实际示例来加深理解。
GJK 算法简介
GJK 算法是一种几何算法,用于确定两个凸几何体的相交情况。它通过迭代方式逐步逼近相交点,最终收敛到最接近点对。该算法利用闵可夫斯基和点差的概念,在凸几何体之间构建闵可夫斯基和集,并寻找该和集中的支持点。
GJK 算法步骤
GJK 算法的基本步骤如下:
- 初始化两个凸几何体的支持点集合。
- 计算闵可夫斯基和集的支持点。
- 如果支持点在原点内,则说明两个几何体相交。
- 否则,将新的支持点添加到支持点集合中,并返回步骤 2。
- 重复步骤 2-4,直到达到最大迭代次数或收敛到最近点对。
Python 实现
以下是用 Python 实现的二维 GJK 算法:
import math
def gjk_2d(geometry1, geometry2, max_iterations=100):
"""
GJK 算法的二维实现。
参数:
geometry1: 凸几何体 1
geometry2: 凸几何体 2
max_iterations: 最大迭代次数
返回值:
True 如果几何体相交,否则为 False
"""
# 初始化支持点集合
support_points1 = [geometry1.support_point(direction) for direction in [0, math.pi/2]]
support_points2 = [geometry2.support_point(direction) for direction in [0, math.pi/2]]
for _ in range(max_iterations):
# 计算闵可夫斯基和集的支持点
support_point = support_points1[0] - support_points2[0]
# 检查支持点是否在原点内
if support_point.dot(support_point) <= 1e-6:
return True
# 否则,更新支持点集合
direction = support_point.normalized()
support_points1.append(geometry1.support_point(direction))
support_points2.append(geometry2.support_point(-direction))
return False
示例
为了展示 GJK 算法的实际应用,让我们考虑以下两个示例:
示例 1:两个相交的圆
from geometry import Circle
circle1 = Circle(radius=1, center=(0, 0))
circle2 = Circle(radius=1, center=(1, 0))
if gjk_2d(circle1, circle2):
print("圆 1 和圆 2 相交")
else:
print("圆 1 和圆 2 不相交")
输出:
圆 1 和圆 2 相交
示例 2:不相交的矩形和圆
from geometry import Rectangle, Circle
rectangle = Rectangle(width=2, height=1, center=(0, 0))
circle = Circle(radius=1, center=(2, 0))
if gjk_2d(rectangle, circle):
print("矩形和圆相交")
else:
print("矩形和圆不相交")
输出:
矩形和圆不相交