pub mod body; pub mod orbit; use self::body::*; use self::orbit::*; use serde::{Deserialize}; use crate::known_stars::*; use crate::ntree::NTree; use crate::ntree::NTreeNode; use crate::timeman::Second; use std::error::Error; pub const GRAVITATIONAL_CONSTANT: f64 = 6.67408e-20; pub type Kilograms = f64; pub type Kilometers = f64; pub type Percentage = f64; pub type Angle = f64; pub type SystemId = usize; #[derive(Debug, Deserialize)] pub struct CSVOrbitalBody { name: String, orbits: Option, 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 SolarSystem { id: SystemId, name: String, bodies: Vec, heirarchy: NTreeNode } impl SolarSystem { fn rebuild_system_heirarchy( bodies: &[OrbitalBody], root: &mut NTreeNode) { for body in bodies { if let Some(orbit) = body.orbit() { if orbit.parent() == *root.value() { let mut subtree = NTreeNode::new(body.id()); SolarSystem::rebuild_system_heirarchy(bodies, &mut subtree); root.insert_node(subtree); } } } } pub fn new_from_csv( id: SystemId, data: &'static str) -> Result> { let data_reader = stringreader::StringReader::new(data); let mut body_reader = csv::Reader::from_reader(data_reader); let mut bodies = Vec::::new(); for result in body_reader.deserialize() { let mut record: CSVOrbitalBody = result?; match record.orbits { Some(orbits) => { if record.sgp == 0.0 { record.sgp = (bodies[orbits].mass() + record.mass) * GRAVITATIONAL_CONSTANT; } } None => {} } //if record.radius == 0.0 { continue; } println!("New body: {:?}", record); bodies.push(OrbitalBody::new_from_record(bodies.len(), id, record)); } let mut heirarchy_root = NTreeNode::new(0); SolarSystem::rebuild_system_heirarchy(&bodies, &mut heirarchy_root); Ok(Self { id: id, name: bodies[0].name().clone(), bodies: bodies, heirarchy: heirarchy_root }) } pub fn new_from_known_star( id: SystemId, star: &'static str) -> Result> { let star_csv = match KNOWN_STARS.get(star).copied() { Some(csv) => csv, None => return Err(Box::new(StarNotFoundError { star: star })) }; SolarSystem::new_from_csv(id, star_csv) } pub fn id(&self) -> SystemId { self.id } pub fn name(&self) -> &String { &self.name } pub fn bodies(&self) -> &[OrbitalBody] { self.bodies.as_slice() } pub fn body(&self, id: BodyId) -> &OrbitalBody { &self.bodies[id] } pub fn heirarchy(&self) -> &NTreeNode { &self.heirarchy } pub fn body_position( &self, body: &OrbitalBody, time: Second) -> cgmath::Vector3 { body.absolute_position(self, time) } /*fn tick_tickables( to_tick: &mut [T], time_then: Second, time_now: Second) { let tick_interval = T::subtick_interval(); let time_then_offset = time_then % tick_interval; let time_now_offset = time_now % tick_interval; let tick_start = time_then + tick_interval - time_then_offset; let tick_end = time_now - time_now_offset; let num_ticks = (tick_end - tick_start) / tick_interval; for tick_i in 0..num_ticks+1 { let tick_second = tick_start + tick_i * tick_interval; to_tick.iter_mut().for_each(|v| { v.tick(tick_second); }); } if !T::tick_only_on_subtick() && tick_end != time_now { to_tick.iter_mut().for_each(|v| { v.tick(time_now); }); } }*/ }