How do we handle two dimensional collisions? Do we need to delve into trigonometry? So far it’s been quite straightforward but the step into two dimensions seems daunting at first.
Fortunately we can use two concepts that we have used before to assist us here: vectors and frames of reference. With a few more simple changes to our frame of reference we can just continue to use the old 1D version of the collision calculation!
Here are the steps…
Move the origin
Just as there are no absolute frames of reference with respect to velocity, there are no absolute frames of reference with respect to position. So we are free to redefine where the origin (0, 0) point of our sketch is. We have already changed the FoR such that ball2 is at rest. Now we are going to change the FoR again so that ball2 is located at the origin.
Again, we just need to subtract the position vector of ball2 from each of the balls. Now we have a FoR with ball2 at the origin.
Rotate
The next thing to do is rotate the FoR so that the point of collision is on the x-axis. Because ball2 is now located at the origin and we applied the same transformation to ball1, we can now use ball1’s position vector to get the angle we need to rotate.
Think of this change to the FoR as just tilting your head to the side. There are a few important things to remember about this particular change:
- Ball 2 is not affected because it is located at the origin and is at rest.
- We need to rotate both the position and velocity vectors of ball 1 to make them correct in this new FoR.
Having done that, we now have a FoR that looks like this:
It that it?
Almost. We now have a frame of reference where one ball is at rest (ball 2) and the other ball is colliding with it on the x-axis. Almost perfect. The only problem is that ball 1 is moving in two dimensions – i.e. it has both an x-velocity and a y-velocity. Fortunately for us, because the point of collision is on the x-axis, the impulse is only transmitted to ball2 along this axis. This means we can just use the x-velocity of ball1 as the input to our elasticCollision() function and we will achieve the desired result. So we are ready to handle the collision, and then revert back to the original FoR. We need to do that last part carefully, as the order of transformations is important. The beauty of this is that we can do it all in the handleCollision() function. Here it is…
The Code
function handleCollision(ball1, ball2) {
// Change to a new FoR in which ball2 is at rest
var vel_adj = ball2.vel.copy()
ball1.vel.sub(vel_adj)
ball2.vel.sub(vel_adj)
// Now change to a new FoR in which ball2 is at the origin
var pos_adj = ball2.pos.copy()
ball1.pos.sub(pos_adj)
ball2.pos.sub(pos_adj)
// Rotate frame of reference so the point of collision is on x axis and > 0
var angle_adj = ball1.pos.heading()
ball1.pos.rotate(-angle_adj)
ball1.vel.rotate(-angle_adj)
// Handle the collision in the new FoR
let [v1f, v2f] = elastic_collision(ball1.mass, ball2.mass, ball1.vel.x);
ball1.vel.x = v1f;
ball2.vel.x = v2f;
// Remove overlap
ball1.pos.x = ball2.r + ball1.r + 0.01
// Switch back to the original FoR
ball1.pos.rotate(angle_adj)
ball1.vel.rotate(angle_adj)
ball2.vel.rotate(angle_adj)
ball1.pos.add(pos_adj)
ball2.pos.add(pos_adj)
ball1.vel.add(vel_adj)
ball2.vel.add(vel_adj)
}
What are the changes?
- Lines 7, 8 & 9 contain the code to change the frame of reference so that ball2 is at the origin.
- Lines 11, 12 & 13 contain the code to rotate frame of reference so the point of collision is on x axis (and also greater than zero – this is useful shortly).
- Lines 16, 17 & 18 are unchanged – still using the original 1D collision code!
- Line 21 removes any overlap of the balls by taking advantage of the fact that ball2 is on the origin and ball1 is on the x-axis. It simply moves ball1 along the x-axis so that it is no longer intersecting ball2. It just has to move it to a position that is the sum of the radii of the balls plus a little bit (0.01). This is more elegant than the ugly code we used for this job in the last chapter.
- Lines 23-29 just switch us back to our original frame of reference. You might notice that the code to revert to the original FoR requires 7 lines, but the code to change the FoR in the first place required only 6 lines. The reason for the extra line of code (line 25) is that before the collision ball2 had zero velocity so we did not need to rotate its velocity vector, but after the collision ball2 now has velocity so we need to do the rotation on it to get back to the original FoR.
The Sketch
Now we have a fully working sketch with colliding balls and demonstrating the conservation of energy and momentum…
You can see that after each collision the total amount of energy in the system is unchanged, as is the total momentum.