Finish AB 2

This commit is contained in:
2022-03-28 10:13:19 +02:00
parent 5158aa2cbe
commit dca869995a
4 changed files with 151 additions and 32 deletions

View File

@ -53,6 +53,10 @@ public class Body {
return SpaceDraw.massToRadius(mass); return SpaceDraw.massToRadius(mass);
} }
public double mass() {
return mass;
}
// Returns a new body that is formed by the collision of this body and 'b'. The impulse // Returns a new body that is formed by the collision of this body and 'b'. The impulse
// of the returned body is the sum of the impulses of 'this' and 'b'. // of the returned body is the sum of the impulses of 'this' and 'b'.
public Body merge(Body b) { public Body merge(Body b) {

View File

@ -3,21 +3,55 @@
// //
public class BodyForceMap { public class BodyForceMap {
//TODO: declare variables. private int size = 0;
private int capacity;
private Body[] keys;
private Vector3[] values;
public BodyForceMap() {
this(4);
}
// Initializes this map with an initial capacity. // Initializes this map with an initial capacity.
// Precondition: initialCapacity > 0. // Precondition: initialCapacity > 0.
public BodyForceMap(int initialCapacity) { public BodyForceMap(int initialCapacity) {
this.capacity = initialCapacity;
//TODO: define constructor. this.keys = new Body[this.capacity];
this.values = new Vector3[this.capacity];
} }
// Adds a new key-value association to this map. If the key already exists in this map, // Adds a new key-value association to this map. If the key already exists in this map,
// the value is replaced and the old value is returned. Otherwise 'null' is returned. // the value is replaced and the old value is returned. Otherwise 'null' is returned.
// Precondition: key != null. // Precondition: key != null.
public Vector3 put(Body key, Vector3 force) { public Vector3 put(Body key, Vector3 force) {
if (size == capacity) {
doubleCapacity();
}
//TODO: implement method. int left = 0;
int right = size - 1;
while (left <= right) {
int middle = left + (right - left) / 2;
if (keys[middle] == key) {
Vector3 v = values[middle];
values[middle] = force;
return v;
} else if (keys[middle].mass() < key.mass()) {
right = middle - 1;
} else {
left = middle + 1;
}
}
int insert = right + 1;
for (int i = size; i > insert; i--) {
keys[i] = keys[i - 1];
values[i] = values[i - 1];
}
size++;
keys[insert] = key;
values[insert] = force;
return null; return null;
} }
@ -25,8 +59,52 @@ public class BodyForceMap {
// associated with the specified body. Returns 'null' if the key is not contained in this map. // associated with the specified body. Returns 'null' if the key is not contained in this map.
// Precondition: key != null. // Precondition: key != null.
public Vector3 get(Body key) { public Vector3 get(Body key) {
int left = 0;
int right = size - 1;
while (left <= right) {
int middle = left + ((right - left) / 2);
int middleLeft = left + (middle - left) / 2;
int middleRight = middle + (right - middle) / 2;
if (keys[middle] == key) {
return values[middle];
}
if (keys[middleLeft].mass() == keys[middle].mass()) {
for (int i = middleLeft; i < middle; i++) {
if (keys[i] == key)
return values[i];
}
}
if (keys[middle].mass() == keys[middleRight].mass()) {
for (int i = middle; i < middleRight; i++) {
if (keys[i] == key)
return values[i];
}
}
if (keys[middle].mass() < key.mass()) {
right = middle - 1;
} else {
left = middle + 1;
}
}
//TODO: implement method.
return null; return null;
} }
private void doubleCapacity() {
capacity *= 2;
Body[] tmpKeys = new Body[capacity];
Vector3[] tmpValues = new Vector3[capacity];
for (int i = 0; i < size; i++) {
tmpKeys[i] = keys[i];
tmpValues[i] = values[i];
}
keys = tmpKeys;
values = tmpValues;
}
} }

View File

@ -5,13 +5,20 @@
// //
public class BodyQueue { public class BodyQueue {
//TODO: declare variables. private int capacity;
private int head = 0;
private int tail = 0;
private Body[] queue;
public BodyQueue() {
this(4);
}
// Initializes this queue with an initial capacity. // Initializes this queue with an initial capacity.
// Precondition: initialCapacity > 0. // Precondition: initialCapacity > 0.
public BodyQueue(int initialCapacity) { public BodyQueue(int initialCapacity) {
this.capacity = initialCapacity;
//TODO: define constructor. this.queue = new Body[this.capacity];
} }
// Initializes this queue as an independent copy of the specified queue. // Initializes this queue as an independent copy of the specified queue.
@ -19,28 +26,50 @@ public class BodyQueue {
// and vice versa. // and vice versa.
// Precondition: q != null. // Precondition: q != null.
public BodyQueue(BodyQueue q) { public BodyQueue(BodyQueue q) {
this.capacity = q.capacity;
//TODO: define constructor. this.head = q.size();
this.tail = 0;
this.queue = new Body[this.capacity];
for (int i = 0; i < q.size(); i++) {
this.queue[i] = q.queue[i];
}
} }
// Adds the specified body 'b' to this queue. // Adds the specified body 'b' to this queue.
public void add(Body b) { public void add(Body b) {
queue[head] = b;
//TODO: implement method. head = (head + 1) % capacity;
if (head == tail) {
doubleCapacity();
head = capacity / 2;
}
} }
// Retrieves and removes the head of this queue, or returns 'null' // Retrieves and removes the head of this queue, or returns 'null'
// if this queue is empty. // if this queue is empty.
public Body poll() { public Body poll() {
if (tail == head) {
//TODO: implement method. return null;
return null; }
Body b = queue[tail];
queue[tail] = null;
tail = (tail + 1) % capacity;
return b;
} }
// Returns the number of bodies in this queue. // Returns the number of bodies in this queue.
public int size() { public int size() {
return (head - tail + capacity) % capacity;
}
//TODO: implement method. private void doubleCapacity() {
return -1; Body[] tmp = new Body[capacity * 2];
for (int i = head, j = 0; i < tail + capacity; i++, j++) {
tmp[j] = queue[i % capacity];
}
head = capacity;
tail = 0;
capacity *= 2;
queue = tmp;
} }
} }

View File

@ -41,14 +41,14 @@ public class Simulation {
public static void main(String[] args) { public static void main(String[] args) {
// simulation // simulation
CodeDraw cd = new CodeDraw(); CodeDraw cd = new CodeDraw();
Body[] bodies = new Body[NUMBER_OF_BODIES]; BodyQueue bodies = new BodyQueue();
Vector3[] forceOnBody = new Vector3[bodies.length]; BodyForceMap forceOnBody = new BodyForceMap();
Random random = new Random(2022); Random random = new Random(2022);
for (int i = 0; i < bodies.length; i++) { for (int i = 0; i < NUMBER_OF_BODIES; i++) {
bodies[i] = new Body( bodies.add(new Body(
Math.abs(random.nextGaussian()) * OVERALL_SYSTEM_MASS / bodies.length, // kg Math.abs(random.nextGaussian()) * OVERALL_SYSTEM_MASS / NUMBER_OF_BODIES, // kg
new Vector3( new Vector3(
0.2 * random.nextGaussian() * AU, 0.2 * random.nextGaussian() * AU,
0.2 * random.nextGaussian() * AU, 0.2 * random.nextGaussian() * AU,
@ -59,15 +59,21 @@ public class Simulation {
0 + random.nextGaussian() * 5e3, 0 + random.nextGaussian() * 5e3,
0 + random.nextGaussian() * 5e3 0 + random.nextGaussian() * 5e3
) )
); ));
} }
double seconds = 0; double seconds = 0;
// simulation loop // simulation loop
while (true) { 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. seconds++; // each iteration computes the movement of the celestial bodies within one second.
/*
// merge bodies that have collided // merge bodies that have collided
for (int i = 0; i < bodies.length; i++) { for (int i = 0; i < bodies.length; i++) {
for (int j = i + 1; j < bodies.length; j++) { for (int j = i + 1; j < bodies.length; j++) {
@ -86,22 +92,23 @@ public class Simulation {
} }
} }
} }
*/
// for each body (with index i): compute the total force exerted on it. // for each body (with index i): compute the total force exerted on it.
for (int i = 0; i < bodies.length; i++) { for (Body b1 : tmp) {
forceOnBody[i] = new Vector3(); // begin with zero Vector3 force = new Vector3(); // begin with zero
for (int j = 0; j < bodies.length; j++) { for (Body b2 : tmp) {
if (i != j) { if (b1 != b2) {
Vector3 forceToAdd = bodies[i].gravitationalForce(bodies[j]); force = force.plus(b1.gravitationalForce(b2));
forceOnBody[i] = forceOnBody[i].plus(forceToAdd);
} }
} }
forceOnBody.put(b1, force);
} }
// now forceOnBody[i] holds the force vector exerted on body with index i. // 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 each body (with index i): move it according to the total force exerted on it.
for (int i = 0; i < bodies.length; i++) { for (Body body : tmp) {
bodies[i].move(forceOnBody[i]); body.move(forceOnBody.get(body));
} }
// show all movements in the canvas only every hour (to speed up the simulation) // show all movements in the canvas only every hour (to speed up the simulation)
@ -110,7 +117,7 @@ public class Simulation {
cd.clear(Color.BLACK); cd.clear(Color.BLACK);
// draw new positions // draw new positions
for (Body body : bodies) { for (Body body : tmp) {
body.draw(cd); body.draw(cd);
} }
@ -118,6 +125,7 @@ public class Simulation {
cd.show(); cd.show();
} }
bodies = newBodies;
} }
} }