/************************************************************************* * Compilation: javac Particle.java * * A particle moving in the unit box with a given position, velocity, * radius, and mass. * *************************************************************************/ import java.awt.Color; import edu.princeton.cs.introcs.StdDraw; public class Particle { private static final double INFINITY = Double.POSITIVE_INFINITY; private double rx, ry; // position private double vx, vy; // velocity private double radius; // radius private double mass; // mass private Color color; // color private int count; // number of collisions so far // create a new particle with given parameters public Particle(double rx, double ry, double vx, double vy, double radius, double mass, Color color) { this.vx = vx; this.vy = vy; this.rx = rx; this.ry = ry; this.radius = radius; this.mass = mass; this.color = color; } // create a random particle in the unit box (overlaps not checked) public Particle() { rx = Math.random(); ry = Math.random(); vx = 0.01 * (Math.random() - 0.5); vy = 0.01 * (Math.random() - 0.5); radius = 0.01; mass = 0.5; color = Color.BLACK; } // updates position public void move(double dt) { rx += vx * dt; ry += vy * dt; } // draw the particle public void draw() { StdDraw.setPenColor(color); StdDraw.filledCircle(rx, ry, radius); } // return the number of collisions involving this particle public int count() { return count; } // how long into future until collision between this particle a and b? public double timeToHit(Particle b) { Particle a = this; if (a == b) return INFINITY; double dx = b.rx - a.rx; double dy = b.ry - a.ry; double dvx = b.vx - a.vx; double dvy = b.vy - a.vy; double dvdr = dx*dvx + dy*dvy; if (dvdr > 0) return INFINITY; double dvdv = dvx*dvx + dvy*dvy; double drdr = dx*dx + dy*dy; double sigma = a.radius + b.radius; double d = (dvdr*dvdr) - dvdv * (drdr - sigma*sigma); // if (drdr < sigma*sigma) StdOut.println("overlapping particles"); if (d < 0) return INFINITY; return -(dvdr + Math.sqrt(d)) / dvdv; } // how long into future until this particle collides with a vertical wall? public double timeToHitVerticalWall() { if (vx > 0) return (1.0 - rx - radius) / vx; else if (vx < 0) return (radius - rx) / vx; else return INFINITY; } // how long into future until this particle collides with a horizontal wall? public double timeToHitHorizontalWall() { if (vy > 0) return (1.0 - ry - radius) / vy; else if (vy < 0) return (radius - ry) / vy; else return INFINITY; } // update velocities upon collision between this particle and that particle public void bounceOff(Particle that) { double dx = that.rx - this.rx; double dy = that.ry - this.ry; double dvx = that.vx - this.vx; double dvy = that.vy - this.vy; double dvdr = dx*dvx + dy*dvy; // dv dot dr double dist = this.radius + that.radius; // distance between particle centers at collison // normal force F, and in x and y directions double F = 2 * this.mass * that.mass * dvdr / ((this.mass + that.mass) * dist); double fx = F * dx / dist; double fy = F * dy / dist; // update velocities according to normal force this.vx += fx / this.mass; this.vy += fy / this.mass; that.vx -= fx / that.mass; that.vy -= fy / that.mass; // update collision counts this.count++; that.count++; } // update velocity of this particle upon collision with a vertical wall public void bounceOffVerticalWall() { vx = -vx; count++; } // update velocity of this particle upon collision with a horizontal wall public void bounceOffHorizontalWall() { vy = -vy; count++; } // return kinetic energy associated with this particle public double kineticEnergy() { return 0.5 * mass * (vx*vx + vy*vy); } }