summaryrefslogtreecommitdiffstats
path: root/src/orbital.rs
blob: 178273ab4c147af2ffa05fc6a94a1c965daf02fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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
        }
    }
}