134 lines
4.6 KiB
Java
134 lines
4.6 KiB
Java
import codedraw.CodeDraw;
|
|
|
|
/**
|
|
* This class represents celestial bodies like stars, planets, asteroids, etc...
|
|
*/
|
|
public class Body {
|
|
private double mass;
|
|
private Vector massCenter; // position of the mass center.
|
|
private Vector currentMovement;
|
|
|
|
public Body(double mass, Vector massCenter, Vector currentMovement) {
|
|
this.mass = mass;
|
|
this.massCenter = massCenter;
|
|
this.currentMovement = currentMovement;
|
|
}
|
|
|
|
public Body(double mass, Vector massCenter) {
|
|
this(mass, massCenter, new Vector());
|
|
}
|
|
|
|
public Body(Body other) {
|
|
this(other.mass, new Vector(other.massCenter), new Vector(other.currentMovement));
|
|
}
|
|
|
|
/**
|
|
* Returns the distance between the mass centers of this body and the specified body 'b'.
|
|
*/
|
|
public double distanceTo(Body b) {
|
|
return massCenter.distanceTo(b.massCenter);
|
|
}
|
|
|
|
/**
|
|
* Returns a vector representing the gravitational force exerted by 'b' on this body.
|
|
* The gravitational Force F is calculated by F = G*(m1*m2)/(r*r), with m1 and m2 being the
|
|
* masses of the objects interacting, r being the distance between the centers of the masses
|
|
* and G being the gravitational constant.
|
|
* Hint: see simulation loop in Simulation.java to find out how this is done.
|
|
*/
|
|
public Vector gravitationalForce(Body b) {
|
|
Vector direction = b.massCenter.minus(massCenter);
|
|
double distance = direction.length();
|
|
if (distance == 0) return new Vector();
|
|
direction.normalize();
|
|
double force = Simulation.G * mass * b.mass / (distance * distance);
|
|
return direction.times(force);
|
|
}
|
|
|
|
/**
|
|
* Moves this body to a new position, according to the specified force vector 'force' exerted
|
|
* on it, and updates the current movement accordingly.
|
|
* (Movement depends on the mass of this body, its current movement and the exerted force.)
|
|
* Hint: see simulation loop in Simulation.java to find out how this is done.
|
|
*/
|
|
public void move(Vector force) {
|
|
// F = m*a -> a = F/m
|
|
Vector newPosition = massCenter.plus(force.times(1.0 / mass)).plus(currentMovement);
|
|
|
|
// new minus old position.
|
|
Vector newMovement = newPosition.minus(massCenter);
|
|
|
|
// update body state
|
|
massCenter = newPosition;
|
|
currentMovement = newMovement;
|
|
}
|
|
|
|
/**
|
|
* Returns the approximate radius of this body.
|
|
* (It is assumed that the radius r is related to the mass m of the body by r = m ^ 0.5,
|
|
* where m and r measured in solar units.)
|
|
*/
|
|
public double radius() {
|
|
return SpaceDraw.massToRadius(mass);
|
|
}
|
|
|
|
/**
|
|
* Return the mass of the Body.
|
|
*/
|
|
public double mass() {
|
|
return mass;
|
|
}
|
|
|
|
public Vector massCenter() {
|
|
return massCenter;
|
|
}
|
|
|
|
public void update(Body b) {
|
|
double combinedMass = this.mass + b.mass;
|
|
this.massCenter = this.massCenter.times(this.mass / combinedMass).plus(b.massCenter.times(b.mass / combinedMass));
|
|
this.mass = combinedMass;
|
|
}
|
|
|
|
public boolean collidesWith(Body body) {
|
|
return this.distanceTo(body) < this.radius() + body.radius();
|
|
}
|
|
|
|
/**
|
|
* 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 body) {
|
|
double totalMass = this.mass + body.mass;
|
|
return new Body(
|
|
totalMass,
|
|
this.massCenter.times(this.mass).plus(body.massCenter.times(body.mass)).times(1.0 / totalMass),
|
|
this.currentMovement.times(this.mass).plus(body.currentMovement.times(body.mass)).times(1.0 / totalMass)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Draws the body to the specified canvas as a filled circle.
|
|
* The radius of the circle corresponds to the radius of the body
|
|
* (use a conversion of the real scale to the scale of the canvas as
|
|
* in 'Simulation.java').
|
|
* Hint: call the method 'drawAsFilledCircle' implemented in 'Vector'.
|
|
*/
|
|
public void draw(CodeDraw cd) {
|
|
cd.setColor(SpaceDraw.massToColor(mass));
|
|
massCenter.drawAsFilledCircle(cd, SpaceDraw.massToRadius(mass));
|
|
}
|
|
|
|
/**
|
|
* Returns a string with the information about this body including
|
|
* mass, position (mass center) and current movement. Example:
|
|
* "5.972E24 kg, position: [1.48E11,0.0,0.0] m, movement: [0.0,29290.0,0.0] m/s."
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
return String.format(
|
|
"%g kg, position: %s m, movement: %s m/s.",
|
|
mass, massCenter.toString(), currentMovement.toString()
|
|
);
|
|
}
|
|
}
|