As explained previously, the current algorithm does not handle collisions of multiple balls at the same time. I found a solution for a double collision, and I am pretty sure that there is no single solution for more complex cases using only conservation laws and the coefficient of restitution formula – but I still have to prove it. Of course there would be a solution modeling the actual physics of the collisions – a problem for another day.

### Double ball collision

..or more formally: elastic collision of three spheres in two dimensions

Ball 0 – with velocity \((v_0,w_0)\), hits at the same time ball 1 and ball 2 – that have velocities \((v_1, w_1)\) and \((v_2, w_2)\) respectively.

Projecting the velocity \((v_0,w_0)\) onto the lines connecting the center of ball 0 with the centers of balls 1 and 2 gives the velocity components \(q_{01}\) and \(q_{02}\). Projecting the velocity \((v_1,w_1)\) onto the line connecting the center of ball 0 with the center of ball 1 and onto its perpendicular through the center of ball 1 gives the velocity components \(q_1\) and \(p_1\). Doing the same thing for ball 2 gives the velocity components \(q_2\) and \(p_2\).

Here is the drawing:

As usual, balls are not spinning and there is no ball-ball friction, so the forces between balls are only along the lines connecting the center of ball 0 with the centers of balls 1 and 2. This means that the velocity components perpendicular to those lines are the same before and after the collision:

$$ p’_1 = p_1 $$

$$ p’_2 = o_2 $$

(indicating with a prime the velocities after the collision), whereas the velocity components along those lines are related by the coefficient of restitution formula:

$$ q’_{01} – q’_1 = c(q_1 – q_{01}) $$

$$ q’_{02} – q’_2 = c(q_2 – q_{02}) $$

Let’s not use trigonometry this time. The projection of a velocity onto the line connecting the center of two ball is the scalar product of the velocity with the unit vector pointing from one center to the other. For balls 0 and 1 this unit vector is:

$$ \left( \frac{x_{01}}{\sqrt{x_{01}^2 + y_{01}^2}}, \frac{y_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} \right)$$

where \(x_{01} = x_1 – x_0\) and \(y_{01}=y_1-y_0\), hence:

$$ q_1 = \frac{v_1x_{01} + w_1y_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} $$

$$ q_01 = \frac{v_0x_{01} + w_0y_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} $$

Similarly, the projection on the perpendicular of that line is the scalar product of the velocity with the perpendicular unit vector:

$$ \left( -\frac{y_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} , \frac{x_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} \right) $$

hence:

$$ p_1 = \frac{-v_1y_{01} + w_1x_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} $$

Replacing these values in the four initial equations gives:

$$ –v’_1y_{01} + w’_1x_{01} = -v_1y_{01} + w_1x_{01} $$

$$ –v’_2y_{02} + w’_2x_{02} = -v_2y_{02} + w_2x_{02} $$

$$ v’_0x_{01} + w’_0y_{01} – v’_1x_{01} – w’_1y_{01} = c(v_1x_{01} + w_1y_{01} - v_0x_{01} - w_0y_{01}) $$

$$ v’_0x_{02} + w’_0y_{02} – v’_1x_{02} – w’_2y_{02} = c(v_2x_{02} + w_2y_{02} - v_0x_{02} - w_0y_{02}) $$

The conservation of momentum gives two additional equations:

$$ m_0v’_0 + m_1v’_1 + m_2v’_2 = m_0v_0 + m_1v_1 + m_2v_2 $$

$$ m_0w’_0 + m_1w’_1 + m_2w’_2 = m_0w_0 + m_1w_1 + m_2w_2 $$

- where \(m_0\), \(m_1\) and \(m_2\) are the masses of the balls, resulting in a system of 6 linear equations for the 6 unknowns \(v’_0, w’_0, v’_1, w’_1, v’_2, w’_2\). Introducing new unknowns \(u_j\) defined as:

$$ u_0 = v’_0 – v_0,\quad u_1 = w’_0 – w_0,\quad u_2 = v’_1 – v_1,\quad u_3 = w’_1 – w_1,\quad u_4 = v’_2 – v_2,\quad u_5 = w’_2 – w_2 $$

the system becomes a bit simpler:

$$ x_{01} u_3 – y_{01} u_2 = 0 $$

$$ x_{02} u_5 – y_{02} u_4 = 0 $$

$$ x_{01} (u_0-u_2) + y_{01}(u_1-u_3) = B_{01} $$

$$ x_{02} (u_0-u_4) + y_{02}(u_1-u_5) = B_{02} $$

$$ m_0u_0 + m_1u_2 + m_2u_4 = 0 $$

$$ m_0u_1 + m_1u_3 + m_2u_5 = 0 $$

with

$$ B_{01} = (1+c)[x_{01}(v_1 – v_0) + y_{01}(w_1-w_0)] $$

$$ B_{02} = (1+c)[x_{02}(v_2 – v_0) + y_{02}(w_2-w_0)] $$

After quite a lot of substitutions and simplification the result is

$$ u_0 = v’_0 – v_0 = –\frac{1}{\Delta}[B_{01}m_1(x_{02}m_2P – x_{01}(m_0+m_2)S_{02}) + B_{02}m_2(x_{01}m_1P-x_{02}(m_0+m_1)S_{01})] $$

$$ u_1= w’_0 – w_0 = –\frac{1}{\Delta}[B_{01}m_1(y_{02}m_2P – y_{01}(m_0+m_2)S_{02}) + B_{02}m_2(y_{01}m_1P-y_{02}(m_0+m_1)S_{01})] $$

$$ u_2 = v’_1 – v_1 = \frac{x_{01}m_0}{\Delta}[B_{02}m_2P-B_{01}(m_0+m_2)S_{02})] $$

$$ u_3= w’_1 – w_1 = \frac{y_{01}m_0}{\Delta}[B_{02}m_2P-B_{01}(m_0+m_2)S_{02})] $$

$$ u_4 = v’_2 – v_2 = \frac{x_{02}m_0}{\Delta}[B_{01}m_1P-B_{02}(m_0+m_1)S_{01})] $$

$$ u_5 = w’_2 – w_2 = \frac{y_{02}m_0}{\Delta}[B_{01}m_1P-B_{02}(m_0+m_1)S_{01})] $$

with

$$ P = x_{01}x_{02}+y_{01}y_{02} $$

$$ S_{01} = x_{01}^2 + y_{01}^2 $$

$$ S_{02} = x_{02}^2 + y_{02}^2 $$

$$ \Delta = (m_0 + m_1)(m_0 + m_2) S_{01}S_{02}-m_1m_2P^2 $$

The corresponding code is:

/** * Updates the velocities of this ball and two other balls after a double collisions * with both balls at the exact same time * The coordinate of the balls must be at the collision point. * @param otherBall1 second colliding ball * @param otherBall2 third colliding ball * @param restitution coefficient of restitution for a ball-ball collision */ collide2(otherBall1: Ball, otherBall2: Ball, restitution: number) { var m0 = Math.pow(this.radius, 3); var m1 = Math.pow(otherBall1.radius, 3); var m2 = Math.pow(otherBall2.radius, 3); var x01 = otherBall1.x - this.x; var y01 = otherBall1.y - this.y; var x02 = otherBall2.x - this.x; var y02 = otherBall2.y - this.y; var p = x01 * x02 + y01 * y02; var s01 = x01 * x01 + y01 * y01; var s02 = x02 * x02 + y02 * y02; var delta = (m0 + m1) * (m0 + m2) * s01 * s02 - m1 * m2 * p * p; var v01 = otherBall1.v - this.v; var w01 = otherBall1.w - this.w; var b01 = (1 + restitution) * (x01 * v01 + y01 * w01); var v02 = otherBall2.v - this.v; var w02 = otherBall2.w - this.w; var b02 = (1 + restitution) * (x02 * v02 + y02 * w02); this.v = -(b01 * m1 * (x02 * m2 * p - x01 * (m0 + m2) * s02) + b02 * m2 * (x01 * m1 * p - x02 * (m0 + m1) * s01)) / delta + this.v; this.w = -(b01 * m1 * (y02 * m2 * p - y01 * (m0 + m2) * s02) + b02 * m2 * (y01 * m1 * p - y02 * (m0 + m1) * s01)) / delta + this.w; var r1 = m0 * (b02 * m2 * p - b01 * (m0 + m2) * s02) / delta; otherBall1.v = x01 * r1 + otherBall1.v; otherBall1.w = y01 * r1 + otherBall1.w; var r2 = m0 * (b01 * m1 * p - b02 * (m0 + m1) * s01) / delta; otherBall2.v = x02 * r2 + otherBall2.v; otherBall2.w = y02 * r2 + otherBall2.w; } // collide2

As a verification, when \(m_2 = 0\) the first four equations become:

$$ u_0 = v’_0 – v_0 = x_{01} \frac{m_1}{m_0+m_1} \frac{B_{01}}{S_{01}} $$

$$ u_1 = w’_0 – w_0 = y_{01} \frac{m_1}{m_0+m_1} \frac{B_{01}}{S_{01}} $$

$$ u_2 = v’_1 – v_1 = -x_{01} \frac{m_0}{m_0+m_1} \frac{B_{01}}{S_{01}} $$

$$ u_3 = w’_1 – w_1 = -y_{01} \frac{m_0}{m_0+m_1} \frac{B_{01}}{S_{01}} $$

if \(\alpha\) is the angle between the vector from ball 0 to ball 1 and the horizontal, then:

$$ \cos\alpha = \frac{x_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} $$

$$ \sin\alpha = \frac{y_{01}}{\sqrt{x_{01}^2 + y_{01}^2}} $$

hence

$$ \frac{B_{01}}{S_{01}} = -\frac{1+c}{\sqrt{x_{01}^2 + y_{01}^2}}[\cos\alpha(v_0 – v_1) + \sin\alpha(w_0-w_1)] $$

and the result is the same as in the two balls case.