use super::units::*;
use super::system::System;
use std::vec::Vec;
use std::rc::Rc;
use std::cell::RefCell;
pub struct Orbital
{
origin : Option<usize>,
//Euler angles for a given time (T) relative to origin
rel_pos : Option<(Second, Meter, Rad, Rad, Rad)>,
//Position for a given time (T) in absolute system coordinates
abs_pos : Option<(Second, Meter, Meter, Meter)>,
name : String,
//Physical parameters
mass : Kilogram,
radius : Meter,
//Orbital parameters
semi_major_axis : Meter,
eccentricity : f64,
inclination : Rad,
longitude_asc_node : Rad,
argument_periapsis : Rad,
mean_anomaly_epoch : Rad,
}
pub struct OrbitalBuilder
{
origin : Option<usize>,
name : String,
mass : Kilogram,
radius : Meter,
semi_major_axis : Meter,
eccentricity : f64,
inclination : Rad,
longitude_asc_node : Rad,
argument_periapsis : Rad,
mean_anomaly_epoch : Rad,
}
impl Orbital
{
pub fn tick(&mut self,
origin : &mut Orbital,
t : Second)
{
match self.rel_pos {
None => {},
Some(rel_pos) => {
if rel_pos.0 == t { return; }
}
}
let origin_mass = origin.mass;
let std_grav_param = GRAVITATIONAL_CONSTANT * (origin_mass + self.mass);
let mean_angular_motion = f64::sqrt(std_grav_param / self.semi_major_axis.powi(3));
let mean_anomaly = self.mean_anomaly_epoch + (mean_angular_motion * t as f64);
let mut eccentric_anomaly = mean_anomaly;
loop {
let de = (eccentric_anomaly -
self.eccentricity * eccentric_anomaly.sin() -
mean_anomaly) /
(1.0 - self.eccentricity * eccentric_anomaly.cos());
eccentric_anomaly -= de;
if de.abs() < 1e6 { break; }
}
//True anomaly
let beta = self.eccentricity /
(1.0 + f64::sqrt(1.0 - self.eccentricity.powi(2)));
let true_anomaly = eccentric_anomaly * 2.0 *
f64::atan((beta * eccentric_anomaly.sin()) /
(1.0 - beta * eccentric_anomaly.cos()));
let distance = self.semi_major_axis *
(1.0 - self.eccentricity * eccentric_anomaly.cos());
self.rel_pos = Some((t, distance, self.longitude_asc_node, self.inclination, true_anomaly));
println!("{0:?}", self.rel_pos.unwrap());
}
pub fn pos(&mut self,
system : &System,
t : Second)
-> (Meter, Meter, Meter)
{
(0.0, 0.0, 0.0)
}
pub fn name(&self) -> &String { &self.name }
pub fn origin(&self) -> Option<usize> { self.origin }
}
impl OrbitalBuilder
{
pub fn new() -> OrbitalBuilder {
OrbitalBuilder {
origin : None,
name : "".to_string(),
mass : 0.0,
radius : 0.0,
semi_major_axis : 0.0,
eccentricity : 0.0,
inclination : 0.0,
longitude_asc_node : 0.0,
argument_periapsis : 0.0,
mean_anomaly_epoch : 0.0,
}
}
pub fn orbits(mut self, parent : usize) -> OrbitalBuilder
{ self.origin = Some(parent); self }
pub fn name(mut self, name : String) -> OrbitalBuilder
{ self.name = name; self }
pub fn mass(mut self, mass : Kilogram) -> OrbitalBuilder
{ self.mass = mass; self }
pub fn radius(mut self, radius : Meter) -> OrbitalBuilder
{ self.radius = radius; self }
pub fn semi_major_axis(mut self, sma : Meter) -> OrbitalBuilder
{ self.semi_major_axis = sma; self }
pub fn eccentricity(mut self, e : Rad) -> OrbitalBuilder
{ self.eccentricity = e; self }
pub fn inclination(mut self, i : Rad) -> OrbitalBuilder
{ self.inclination = i; self }
pub fn long_asc_node(mut self, omega : Rad) -> OrbitalBuilder
{ self.longitude_asc_node = omega; self }
pub fn argument_periapsis(mut self, w : Rad) -> OrbitalBuilder
{ self.argument_periapsis = w; self }
pub fn mean_anomaly_epoch(mut self, mean_anomaly : Rad) -> OrbitalBuilder
{ self.mean_anomaly_epoch = mean_anomaly; self }
pub fn build(self) -> Orbital
{
Orbital {
origin : self.origin,
rel_pos : None,
abs_pos : None,
name : self.name,
mass : self.mass,
radius : self.radius,
semi_major_axis : self.semi_major_axis,
eccentricity : self.eccentricity,
inclination : self.inclination,
longitude_asc_node : self.longitude_asc_node,
argument_periapsis : self.argument_periapsis,
mean_anomaly_epoch : self.mean_anomaly_epoch
}
}
}