At the point of collision, momentum, angular momentum and energy are preserved. Set m1, m2 the masses of the disks, p1=(p1x,p1y), p2=(p2x,p2y) the positions of the centers of the disks at collition time, u1, u2 the velocities before and v1,v2 the velocities after collision. Then the conservation laws demand that
0 = m1*(u1-v1)+m2*(u2-v2)
0 = m1*cross(p1,u1-v1)+m2*cross(p2,u2-v2)
0 = m1*dot(u1-v1,u1+v1)+m2*dot(u2-v2,u2+v2)
Eliminate u2-v2 using the first equation
0 = m1*cross(p1-p2,u1-v1)
0 = m1*dot(u1-v1,u1+v1-u2-v2)
The first tells us that (u1-v1) and thus (u2-v2) is a multiple of (p1-p2), the impulse exchange is in the normal or radial direction, no tangential interaction. Conservation of impulse and energy now leads to a interaction constant a
so that
u1-v1 = m2*a*(p1-p2)
u2-v2 = m1*a*(p2-p1)
0 = dot(m2*a*(p1-p2), 2*u1-m2*a*(p1-p2)-2*u2+m1*a*(p2-p1))
resulting in a condition for the non-zero interaction term a
2 * dot(p1-p2, u1-u2) = (m1+m2) * dot(p1-p2,p1-p2) * a
which can now be solved using the fraction
b = dot(p1-p2, u1-u2) / dot(p1-p2, p1-p2)
as
a = 2/(m1+m2) * b
v1 = u1 - 2 * m2/(m1+m2) * b * (p1-p2)
v2 = u2 - 2 * m1/(m1+m2) * b * (p2-p1)
To get the second disk stationary, set u2=0 and its mass m2 to be very large or infinite, then the second formula says v2=u2=0 and the first
v1 = u1 - 2 * dot(p1-p2, u1) / dot(p1-p2, p1-p2) * (p1-p2)
that is, v1 is the reflection of u1 on the plane that has (p1-p2) as its normal. Note that the point of collision is characterized by norm(p1-p2)=r1+r2
or
dot(p1-p2, p1-p2) = (r1+r2)^2
so that the denominator is already known from collision detection.
Per your code, oc{x,y}
contains the center of the fixed disk or orb, sc{x,y}
the center and {vx,vy}
the velocity of the moving disk.
Compute dc={sc.x-oc.x, sc.y-oc.y}
and dist2=dc.x*dc.x+dc.y*dc.y
1.a Check that sqrt(dist2)
is sufficiently close to sc.radius+oc.radius
. Common lore says that comparing the squares is more efficient. Fine-tune the location of the intersection point if dist2 is too small.
Compute dot = dc.x*vx+dcy*vy
and dot = dot/dist2
Update vx = vx - 2*dot*dc.x
, vy = vy - 2*dot*dc.y
The special cases are contained inside these formulas, e.g., for dc.y==0
, that is, oc.y==sc.y
one gets dot=vx/dc.x
, so that vx=-vx
, vy=vy
results.