基于xyz的3d碰撞公式

3d collision formula based on xyz

问题来了。我们在 xyz 中有两个点(球体),信息如下:

1- x,y,z => 对象的中心当前位于

2- r => 物体的碰撞半径

3- Vx, Vy, Vz => 物体沿着向量行进。如果该向量是 (0,0,0),则对象是静止的。

注意:半径和位置以米为单位,速度以米/秒为单位。

问题:对于每个测试,输出一行包含自测试开始以来两个对象首次碰撞的时间(以秒为单位)。如果它们从未发生碰撞,则改为打印 No collision。

我想知道这次的计算公式。任何想法将不胜感激。

示例:

1-

xyz(1): -7 5 0
v(1): -1 0 3
r(1): 3

xyz(2): 10 7 -6
v(2): -2 0 4
r(2): 6


t: 8.628 // this is the answer
2-

xyz(1): 10 3 -10
v(1): -9 3 -8
r(1): 5

xyz(2): 2 0 0
v(2): 6
r(2): -4 3 -10


t: 0.492 // this is the answer

为了简化问题,让我们使用哈利略原理。将第一个对象作为基点,因此第二个对象相对于它移动。

将第一个对象位置放在坐标原点。

从第二个坐标减去第一个对象初始坐标,对速度分量做同样的事情

x2_0 = x2_0 - x1_0  (same for y,z)
Vx2 = Vx2 - Vx1  (same for y,z)

现在我们有了相对于时间的第二个中心坐标

x = x2_0 + Vx2 * t
y = y2_0 + Vy2 * t
z = z2_0 + Vz2 * t

和到原点的平方距离:

dd = x*x + y*y + z*z =
     (x2_0 + Vx2 * t)^2 + ...  = 
     x2_0^2 + 2*x2_0*Vx2*t + Vx2^2*t^2 + ... 

我们需要计算什么时候dd等于半径平方和(r1+r2)^2

   t^2 * (Vx2^2+Vy2^2+Vz2^2) + t*(2*x2_0*Vx2+2*y2_0*Vy2+2*z2_0*Vz2) + 
         x2_0^2 + y2_0^2 + y2_0^2 - (r1+r2)^2 = 0

求解此二次方程 t,得到 0,1 或 2 个解。

案例 0 个解决方案 - 无碰撞
1 个解决方案的案例 t - 触摸时刻
两种解决方案的情况 - 在碰撞时刻获得更小的正值 t

t 的负值表示碰撞“过去”,在测试开始之前

快速测试 Python (ideone)

from math import sqrt, isclose

def collisiontime(x1,y1,z1,vx1,vy1,vz1,r1,  x2,y2,z2,vx2,vy2,vz2,r2):
    x2 -= x1
    y2 -= y1
    z2 -= z1
    vx2 -= vx1
    vy2 -= vy1
    vz2 -= vz1
    a = vx2**2 + vy2**2 + vz2**2
    b = 2*x2*vx2 + 2*y2*vy2 + 2*z2*vz2
    c = x2**2 + y2**2 + z2**2 - (r1+r2)**2
    D = b**2-4*a*c
    if D < 0:
        return None
    if isclose(D, 0):
        return -b/2/a
    return (-b - sqrt(D)) / 2 /a, (-b + sqrt(D)) / 2 /a

print(collisiontime(0, 0, 0, 2, 0, 0, 2, 25, 0, 0, -3, 0, 0, 3)) #    1=>   <=2
print(collisiontime(0, 0, 0, 2, 0, 0, 2, 25, 5, 0, 1, 0, 0, 3))  #    1==>   2=>  chase with touching

print(collisiontime(-7, 5, 0,-1, 0, 3, 3,  10, 7, -6, -2, 0, 4, 6))
print(collisiontime(10, 3, -10,-9, 3, -8,5,  2, 0, 0, -4, 3, -10, 6))


(4.0, 6.0) 
25.0
(8.627718676730986, 14.372281323269014)
(0.4917797757201004, 3.646151258762658)