133 lines
5.1 KiB
Java
133 lines
5.1 KiB
Java
import codedraw.CodeDraw;
|
|
|
|
import java.awt.*;
|
|
import java.util.Random;
|
|
|
|
// 1. Datenkapselung: Zusammenfassen von Methoden und Variablen zu Einheit.
|
|
// Die `static` Methoden von `Simulation` nach `Body` oder `Vector3` verschieben.
|
|
|
|
// 2. Data Hiding: Verstecken vor Zugriffen von außen.
|
|
// Attribute von `Body` und `Vector3` auf `private` setzen.
|
|
|
|
// 3. Beim Methodenaufruf steht links vom `.` entweder das Objekt, oder die Klasse. In Java beginnen Variablennamen
|
|
// üblicherweise mit Kleinbuchstaben und Klassennamen üblicherweise mit einem Großbuchstaben.
|
|
|
|
// Simulates the formation of a massive solar system.
|
|
public class Simulation {
|
|
|
|
// gravitational constant
|
|
public static final double G = 6.6743e-11;
|
|
|
|
// one astronomical unit (AU) is the average distance of earth to the sun.
|
|
public static final double AU = 150e9; // meters
|
|
|
|
// one light year
|
|
public static final double LY = 9.461e15; // meters
|
|
|
|
// some further constants needed in the simulation
|
|
public static final double SUN_MASS = 1.989e30; // kilograms
|
|
public static final double SUN_RADIUS = 696340e3; // meters
|
|
public static final double EARTH_MASS = 5.972e24; // kilograms
|
|
public static final double EARTH_RADIUS = 6371e3; // meters
|
|
|
|
// set some system parameters
|
|
public static final double SECTION_SIZE = 2 * AU; // the size of the square region in space
|
|
public static final int NUMBER_OF_BODIES = 22;
|
|
public static final double OVERALL_SYSTEM_MASS = 20 * SUN_MASS; // kilograms
|
|
|
|
// all quantities are based on units of kilogram respectively second and meter.
|
|
|
|
// The main simulation method using instances of other classes.
|
|
public static void main(String[] args) {
|
|
// simulation
|
|
CodeDraw cd = new CodeDraw();
|
|
BodyQueue bodies = new BodyQueue();
|
|
BodyForceMap forceOnBody = new BodyForceMap();
|
|
|
|
Random random = new Random(2022);
|
|
|
|
for (int i = 0; i < NUMBER_OF_BODIES; i++) {
|
|
bodies.add(new Body(
|
|
Math.abs(random.nextGaussian()) * OVERALL_SYSTEM_MASS / NUMBER_OF_BODIES, // kg
|
|
new Vector3(
|
|
0.2 * random.nextGaussian() * AU,
|
|
0.2 * random.nextGaussian() * AU,
|
|
0.2 * random.nextGaussian() * AU
|
|
),
|
|
new Vector3(
|
|
0 + random.nextGaussian() * 5e3,
|
|
0 + random.nextGaussian() * 5e3,
|
|
0 + random.nextGaussian() * 5e3
|
|
)
|
|
));
|
|
}
|
|
|
|
double seconds = 0;
|
|
|
|
// simulation loop
|
|
while (true) {
|
|
BodyQueue newBodies = new BodyQueue(bodies);
|
|
Body[] tmp = new Body[bodies.size()];
|
|
for (int i = 0; bodies.size() > 0; i++) {
|
|
tmp[i] = bodies.poll();
|
|
}
|
|
seconds++; // each iteration computes the movement of the celestial bodies within one second.
|
|
|
|
/*
|
|
// merge bodies that have collided
|
|
for (int i = 0; i < bodies.length; i++) {
|
|
for (int j = i + 1; j < bodies.length; j++) {
|
|
if (bodies[j].distanceTo(bodies[i]) < bodies[j].radius() + bodies[i].radius()) {
|
|
bodies[i] = bodies[i].merge(bodies[j]);
|
|
Body[] bodiesOneRemoved = new Body[bodies.length - 1];
|
|
for (int k = 0; k < bodiesOneRemoved.length; k++) {
|
|
bodiesOneRemoved[k] = bodies[k < j ? k : k + 1];
|
|
}
|
|
bodies = bodiesOneRemoved;
|
|
|
|
// since the body index i changed size there might be new collisions
|
|
// at all positions of bodies, so start all over again
|
|
i = -1;
|
|
j = bodies.length;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
// for each body (with index i): compute the total force exerted on it.
|
|
for (Body b1 : tmp) {
|
|
Vector3 force = new Vector3(); // begin with zero
|
|
for (Body b2 : tmp) {
|
|
if (b1 != b2) {
|
|
force = force.plus(b1.gravitationalForce(b2));
|
|
}
|
|
}
|
|
forceOnBody.put(b1, force);
|
|
}
|
|
// now forceOnBody[i] holds the force vector exerted on body with index i.
|
|
|
|
// for each body (with index i): move it according to the total force exerted on it.
|
|
for (Body body : tmp) {
|
|
body.move(forceOnBody.get(body));
|
|
}
|
|
|
|
// show all movements in the canvas only every hour (to speed up the simulation)
|
|
if (seconds % (3600) == 0) {
|
|
// clear old positions (exclude the following line if you want to draw orbits).
|
|
cd.clear(Color.BLACK);
|
|
|
|
// draw new positions
|
|
for (Body body : tmp) {
|
|
body.draw(cd);
|
|
}
|
|
|
|
// show new positions
|
|
cd.show();
|
|
}
|
|
|
|
bodies = newBodies;
|
|
}
|
|
|
|
}
|
|
}
|