summaryrefslogblamecommitdiffstats
path: root/src/orbital.rs
blob: 178273ab4c147af2ffa05fc6a94a1c965daf02fe (plain) (tree)



































































































































































                                                                                                    
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
        }
    }
}