001package algs61; // section 6.1 002import stdlib.*; 003import java.awt.Color; 004/* *********************************************************************** 005 * Compilation: javac Particle.java 006 * 007 * A particle moving in the unit box with a given position, velocity, 008 * radius, and mass. 009 * 010 *************************************************************************/ 011 012public class Particle { 013 private static final double INFINITY = Double.POSITIVE_INFINITY; 014 015 private double rx, ry; // position 016 private double vx, vy; // velocity 017 private final double radius; // radius 018 private final double mass; // mass 019 private final Color color; // color 020 private int count; // number of collisions so far 021 022 023 // create a new particle with given parameters 024 public Particle(double rx, double ry, double vx, double vy, double radius, double mass, Color color) { 025 this.vx = vx; 026 this.vy = vy; 027 this.rx = rx; 028 this.ry = ry; 029 this.radius = radius; 030 this.mass = mass; 031 this.color = color; 032 } 033 034 // create a random particle in the unit box (overlaps not checked) 035 public Particle() { 036 rx = Math.random(); 037 ry = Math.random(); 038 vx = 0.01 * (Math.random() - 0.5); 039 vy = 0.01 * (Math.random() - 0.5); 040 radius = 0.01; 041 mass = 0.5; 042 //color = Color.BLACK; 043 color = new Color (StdRandom.uniform(200), StdRandom.uniform(200), StdRandom.uniform(200)); 044 } 045 046 // updates position 047 public void move(double dt) { 048 rx += vx * dt; 049 ry += vy * dt; 050 } 051 052 // draw the particle 053 public void draw() { 054 StdDraw.setPenColor(color); 055 StdDraw.filledCircle(rx, ry, radius); 056 } 057 058 // return the number of collisions involving this particle 059 public int count() { return count; } 060 061 062 // how long into future until collision between this particle a and b? 063 public double timeToHit(Particle b) { 064 Particle a = this; 065 if (a == b) return INFINITY; 066 double dx = b.rx - a.rx; 067 double dy = b.ry - a.ry; 068 double dvx = b.vx - a.vx; 069 double dvy = b.vy - a.vy; 070 double dvdr = dx*dvx + dy*dvy; 071 if (dvdr > 0) return INFINITY; 072 double dvdv = dvx*dvx + dvy*dvy; 073 double drdr = dx*dx + dy*dy; 074 double sigma = a.radius + b.radius; 075 double d = (dvdr*dvdr) - dvdv * (drdr - sigma*sigma); 076 // if (drdr < sigma*sigma) StdOut.println("overlapping particles"); 077 if (d < 0) return INFINITY; 078 return -(dvdr + Math.sqrt(d)) / dvdv; 079 } 080 081 // how long into future until this particle collides with a vertical wall? 082 public double timeToHitVerticalWall() { 083 if (vx > 0) return (1.0 - rx - radius) / vx; 084 else if (vx < 0) return (radius - rx) / vx; 085 else return INFINITY; 086 } 087 088 // how long into future until this particle collides with a horizontal wall? 089 public double timeToHitHorizontalWall() { 090 if (vy > 0) return (1.0 - ry - radius) / vy; 091 else if (vy < 0) return (radius - ry) / vy; 092 else return INFINITY; 093 } 094 095 // update velocities upon collision between this particle and that particle 096 public void bounceOff(Particle that) { 097 double dx = that.rx - this.rx; 098 double dy = that.ry - this.ry; 099 double dvx = that.vx - this.vx; 100 double dvy = that.vy - this.vy; 101 double dvdr = dx*dvx + dy*dvy; // dv dot dr 102 double dist = this.radius + that.radius; // distance between particle centers at collison 103 104 // normal force F, and in x and y directions 105 double F = 2 * this.mass * that.mass * dvdr / ((this.mass + that.mass) * dist); 106 double fx = F * dx / dist; 107 double fy = F * dy / dist; 108 109 // update velocities according to normal force 110 this.vx += fx / this.mass; 111 this.vy += fy / this.mass; 112 that.vx -= fx / that.mass; 113 that.vy -= fy / that.mass; 114 115 // update collision counts 116 this.count++; 117 that.count++; 118 } 119 120 // update velocity of this particle upon collision with a vertical wall 121 public void bounceOffVerticalWall() { 122 vx = -vx; 123 count++; 124 } 125 126 // update velocity of this particle upon collision with a horizontal wall 127 public void bounceOffHorizontalWall() { 128 vy = -vy; 129 count++; 130 } 131 132 // return kinetic energy associated with this particle 133 public double kineticEnergy() { return 0.5 * mass * (vx*vx + vy*vy); } 134}