-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParticleSimulator.java
More file actions
197 lines (173 loc) · 5.88 KB
/
ParticleSimulator.java
File metadata and controls
197 lines (173 loc) · 5.88 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
import java.util.*;
import java.util.function.*;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import javax.sound.sampled.*;
public class ParticleSimulator extends JPanel {
private Heap<Event> _events;
private java.util.List<Particle> _particles;
private double _duration;
private int _width;
private java.util.List<Wall> _walls;
/**
* @param filename the name of the file to parse containing the particles
*/
public ParticleSimulator (String filename) throws IOException {
_events = new HeapImpl<>();
_walls = new ArrayList<>();
Wall right = new Wall("Right");
Wall left = new Wall("Left");
Wall top = new Wall("Top");
Wall bottom = new Wall("Bottom");
// Parse the specified file and load all the particles.
Scanner s = new Scanner(new File(filename));
_width = s.nextInt();
_duration = s.nextDouble();
s.nextLine();
_particles = new ArrayList<>();
while (s.hasNext()) {
String line = s.nextLine();
Particle particle = Particle.build(line);
_particles.add(particle);
}
_walls.add(right);
_walls.add(left);
_walls.add(top);
_walls.add(bottom);
setPreferredSize(new Dimension(_width, _width));
}
@Override
/**
* Draws all the particles on the screen at their current locations
* DO NOT MODIFY THIS METHOD
*/
public void paintComponent (Graphics g) {
g.clearRect(0, 0, _width, _width);
for (Particle p : _particles) {
p.draw(g);
}
}
// Helper class to signify the final event of the simulation.
private class TerminationEvent extends Event {
TerminationEvent (double timeOfEvent) {
super(timeOfEvent, 0);
}
}
/**
* Helper method to update the positions of all the particles based on their current velocities.
*/
private void updateAllParticles (double delta) {
for (Particle p : _particles) {
p.update(delta);
}
}
/**
* Enqueue will create a new Event from the particleList and the pre-existing _particles
* @param particleList
* @param lastTime
*/
private void enqueue (java.util.List<Particle> particleList, double lastTime) {
for (int i = 0; i < particleList.size(); i++) {
for (int j = 0; j < _particles.size(); j++) {
if (!_particles.get(j).equals(particleList.get(i))) {
double particleCollisionTime = _particles.get(j).getCollisionTime(particleList.get(i));
if (particleCollisionTime != Double.POSITIVE_INFINITY) {
_events.add(new ParticleCollisionEvent(_particles.get(j), particleList.get(i), lastTime + particleCollisionTime, lastTime));
}
}
}
for (Wall w : _walls) {
double wallCollisionTime = particleList.get(i).getWallCollisionTime(w, _width);
if(wallCollisionTime != Double.POSITIVE_INFINITY) {
_events.add(new WallCollisionEvent (particleList.get(i), w, lastTime + wallCollisionTime, lastTime));
}
}
}
}
/**
* Executes the actual simulation.
*/
private void simulate (boolean show) {
double lastTime = 0;
// Create initial events, i.e., all the possible
// collisions between all the particles and each other,
// and all the particles and the walls.
enqueue(_particles, lastTime);
_events.add(new TerminationEvent(_duration));
while (_events.size() > 0) {
Event event = _events.removeFirst();
double delta = event.getTimeOfEvent() - lastTime;
if (event instanceof TerminationEvent) {
updateAllParticles(delta);
break;
}
// Check if event still valid; if not, then skip this event
if (event instanceof ParticleCollisionEvent) {
ParticleCollisionEvent check = (ParticleCollisionEvent) event;
Particle part1 = (Particle) check.p1;
Particle part2 = (Particle) check.p2;
if (part1.getLastUpdateTime() > event.getTimeEventCreated() || part2.getLastUpdateTime() > event.getTimeEventCreated())
continue;
}
else if (event instanceof WallCollisionEvent) {
if (event.getP1().getLastUpdateTime() > event.getTimeEventCreated())
continue;
}
// Since the event is valid, then pause the simulation for the right
// amount of time, and then update the screen.
if (show) {
try {
Thread.sleep((long) delta);
} catch (InterruptedException ie) {}
}
// Update positions of all particles
updateAllParticles(delta);
// Update the time of our simulation
lastTime = event.getTimeOfEvent();
java.util.List<Particle> _newParticles;
_newParticles = new ArrayList<>();
// Update the velocity of the particle(s) involved in the collision
// (either for a particle-wall collision or a particle-particle collision).
// You should call the Particle.updateAfterCollision method at some point.
// Enqueue new events for the particle(s) that were involved in this event.
if (event instanceof WallCollisionEvent) {
event.getP1().updateAfterWalls(event.getWall(), lastTime);
_newParticles.add(event.getP1());
enqueue(_newParticles, lastTime);
}
if (event instanceof ParticleCollisionEvent) {
event.getP1().updateAfterCollision(lastTime, event.getP2());
_newParticles.add(event.getP1());
_newParticles.add(event.getP2());
enqueue(_newParticles, lastTime);
}
// Redraw the screen
if (show) {
repaint();
}
}
// Print out the final state of the simulation
System.out.println(_width);
System.out.println(_duration);
for (Particle p : _particles) {
System.out.println(p);
}
}
public static void main (String[] args) throws IOException {
if (args.length < 1) {
System.out.println("Usage: java ParticalSimulator <filename>");
System.exit(1);
}
ParticleSimulator simulator;
simulator = new ParticleSimulator(args[0]);
JFrame frame = new JFrame();
frame.setTitle("Particle Simulator");
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(simulator, BorderLayout.CENTER);
frame.setVisible(true);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
simulator.simulate(true);
}
}