diff options
Diffstat (limited to 'src/solar_system.rs')
| -rw-r--r-- | src/solar_system.rs | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/solar_system.rs b/src/solar_system.rs new file mode 100644 index 0000000..e8137f0 --- /dev/null +++ b/src/solar_system.rs @@ -0,0 +1,161 @@ +use serde::{Deserialize}; +use crate::{known_stars::{KNOWN_STARS, StarNotFoundError}, timeman::Second}; +use std::error::Error; + +const GRAVITATIONAL_CONSTANT: f64 = 6.67408e-11; + +pub type Kilograms = f64; +pub type Kilometers = f64; +pub type Percentage = f64; +pub type Angle = f64; + +pub type BodyId = usize; +pub type SystemId = usize; + +#[derive(Debug, Deserialize)] +pub struct SerialOrbitalBody +{ + name: String, + orbits: BodyId, + mass: Kilograms, + radius: Kilometers, + + eccentricity: Percentage, + inclination: Angle, + long_asc_node: Angle, + long_periapsis: Angle, + sgp: f64, + mean_long: Angle, + + semi_major_axis: Kilometers, +} + +pub struct OrbitalBody +{ + body: SerialOrbitalBody, + position: Option<(Second, cgmath::Point3<Kilometers>)> +} + +pub struct SolarSystem +{ + name: String, + bodies: Vec<OrbitalBody>, +} + +impl SolarSystem +{ + pub fn new_from_csv( + data: &'static str) + -> Result<Self, Box<dyn Error>> { + let data_reader = stringreader::StringReader::new(data); + let mut body_reader = csv::Reader::from_reader(data_reader); + + let mut bodies = Vec::<OrbitalBody>::new(); + + for result in body_reader.deserialize() { + let record: SerialOrbitalBody = result?; + + println!("New body: {:?}", record); + + bodies.push(OrbitalBody { body: record, position: None }); + } + + Ok(Self { + name: bodies[0].name().clone(), + bodies: bodies, + }) + } + + pub fn new_from_known_star( + star: &'static str) + -> Result<Self, Box<dyn Error>> { + let star_csv = match KNOWN_STARS.get(star).copied() { + Some(csv) => csv, + None => return Err(Box::new(StarNotFoundError { star: star })) + }; + SolarSystem::new_from_csv(star_csv) + } + + pub fn name(&self) -> &String { &self.name } + + pub fn bodies(&self) + -> &[OrbitalBody] + { + self.bodies.as_slice() + } +} + +impl OrbitalBody +{ + pub fn name(&self) -> &String { &self.body.name } + pub fn radius(&self) -> f32 { self.body.radius as f32 } + + pub fn position(&self, time: Second) + -> Option<cgmath::Point3<Kilometers>> + { + match self.position { + Some((cache_time, pos)) => { + if time == cache_time { + return Some(pos); + } + return None; + }, + None => None + } + } + + fn calculate_orbit( + &self, + time: i64) + -> cgmath::Point3<Kilometers> { + cgmath::Point3 { x: 0.0, y: 0.0, z: 0.0 } + /*let arg_periapsis = self.long_periapsis - self.long_asc_node; + + + let mean_angular_motion: f64 = ( + self.sgp as f64 / (self.semi_major_axis as f64).powf(3.0) + ).sqrt(); + + let mean_anomaly = (self.mean_long - self.long_periapsis) + (mean_angular_motion * time as f64) as f32; + + let mut eccentric_anomaly = mean_anomaly + self.eccentricity * mean_anomaly.sin(); + for _ in 0..100 { + let new_eccentric = eccentric_anomaly + + (mean_anomaly - eccentric_anomaly + self.eccentricity * eccentric_anomaly.sin()) / + (1.0 - self.eccentricity * eccentric_anomaly.cos()); + if (new_eccentric - eccentric_anomaly).abs() < 1e-6 { + eccentric_anomaly = new_eccentric; + break; + } + eccentric_anomaly = new_eccentric; + } + + let beta = self.eccentricity / 1.0 + (1.0 - self.eccentricity * self.eccentricity).sqrt(); + let true_anomaly = eccentric_anomaly + 2.0 * + ((beta * eccentric_anomaly.sin()) / (1.0 - beta * eccentric_anomaly.cos())).atan(); + + let radius: f64 = self.semi_major_axis * (1.0 - self.eccentricity * eccentric_anomaly.cos()) as f64; + + let ohm_sin = self.long_asc_node.sin(); + let ohm_cos = self.long_asc_node.cos(); + + let inc_sin = self.inclination.sin(); + let inc_cos = self.inclination.cos(); + + let per_anom_sin = (arg_periapsis + true_anomaly).sin(); + let per_anom_cos = (arg_periapsis + true_anomaly).cos(); + + let x: f32 = (radius as f32) * ( + (ohm_cos * per_anom_cos) - + (ohm_sin * per_anom_sin * inc_cos)); + let y: f32 = (radius as f32) * ( + (ohm_sin * per_anom_cos) + + (ohm_cos * per_anom_sin * inc_cos)); + let z: f32 = (radius as f32) * (inc_sin * per_anom_sin); + + OrbitState { + position: cgmath::Vector3::new(x, y, z) + }*/ + } +} + |
