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
|
pub mod body;
pub mod ship;
pub mod orbit;
use self::body::*;
use self::ship::*;
use self::orbit::*;
use serde::{Deserialize};
use crate::known_stars::*;
use crate::timeman::Second;
use std::error::Error;
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<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 SolarSystem
{
id: SystemId,
name: String,
bodies: Vec<OrbitalBody>,
ships: Vec<Ship>
}
impl SolarSystem
{
pub fn new_from_csv(
id: SystemId,
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 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(), record));
}
Ok(Self {
id: id,
name: bodies[0].name().clone(),
bodies: bodies,
ships: vec![]
})
}
pub fn new_from_known_star(
id: SystemId,
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(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_position(
&self,
body: &OrbitalBody)
-> cgmath::Vector3<Kilometers>
{
body.absolute_position(self)
}
pub fn update(
&mut self,
time: Second)
{
self.bodies.iter_mut().for_each(|body| {
body.update(time);
});
}
}
|