Files
EP2/src/Simulation.java
2022-03-28 10:13:19 +02:00

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;
}
}
}