Skip to content

Commit 51b8c3a

Browse files
committed
� Conflicts: � src/main/java/stl/threebodysimulation/UserManualFXMLController.java
2 parents 371a475 + aa3c0d1 commit 51b8c3a

16 files changed

+518
-161
lines changed

.idea/artifacts/threebodysimulation_jar.xml

Lines changed: 0 additions & 22 deletions
This file was deleted.

_config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
theme: jekyll-theme-cayman
2+
logo: /favicon.ico
23
title: Three-Body Simulation
4+
show_downloads: true

pom.xml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@
5959

6060
<build>
6161
<plugins>
62+
<plugin>
63+
<groupId>org.apache.maven.plugins</groupId>
64+
<artifactId>maven-shade-plugin</artifactId>
65+
<version>3.2.4</version>
66+
<executions>
67+
<execution>
68+
<phase>package</phase>
69+
<goals>
70+
<goal>shade</goal>
71+
</goals>
72+
<configuration>
73+
<transformers>
74+
<!-- add Main-Class to manifest file -->
75+
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
76+
<mainClass>stl.threebodysimulation.Launcher</mainClass>
77+
</transformer>
78+
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
79+
</transformers>
80+
</configuration>
81+
</execution>
82+
</executions>
83+
</plugin>
6284
<plugin>
6385
<groupId>org.apache.maven.plugins</groupId>
6486
<artifactId>maven-compiler-plugin</artifactId>
@@ -100,6 +122,7 @@
100122
<artifactId>client-maven-plugin</artifactId>
101123
<version>0.1.27-SNAPSHOT</version>
102124
<configuration>
125+
<verbose>true</verbose>
103126
<reflectionList>
104127
<!-- Include every class that is imported or created here, in case they involve reflection.-->
105128
<list>javafx.application.Platform</list>
@@ -198,7 +221,6 @@
198221
<list>stl.threebodysimulation.SettingsPanelFXMLController</list>
199222
<list>stl.threebodysimulation.SimulationSettings</list>
200223
<list>stl.threebodysimulation.SimulationState</list>
201-
<list>stl.threebodysimulation.UserManualFXMLController</list>
202224
<list>stl.threebodysimulation.LimitedTextFieldWrapper</list>
203225
<list>stl.threebodysimulation.WarningWindowFXMLController</list>
204226
</reflectionList>

splashscreen.bmp

703 KB
Binary file not shown.

src/main/java/stl/threebodysimulation/CanvasPanelFXMLController.java

Lines changed: 54 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,6 @@ void setup() {
204204
currentTime = 0;
205205
// Wrap the canvas.
206206
canvasWrapper = new CanvasWrapper(canvas, gridCanvas, trailCanvas);
207-
// Set up the integrator that we will be using. The minimum step size is 10 ^ -20, so that the integrator will return errors at asymptotes.
208-
integrator = new DormandPrince853Integrator(Math.pow(10, -10), 10000, 0.01, 0.0001);
209207
}
210208

211209
/**
@@ -246,6 +244,9 @@ void runSimulation(SimulationSettings settings) {
246244
// Set up the particle differential equation according to the masses of each particle.
247245
particleDifferentialEquations = new ParticleDifferentialEquations(settings.getMass());
248246

247+
// Set up the integrator that we will be using. The minimum step size is 10 ^ -20, so that the integrator will return errors at asymptotes.
248+
integrator = new DormandPrince853Integrator(Math.pow(10, -10), 10000, 0.01, 0.0001);
249+
249250
// Flatten particles into the flattenedParticles array.
250251
flattenParticles();
251252

@@ -254,12 +255,28 @@ void runSimulation(SimulationSettings settings) {
254255

255256
// Get position, velocity, acceleration at current time.
256257
if (currentTime != 0) {
257-
if (!tryToIntegrate(0, currentTime, flattenedParticles, true)) {
258+
try {
259+
// Get the position and velocity of particles at currentTime
260+
integrator.integrate(particleDifferentialEquations, 0, flattenedParticles, currentTime, flattenedParticles);
261+
} catch (NumberIsTooSmallException e) {
262+
// Asymptote error (the integrator can't converge and gives up)
263+
System.out.println(e.getMessage());
264+
breakSimulationAfterUpdate(FilenameUnspecificMessage.ASYMPTOTE_ERROR);
265+
return;
266+
} catch (NumberIsTooLargeException e) {
267+
// Double overflow error (inputs too large for double datatype to handle)
268+
System.out.println(e.getMessage());
269+
breakSimulationAfterUpdate(FilenameUnspecificMessage.OVERFLOW_ERROR);
270+
return;
271+
} catch (Exception e) {
272+
// Other errors
273+
System.out.println(e.getMessage());
274+
breakSimulationAfterUpdate(FilenameUnspecificMessage.UNKNOWN_ERROR);
258275
return;
259276
}
260277
}
261278

262-
double[][] scales = generateScale(flattenedParticles.clone(), settings);
279+
double[][] scales = generateScale(integrator, flattenedParticles.clone(), settings);
263280

264281
updateParticles();
265282

@@ -289,99 +306,36 @@ void runSimulation(SimulationSettings settings) {
289306
}
290307
}
291308

292-
/**
293-
* Attempts to integrate and find particle states at another time.
294-
*
295-
* @param time0 The current time.
296-
* @param time The time to travel to.
297-
* @param particles The particles involved.
298-
* @param wantErrors Whether errors should be reported to the user (True if you want reports, false otherwise)
299-
* @return True if the integration was successful, false otherwise.
300-
*/
301-
@SuppressWarnings("BooleanMethodIsAlwaysInverted") // Inverted for clarity.
302-
private boolean tryToIntegrate(double time0, double time, double[] particles, boolean wantErrors) {
303-
304-
final boolean[] successfulIntegration = {false};
305-
306-
Task<Void> integrationTask = new Task<>() {
307-
@Override
308-
protected Void call() {
309-
try {
310-
integrator.integrate(particleDifferentialEquations, time0, particles, time, particles);
311-
} catch (NumberIsTooSmallException e) {
312-
// Asymptote error catching
313-
e.printStackTrace();
314-
if (wantErrors) {
315-
Platform.runLater(() -> breakSimulationAfterUpdate(FilenameUnspecificMessage.ASYMPTOTE_ERROR));
316-
}
317-
return null;
318-
} catch (NumberIsTooLargeException e) {
319-
// Double overflow error catching.
320-
e.printStackTrace();
321-
if (wantErrors) {
322-
Platform.runLater(() -> breakSimulationAfterUpdate(FilenameUnspecificMessage.OVERFLOW_ERROR));
323-
}
324-
return null;
325-
} catch (Exception e) {
326-
// Other errors
327-
e.printStackTrace();
328-
if (wantErrors) {
329-
Platform.runLater(() -> breakSimulationAfterUpdate(FilenameUnspecificMessage.UNKNOWN_ERROR));
330-
}
331-
return null;
332-
}
333-
successfulIntegration[0] = true;
334-
return null;
335-
}
336-
};
337-
338-
339-
// Run the thread.
340-
Thread simulationThread = new Thread(integrationTask);
341-
simulationThread.setDaemon(true);
342-
// For debugging purposes, an exception handler to terminal output is created.
343-
simulationThread.setUncaughtExceptionHandler((t, e) -> System.out.println(e.getMessage()));
344-
345-
double deadline = System.currentTimeMillis() + 50; // half a second
346-
simulationThread.start();
347-
while ((!simulationThread.isInterrupted()) && simulationThread.isAlive()) {
348-
if (System.currentTimeMillis() > deadline) {
349-
simulationThread.interrupt();
350-
if (wantErrors) {
351-
Platform.runLater(() -> breakSimulation(FilenameUnspecificMessage.ASYMPTOTE_ERROR));
352-
}
353-
return false;
354-
}
355-
}
356-
return successfulIntegration[0];
357-
}
358-
359309
/**
360310
* Calculates the maximum and minimum x/y coordinates during the first ten seconds of simulation.
361311
*
312+
* @param integrator The integrator used.
362313
* @param particles The particles' initial states in flattened form.
363314
* @param settings The settings of the simulation.
364315
* @return The four corners of the smallest possible rectangle that all three particles do not escape in the first 10 seconds of simulation.
365316
*/
366-
private double[][] generateScale(double[] particles, SimulationSettings settings) {
317+
private double[][] generateScale(DormandPrince853Integrator integrator, double[] particles, SimulationSettings settings) {
367318
final int SIMULATION_LENGTH = 10;
368319
double simulationTime = currentTime;
369320

370321
double[][] minsAndMaxs = minAndMaxPositions(particles);
371322

372323
for (double time = simulationTime; time < SIMULATION_LENGTH * settings.getSpeed() + simulationTime; time += settings.getSpeed() / 5) {
373-
if (!tryToIntegrate(time, time + settings.getSpeed() / 5, particles, false)) {
374-
break;
375-
}
376-
377-
double[][] currentMinsAndMaxs = minAndMaxPositions(particles);
378-
for (int i = 0; i < 2; i++) {
379-
if (currentMinsAndMaxs[0][i] < minsAndMaxs[0][i]) {
380-
minsAndMaxs[0][i] = currentMinsAndMaxs[0][i];
381-
}
382-
if (currentMinsAndMaxs[1][i] > minsAndMaxs[1][i]) {
383-
minsAndMaxs[1][i] = currentMinsAndMaxs[1][i];
324+
try {
325+
// Get the position and velocity of particles at currentTime
326+
integrator.integrate(particleDifferentialEquations, time, particles, time + settings.getSpeed() / 5, particles);
327+
double[][] currentMinsAndMaxs = minAndMaxPositions(particles);
328+
for (int i = 0; i < 2; i++) {
329+
if (currentMinsAndMaxs[0][i] < minsAndMaxs[0][i]) {
330+
minsAndMaxs[0][i] = currentMinsAndMaxs[0][i];
331+
}
332+
if (currentMinsAndMaxs[1][i] > minsAndMaxs[1][i]) {
333+
minsAndMaxs[1][i] = currentMinsAndMaxs[1][i];
334+
}
384335
}
336+
} catch (Exception e) {
337+
// All exceptions mean automatic break.
338+
break;
385339
}
386340
}
387341

@@ -513,7 +467,23 @@ private void startSimulation() {
513467
protected Void call() throws Exception {
514468
while (state == SimulationState.ACTIVE) { // Break if the simulation becomes inactive or paused.
515469
long taskTime = System.currentTimeMillis(); // Record current time (to sync framerate)
516-
if (!tryToIntegrate(currentTime, currentTime + (speed / MAX_FRAMERATE), flattenedParticles, true)) {
470+
try {
471+
// Store the state of the particles at the next frame.
472+
integrator.integrate(particleDifferentialEquations, currentTime, flattenedParticles, currentTime + (speed / MAX_FRAMERATE), flattenedParticles);
473+
} catch (NumberIsTooSmallException e) {
474+
// Asymptote error catching
475+
System.out.println(e.getMessage());
476+
Platform.runLater(() -> breakSimulationAfterUpdate(FilenameUnspecificMessage.ASYMPTOTE_ERROR));
477+
break;
478+
} catch (NumberIsTooLargeException e) {
479+
// Double overflow error catching.
480+
System.out.println(e.getMessage());
481+
Platform.runLater(() -> breakSimulationAfterUpdate(FilenameUnspecificMessage.OVERFLOW_ERROR));
482+
break;
483+
} catch (Exception e) {
484+
// Other errors
485+
System.out.println(e.getMessage());
486+
Platform.runLater(() -> breakSimulationAfterUpdate(FilenameUnspecificMessage.UNKNOWN_ERROR));
517487
break;
518488
}
519489

src/main/java/stl/threebodysimulation/CanvasWrapper.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ class CanvasWrapper {
7878
/**
7979
* Constructs a basic CanvasWrapper object for a particular canvas UI element.
8080
*
81-
* @param canvas The main canvas for particles.
82-
* @param gridCanvas The canvas that manages gridlines.
81+
* @param canvas The main canvas for particles.
82+
* @param gridCanvas The canvas that manages gridlines.
8383
* @param trailCanvas The canvas that manages trails.
8484
*/
8585
CanvasWrapper(Canvas canvas, Canvas gridCanvas, Canvas trailCanvas) {
@@ -129,6 +129,23 @@ private static double[][] calculateRectangle(double[][] originalRectangle, doubl
129129
return newRectangle;
130130
}
131131

132+
/**
133+
* Calculates the first gridline based on a corner coordinate and a grid interval.
134+
*
135+
* @param base The corner coordinate.
136+
* @param interval The grid interval.
137+
* @return The coordinate of the first gridline.
138+
*/
139+
private static double calculateFirstGridline(double base, double interval) {
140+
if (base < 0) { // Modulo works differently with positive and negative numbers in Java
141+
return base + Math.abs(base % interval);
142+
} else if (base > 0) {
143+
return base + (interval - base % interval);
144+
} else {
145+
return 0;
146+
}
147+
}
148+
132149
/**
133150
* Sets the graphics options and particles for the canvas.
134151
*
@@ -210,7 +227,7 @@ private void printVerticalGridlines(double interval) {
210227
double relativeCurrentGridline = returnRelativePosition(new double[]{currentGridline, 0})[0];
211228
gridGC.strokeLine(relativeCurrentGridline, -20, relativeCurrentGridline, 800);
212229
// Draw the label for the gridline, but only if it isn't too close to the left side of the canvas (to prevent overlap)
213-
if (!(relativeCurrentGridline < 60)) {
230+
if (!(relativeCurrentGridline < 100)) {
214231
drawRotatedText(gridGC, String.format("%g", currentGridline), 270, relativeCurrentGridline - 10, 710);
215232
}
216233
currentGridline += interval;
@@ -234,23 +251,6 @@ private void drawRotatedText(GraphicsContext gc, String text, double angle, doub
234251
gc.restore(); // back to original state (before rotation)
235252
}
236253

237-
/**
238-
* Calculates the first gridline based on a corner coordinate and a grid interval.
239-
*
240-
* @param base The corner coordinate.
241-
* @param interval The grid interval.
242-
* @return The coordinate of the first gridline.
243-
*/
244-
private static double calculateFirstGridline(double base, double interval) {
245-
if (base < 0) { // Modulo works differently with positive and negative numbers in Java
246-
return base + Math.abs(base % interval);
247-
} else if (base > 0) {
248-
return base + (interval - base % interval);
249-
} else {
250-
return 0;
251-
}
252-
}
253-
254254
/**
255255
* Prints the horizontal gridlines based on the calculated grid interval.
256256
*

src/main/java/stl/threebodysimulation/FilenameUnspecificMessage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,4 @@ public String getMessage() {
8989
return "An unknown error occurred during the simulation. Please let the developers know, and try your simulation again.";
9090
}
9191
}
92-
}
92+
}

src/main/java/stl/threebodysimulation/Launcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class Launcher {
1212
* @param args Terminal arguments.
1313
*/
1414
public static void main(String[] args) {
15+
System.setProperty("prism.allowhidpi", "false");
1516
Application.launch(MainApp.class, args);
1617
}
1718
}

src/main/resources/stl/threebodysimulation/layouts/canvasPanelLayout.fxml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
<?import javafx.scene.text.Font?>
1010
<StackPane xmlns:fx="http://javafx.com/fxml/1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
1111
minWidth="-Infinity"
12-
style="-fx-background-color: #F2F2F2; -fx-border-color: #C0C0C0 transparent transparent transparent;" stylesheets="@../styles/bootstrap3.css"
13-
xmlns="http://javafx.com/javafx/10.0.2-internal" fx:controller="stl.threebodysimulation.CanvasPanelFXMLController">
12+
style="-fx-background-color: #F2F2F2; -fx-border-color: #C0C0C0 transparent transparent transparent;"
13+
stylesheets="@../styles/bootstrap3.css"
14+
xmlns="http://javafx.com/javafx/10.0.2-internal"
15+
fx:controller="stl.threebodysimulation.CanvasPanelFXMLController">
1416
<Canvas fx:id="gridCanvas" height="720.0" layoutX="11.0" layoutY="11.0" width="800.0"/>
1517
<Canvas fx:id="trailCanvas" height="720.0" layoutX="11.0" layoutY="11.0" width="800.0"/>
1618
<Canvas fx:id="canvas" height="720.0" width="800.0"/>

src/main/resources/stl/threebodysimulation/layouts/defaultSavePreviewLayout.fxml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
<?import javafx.scene.layout.RowConstraints?>
1111
<?import javafx.scene.layout.VBox?>
1212
<?import javafx.scene.text.Font?>
13-
<TitledPane xmlns:fx="http://javafx.com/fxml/1" fx:id="fileTitle" alignment="CENTER" expanded="false" maxHeight="-Infinity"
13+
<TitledPane xmlns:fx="http://javafx.com/fxml/1" fx:id="fileTitle" alignment="CENTER" expanded="false"
14+
maxHeight="-Infinity"
1415
maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
1516
style="-fx-background-color: white;" stylesheets="@../styles/bootstrap3.css" text="untitled"
1617
xmlns="http://javafx.com/javafx/10.0.2-internal"

0 commit comments

Comments
 (0)