137 lines
4.4 KiB
Java
137 lines
4.4 KiB
Java
|
|
||
|
|
||
|
/*************************************************************************
|
||
|
* 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); }
|
||
|
}
|