Reflections in a wall:


So here's a formula for bouncing in a rectangular.

Let's assume the following, and only worry about the x coordinate:

So, if we were not in a box, the x position at time t would be:

If we just divided by xr and took the remainder, ie, mod by xr, we would restrict location of the ball to the box:

But this would not be bouncing off the right wall, just wrapping the path back to the left edge with the same slope.

What we really want is to reverse the motion from the right side when the ball goes off the right edge.

BUT, if we do that, then we really want to reverse the direction the second time we meet a right boundary - which is the same as hitting the left wall (x=0) from the right. The result of this is going in the same direction as the original path.

A clever trick is to think of the box as TWICE the width of the original box, with the left side following the original path, but the right side folded over, showing the reverse path.

So, here's the final math:

H(t) gives the final x coordinate.

This is not very hard to program in Excel, particularly if you use more than one column for the intermediate functions of t.

For those with a more algorithmic bent, this is an excellent example where thinking about a bigger problem (larger t) actually gives a simpler insight than simply thinking about what happens when t goes just over the boundary.

In this case, H(t) is the same as H after the ball hits the left and right side.

Perhaps it helps to think about what happens with x(t) if the top boundary is removed and we think of a ball bouncing in an infinite column.

And y works the same way, but the y folds are not the same size as the x folds since vx is not the same as vy.

PS - things are only a little more complicated if vx < 0.



// File:
// Date: Apr 30, 2016
// Author: Nicholas Duchon
// Purpose: step a line around a box
//    showing reflections

import java.util.Scanner;

public class BoxND {
   double x, y, vx, vy, bx, by;
   Scanner sn = new Scanner (;
   public BoxND () {
      System.out.print ("Enter box size, initial x, y and vx and vy: ");
      bx = sn.nextDouble ();
      by = sn.nextDouble ();
       x = sn.nextDouble ();
       y = sn.nextDouble ();
      vx = sn.nextDouble ();
      vy = sn.nextDouble ();
      sn.nextLine(); // eat end of line from this input
      while (menu());
      System.out.println (".. Bye");
   } // end no parameter constructor
   public boolean menu () {
      System.out.print ("enter stop time and step  as doubles or q to quit: ");
      String line = sn.nextLine();
      if (line.trim().startsWith ("q")) return false;
      double t = 0, step = 1.0;
      Scanner st = new Scanner (line);
      try {
         t = st.nextDouble ();
         step = st.nextDouble ();
      catch (NumberFormatException e) {return true;}
      int count = 0;
      for (double tn = 0; tn < t; tn+= step, count++) {
         System.out.printf ("%7.1f %7.1f %7.1f\n", tn, getX (tn), getY (tn));
         if ((count % 5) == 4) System.out.println ();
      } // end for
//       System.out.printf ("f(%5.1f) = (%4.1f, %4.1f)\n", tn, getX (tn), getY (tn));
      return true;
} // end method menu
   public double getX (double t) {
      double xn0 = x / bx;
      double vnx = vx / bx;
      double xnt = xn0 + vnx * t;
      xnt = xnt % 2;
      if (xnt < 0) xnt += 2;
      if (xnt > 1) xnt = 2 - xnt;
      return xnt * bx;
} //end method getX
   public double getY (double t) {
      double yn0 = y / by;
      double vny = vy / by;
      double ynt = yn0 + vny * t;
      ynt = ynt % 2;
      if (ynt < 0) ynt += 2;
      if (ynt > 1) ynt = 2 - ynt;
      return ynt * by;
} // end method getY
   public static void main (String args []) {
      BoxND b = new BoxND ();
} //end main
} // end class BoxND

Oct 15, 2016