Home > front end >  3d collision formula based on xyz
3d collision formula based on xyz

Time:12-07

Here is the problem. We have two points (spheres) in xyz, with this info:

1- x,y,z => The center of the object is currently located at

2- r => The collision radius of the object

3- Vx, Vy, Vz => object is traveling along the vector. If that vector is (0,0,0), the object is stationary.

Note: The radii and positions are in meters and velocities are measured in meters per second.

Question: For each test, output a single line containing the time (in seconds) since the start of the test at which the two objects will first collide. If they never collide, print No collision instead.

I want to know about the formula of calculation this time. Any idea would be appreciated.

Examples:

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

CodePudding user response:

To simplify problem, let us use Halileo's principle. Consider the first object as base point, so the second objects moves relative to it.

Put the first object position in coordinate origin.

Subtract the first object initial coordinates from the second one coordinates, do the same for velocity components

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

Now we have second center coordinates against time

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

and squared distance to origin:

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

and we need to calculate when dd becomes equal to squared radius sum (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

Solve this quadratic equation for t, get 0,1 or 2 solutions.

Case of 0 solutions - no collision
Case of 1 solution with positive t - moment of touching
Case of two solutions - get smaller positive t for the moment of collision.

Negative values of t mean collision "in the past", before the start of the test

Quick test in 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)
  • Related