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);
}
public double mass() {
return mass;
}
// 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'.
public Body merge(Body b) {

View File

@ -3,21 +3,55 @@
//
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.
// Precondition: initialCapacity > 0.
public BodyForceMap(int initialCapacity) {
//TODO: define constructor.
this.capacity = initialCapacity;
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,
// the value is replaced and the old value is returned. Otherwise 'null' is returned.
// Precondition: key != null.
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;
}
@ -25,8 +59,52 @@ public class BodyForceMap {
// associated with the specified body. Returns 'null' if the key is not contained in this map.
// Precondition: key != null.
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;
}
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 {
//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.
// Precondition: initialCapacity > 0.
public BodyQueue(int initialCapacity) {
//TODO: define constructor.
this.capacity = initialCapacity;
this.queue = new Body[this.capacity];
}
// Initializes this queue as an independent copy of the specified queue.
@ -19,28 +26,50 @@ public class BodyQueue {
// and vice versa.
// Precondition: q != null.
public BodyQueue(BodyQueue q) {
//TODO: define constructor.
this.capacity = q.capacity;
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.
public void add(Body b) {
//TODO: implement method.
queue[head] = b;
head = (head + 1) % capacity;
if (head == tail) {
doubleCapacity();
head = capacity / 2;
}
}
// Retrieves and removes the head of this queue, or returns 'null'
// if this queue is empty.
public Body poll() {
//TODO: implement method.
if (tail == head) {
return null;
}
Body b = queue[tail];
queue[tail] = null;
tail = (tail + 1) % capacity;
return b;
}
// Returns the number of bodies in this queue.
public int size() {
return (head - tail + capacity) % capacity;
}
//TODO: implement method.
return -1;
private void doubleCapacity() {
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) {
// simulation
CodeDraw cd = new CodeDraw();
Body[] bodies = new Body[NUMBER_OF_BODIES];
Vector3[] forceOnBody = new Vector3[bodies.length];
BodyQueue bodies = new BodyQueue();
BodyForceMap forceOnBody = new BodyForceMap();
Random random = new Random(2022);
for (int i = 0; i < bodies.length; i++) {
bodies[i] = new Body(
Math.abs(random.nextGaussian()) * OVERALL_SYSTEM_MASS / bodies.length, // kg
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,
@ -59,15 +59,21 @@ public class Simulation {
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++) {
@ -86,22 +92,23 @@ public class Simulation {
}
}
}
*/
// for each body (with index i): compute the total force exerted on it.
for (int i = 0; i < bodies.length; i++) {
forceOnBody[i] = new Vector3(); // begin with zero
for (int j = 0; j < bodies.length; j++) {
if (i != j) {
Vector3 forceToAdd = bodies[i].gravitationalForce(bodies[j]);
forceOnBody[i] = forceOnBody[i].plus(forceToAdd);
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 (int i = 0; i < bodies.length; i++) {
bodies[i].move(forceOnBody[i]);
for (Body body : tmp) {
body.move(forceOnBody.get(body));
}
// 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);
// draw new positions
for (Body body : bodies) {
for (Body body : tmp) {
body.draw(cd);
}
@ -118,6 +125,7 @@ public class Simulation {
cd.show();
}
bodies = newBodies;
}
}