use units::{self, Eval};
use vector::Vector;
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub struct Body {
tick_time: units::Time,
mass: units::Mass,
position: Vector<units::Length>,
velocity: Vector<units::Velocity>,
new_acceleration: Vector<units::Acceleration>,
old_acceleration: Vector<units::Acceleration>,
}
impl Body {
pub fn new(tick_time: units::Time,
mass: units::Mass,
position: Vector<units::Length>,
velocity: Option<Vector<units::Velocity>>)
-> Body {
let default_velocity = Vector::new([units::Velocity::new(0.0); 3]);
let velocity = velocity.unwrap_or(default_velocity);
let acceleration = Vector::new([units::Acceleration::new(0.0); 3]);
Body {
tick_time: tick_time,
mass: mass,
position: position,
velocity: velocity,
new_acceleration: acceleration,
old_acceleration: acceleration,
}
}
pub fn get_position(&self) -> Vector<units::Length> {
self.position
}
pub fn display(&self) -> [f32; 3] {
let mut x = self.position.get().iter().map(|a| a.eval() as f32);
[x.next().unwrap(), x.next().unwrap(), x.next().unwrap()]
}
pub fn get_velocity(&self) -> Vector<units::Velocity> {
self.velocity
}
pub fn get_acceleration(&self) -> Vector<units::Acceleration> {
self.new_acceleration
}
pub fn tick(&mut self) {
let velocity_half: Vector<units::Velocity> = self.velocity
.get()
.iter()
.zip(self.old_acceleration.get().iter())
.map(|(v, a)| v.eval() + 0.5 * a.eval() * self.tick_time.eval())
.map(units::Velocity::new)
.collect();
self.position = self.position
.get()
.iter()
.zip(velocity_half.get().iter())
.map(|(x, v)| x.eval() + v.eval() * self.tick_time.eval())
.map(units::Length::new)
.collect();
self.velocity = velocity_half
.get()
.iter()
.zip(self.new_acceleration.get().iter())
.map(|(v, a)| v.eval() + 0.5 * a.eval() * self.tick_time.eval())
.map(units::Velocity::new)
.collect();
self.old_acceleration = self.new_acceleration;
self.new_acceleration = Vector::new([units::Acceleration::new(0.0); 3]);
}
fn apply_acceleration(&mut self, acceleration: Vector<units::Acceleration>) {
self.new_acceleration = self.new_acceleration + acceleration;
}
pub fn apply_force(&mut self, force: Vector<units::Force>) {
let acceleration = force
.get()
.iter()
.map(|f| f.acceleration_mass(self.mass))
.collect();
self.apply_acceleration(acceleration);
}
pub fn direction(&self, other: &Body) -> Vector<units::Length> {
Vector::displacement(&self.position, &other.position).normalize()
}
pub fn apply_force_towards(&mut self, other: &Body, force: units::Force) {
let direction = Body::direction(self, other);
let force = direction
.get()
.iter()
.map(|x| units::Force::new(x.eval() * force.eval()))
.collect();
self.apply_force(force);
}
}