// Name: Anita Blake Partner: Ted Forrester // ID: 014916 ID: 642708 // Sec: Yan T 2:30 Sec: Artemov R 1:25 // Date: March 30, 2000 // Project 5: Following the Bouncing Ball import java.text.DecimalFormat; import java.awt.*; // a Molecule moving around in a World class Molecule { double mass; // mass double px, py; // (px,py) = position of the center double vx, vy; // (vx,vy) = velocity double radius; // radius Color color; // color World world; // World where the molecule "lives" // create a molecule of color c, mass m, radius r, world w; // place randomly in the world, // with random velocity |vx|, |vy| <= maxv = 5 Molecule(Color c, int m, int r, World w) { double maxv = 5; // maximum magnitude of vx, vy mass = m; radius = r; color = c; world = w; px = r + Math.random() * (w.size - 2.0 * r); py = r + Math.random() * (w.size - 2.0 * r); vx = (Math.random() * 2.0 - 1.0) * maxv; vy = (Math.random() * 2.0 - 1.0) * maxv; } // paint the molecule void paint(Graphics g) { g.setColor(color); int left = (int) (px-radius), top = (int) (py-radius); int diameter = (int) (2.0*radius); g.fillOval(left, top, diameter, diameter); } // move the molecule one time step void move() { px += vx * world.step; py += vy * world.step; double wmin = radius; // topmost, leftmost walls double wmax = world.size - radius; // bottommost, rightmost walls // bounce off walls if (px <= wmin) { px = 2.0 * wmin - px; vx = -vx; } else if (px >= wmax) { px = 2.0 * wmax - px; vx = -vx; } if (py <= wmin) { py = 2.0 * wmin - py; vy = -vy; world.hit += 2.0 * mass * vy; } else if (py >= wmax) { py = 2.0 * wmax - py; vy = -vy; } } // check for collision with m and update velocities if so void collide(Molecule m) { double dt = world.step; // size of time step // variable definitions: named to match write-up double x1 = px, y1 = py; // center of self double x2 = m.px, y2 = m.py; // center of m double vx1 = vx, vy1 = vy; // velocity of self double vx2 = m.vx, vy2 = m.vy; // velocity of m double r = radius, r2 = m.radius; // radii of self, m double m1 = mass, m2 = m.mass; // mass of self, m // if extents don't overlap, then there is no collision if (x1+Math.max(0,vx1)*dt+r < x2+Math.min(0,vx2)*dt-r2 || x1+Math.min(0,vx1)*dt-r > x2+Math.max(0,vx2)*dt+r2 || y1+Math.max(0,vy1)*dt+r < y2+Math.min(0,vy2)*dt-r2 || y1+Math.min(0,vy1)*dt-r > y2+Math.max(0,vy2)*dt+r2 ) return; // ok, (assume) there is a collision: // update velocities according to formula from write-up double fx = x2 - x1, fy = y2 - y1; double s = 2.0 * (fx * (vx2-vx1) + fy * (vy2 - vy1)) / ((fx * fx + fy * fy) * (1.0 / m1 + 1.0 / m2)); vx += (s/m1) * fx; vy += (s/m1) * fy; m.vx -= (s/m2) * fx; m.vy -= (s/m2) * fy; } // return kinetic energy double energy() { return 0.5 * mass * (vx*vx + vy*vy); } } // a World is a square container containing Molecules class World extends Frame { double step = 0.5; // the length of time of each time step double size; // width=height of container double hit = 0.0; // cumulative vertical momentum applied to the top wall double time = 0.0; // elapsed time from start of simulation double P; // pressure double V; // area (not volume) double N; // number of molecules double T; // temperature measured as average kinetic energy Molecule m1,m2,m3; // 3 molecules in the world // create a new world of size s public World(int s) { size = s; V = size*size; N = 3; m1 = new Molecule(Color.red, 1, 4, this); m2 = new Molecule(Color.green, 4, 5, this); m3 = new Molecule(Color.blue, 16, 7, this); show(); // show; apparently needed to getInsets setSize(getInsets().left+getInsets().right+(int)size, getInsets().top+getInsets().bottom+(int)size); setBackground(Color.white); } // move each Molecule one time step public void move() { m1.collide(m2); m2.collide(m3); m3.collide(m1); m1.move(); m2.move(); m3.move(); T = (m1.energy() + m2.energy() + m3.energy())/N; time += step; P = hit / time / size; } // draw all the Molecules safely synchronized public void mypaint(Graphics g) { g.translate(getInsets().left,getInsets().top); g.clearRect(0,0,(int)size,(int)size); // erase old molecules m1.paint(g); m2.paint(g); m3.paint(g); } // draw all the Molecules -- call mypaint to be safe: // need the "synchronization". public void paint(Graphics g) { mypaint(g); } // print statistics: P, T, PV/NT void printStats() { DecimalFormat fmt = new DecimalFormat("0.0000"); System.out.println("P=" + fmt.format(P) +" T=" + fmt.format(T) +" PV/NT=" + fmt.format((P*V)/(N*T))); } } public class Project5 extends Thread { public void run() { int worldsize = 150; // size of world (the container) World w = new World(worldsize); while (true) { try { sleep(20); } catch (InterruptedException e) { } // perform one time step w.move(); w.paint(w.getGraphics()); w.printStats(); } } public static void main(String[] args) { new Thread(new Project5()).start(); } }