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