-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParticle.java
More file actions
285 lines (258 loc) · 9.39 KB
/
Copy pathParticle.java
File metadata and controls
285 lines (258 loc) · 9.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/******************************************************************************
* Compilation: javac Particle.java
* Execution: none
* Dependencies: this.canvas.java
*
* A particle moving in the unit box with a given position, velocity,
* radius, and mass.
*
******************************************************************************/
import java.awt.Color;
/**
* The {@code Particle} class represents a particle moving in the unit box,
* with a given position, velocity, radius, and mass. Methods are provided
* for moving the particle and for predicting and resolvling elastic
* collisions with vertical walls, horizontal walls, and other particles.
* This data type is mutable because the position and velocity change.
* <p>
* For additional documentation,
* see <a href="https://algs4.cs.princeton.edu/61event">Section 6.1</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Particle {
private static final double INFINITY = Double.POSITIVE_INFINITY;
public double rx, ry; // position
private double vx, vy; // velocity
private int count; // number of collisions so far
public final double radius; // radius
public double mass; // mass
private final Color color; // color
public boolean inside_spread_zone;
public double spread_radius;
public boolean infected;
public boolean recovered;
public double recovery_time;
/**
* Initializes a particle with the specified position, velocity, radius, mass, and color.
*
* @param rx <em>x</em>-coordinate of position
* @param ry <em>y</em>-coordinate of position
* @param vx <em>x</em>-coordinate of velocity
* @param vy <em>y</em>-coordinate of velocity
* @param radius the radius
* @param mass the mass
* @param color the color
*/
public Particle(double rx, double ry, double vx, double vy, double radius, double mass, Color color, double spread_radius, double recovery_time) {
this.vx = vx;
this.vy = vy;
this.rx = rx;
this.ry = ry;
this.radius = radius;
this.mass = mass;
this.color = color;
this.inside_spread_zone = false;
this.recovery_time = recovery_time;
this.infected = false;
this.recovered = false;
this.spread_radius = spread_radius;
}
/**
* Initializes a particle with a random position and velocity.
* The position is uniform in the unit box; the velocity in
* either direciton is chosen uniformly at random.
*/
public Particle() {
rx = StdRandom.uniform(0.0, 1.0);
ry = StdRandom.uniform(0.0, 1.0);
vx = StdRandom.uniform(-0.005, 0.005);
vy = StdRandom.uniform(-0.005, 0.005);
radius = 0.005;
mass = 0.5;
color = Color.BLACK;
inside_spread_zone = false;
recovery_time = 200;
infected = false;
recovered = false;
spread_radius = radius * StdRandom.uniform(1.5, 2.5);
}
/**
* Moves this particle in a straight line (based on its velocity)
* for the specified amount of time.
*
* @param dt the amount of time
*/
public void move(double dt) {
rx += vx * dt;
ry += vy * dt;
}
public void recover()
{
recovered = true;
infected = false;
}
public boolean susceptible()
{
return !(infected || recovered);
}
/**
* Draws this particle to standard draw.
*/
public void draw(Draw canvas) {
canvas.setPenColor(color);
if (infected)
{
canvas.setPenColor(Draw.GREEN);
canvas.circle(rx, ry, spread_radius);
canvas.setPenColor(Draw.RED);
}
else if (recovered)
{
canvas.setPenColor(Draw.GRAY);
}
canvas.filledCircle(rx, ry, radius);
}
/**
* Returns the number of collisions involving this particle with
* vertical walls, horizontal walls, or other particles.
* This is equal to the number of calls to {@link #bounceOff},
* {@link #bounceOffVerticalWall}, and
* {@link #bounceOffHorizontalWall}.
*
* @return the number of collisions involving this particle with
* vertical walls, horizontal walls, or other particles
*/
public int count() {
return count;
}
/**
* Returns the amount of time for this particle to collide with the specified
* particle, assuming no interening collisions.
*
* @param that the other particle
* @return the amount of time for this particle to collide with the specified
* particle, assuming no interening collisions;
* {@code Double.POSITIVE_INFINITY} if the particles will not collide
*/
public double[] timeToHit(Particle that) {
double[] dts = new double[2];
dts[0] = INFINITY;
dts[1] = INFINITY;
if (this == that) return dts;
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;
if (dvdr > 0) return dts;
double dvdv = dvx*dvx + dvy*dvy;
if (dvdv == 0) return dts;
double drdr = dx*dx + dy*dy;
double sigma = this.radius + that.radius;
double d = (dvdr*dvdr) - dvdv * (drdr - sigma*sigma);
if (d >= 0)
{
dts[0] = -(dvdr + Math.sqrt(d)) / dvdv;
}
drdr = dx*dx + dy*dy;
if (that.infected)
{
sigma = this.radius + that.spread_radius;
}
else
{
sigma = this.spread_radius + that.radius;
}
d = (dvdr*dvdr) - dvdv * (drdr - sigma*sigma);
if (d >= 0) dts[1] = -(dvdr + Math.sqrt(d)) / dvdv;
// if (drdr < sigma*sigma) StdOut.println("overlapping particles");
return dts;
}
/**
* Returns the amount of time for this particle to collide with a vertical
* wall, assuming no interening collisions.
*
* @return the amount of time for this particle to collide with a vertical wall,
* assuming no interening collisions;
* {@code Double.POSITIVE_INFINITY} if the particle will not collide
* 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;
}
/**
* Returns the amount of time for this particle to collide with a horizontal
* wall, assuming no interening collisions.
*
* @return the amount of time for this particle to collide with a horizontal wall,
* assuming no interening collisions;
* {@code Double.POSITIVE_INFINITY} if the particle will not collide
* 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;
}
/**
* Updates the velocities of this particle and the specified particle according
* to the laws of elastic collision. Assumes that the particles are colliding
* at this instant.
*
* @param that the other 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
// magnitude of normal force
double magnitude = 2 * this.mass * that.mass * dvdr / ((this.mass + that.mass) * dist);
// normal force, and in x and y directions
double fx = magnitude * dx / dist;
double fy = magnitude * 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++;
}
/**
* Updates the velocity of this particle upon collision with a vertical
* wall (by reflecting the velocity in the <em>x</em>-direction).
* Assumes that the particle is colliding with a vertical wall at this instant.
*/
public void bounceOffVerticalWall() {
vx = -vx;
count++;
}
/**
* Updates the velocity of this particle upon collision with a horizontal
* wall (by reflecting the velocity in the <em>y</em>-direction).
* Assumes that the particle is colliding with a horizontal wall at this instant.
*/
public void bounceOffHorizontalWall() {
vy = -vy;
count++;
}
/**
* Returns the kinetic energy of this particle.
* The kinetic energy is given by the formula 1/2 <em>m</em> <em>v</em><sup>2</sup>,
* where <em>m</em> is the mass of this particle and <em>v</em> is its velocity.
*
* @return the kinetic energy of this particle
*/
public double kineticEnergy() {
return 0.5 * mass * (vx*vx + vy*vy);
}
}