use super::units::*; use super::system::System; use std::vec::Vec; use std::rc::Rc; use std::cell::RefCell; pub struct Orbital { origin : Option, //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, 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 { 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 } } }