summaryrefslogtreecommitdiffstats
path: root/src/solar_system.rs
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-04-15 16:53:58 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-04-15 16:53:58 -0400
commitb5ced3af46c96ceb959fbbf1addfeba3bd4f76d5 (patch)
tree06d06fc9562dc99eede655b53635576f67c37e3b /src/solar_system.rs
downloadsystemic4x-b5ced3af46c96ceb959fbbf1addfeba3bd4f76d5.tar.gz
systemic4x-b5ced3af46c96ceb959fbbf1addfeba3bd4f76d5.tar.bz2
systemic4x-b5ced3af46c96ceb959fbbf1addfeba3bd4f76d5.zip
first commit. working body rendering
Diffstat (limited to 'src/solar_system.rs')
-rw-r--r--src/solar_system.rs161
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)
+ }*/
+ }
+}
+