1use lox_core::types::julian_dates::Epoch;
6
7pub mod spk;
8
9pub(crate) type Position = (f64, f64, f64);
10pub(crate) type Velocity = (f64, f64, f64);
11pub(crate) type Body = i32;
12
13pub trait Ephemeris {
14 type Error: std::error::Error;
15
16 fn position(&self, epoch: Epoch, origin: Body, target: Body) -> Result<Position, Self::Error>;
17 fn velocity(&self, epoch: Epoch, origin: Body, target: Body) -> Result<Velocity, Self::Error>;
18 fn state(
19 &self,
20 epoch: Epoch,
21 origin: Body,
22 target: Body,
23 ) -> Result<(Position, Velocity), Self::Error>;
24}
25
26fn ancestors(id: i32) -> Vec<i32> {
27 let mut ancestors = vec![id];
28 let mut current = id;
29 while current != 0 {
30 current /= 100;
31 ancestors.push(current);
32 }
33 ancestors
34}
35
36pub fn path_from_ids(origin: i32, target: i32) -> Vec<i32> {
37 let ancestors_origin = ancestors(origin);
38 let ancestors_target = ancestors(target);
39 let n = ancestors_target.len();
40 let mut path = ancestors_origin;
41
42 ancestors_target
43 .into_iter()
44 .take(n - 1)
45 .rev()
46 .for_each(|id| path.push(id));
47
48 if *path.first().unwrap() != 0 && *path.last().unwrap() != 0 {
49 let idx = path.iter().position(|&id| id == 0).unwrap();
50 if path[idx - 1] == path[idx + 1] {
51 let common_ancestor = vec![path[idx - 1]];
52 path.splice((idx - 1)..=(idx + 1), common_ancestor);
53 }
54 }
55
56 path
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_ancestors() {
65 assert_eq!(ancestors(0), vec![0]);
66 assert_eq!(ancestors(3), vec![3, 0]);
67 assert_eq!(ancestors(399), vec![399, 3, 0]);
68 }
69
70 #[test]
71 fn test_path_from_ids() {
72 assert_eq!(path_from_ids(399, 499), [399, 3, 0, 4, 499]);
73 assert_eq!(path_from_ids(399, 0), [399, 3, 0]);
74 assert_eq!(path_from_ids(0, 399), [0, 3, 399]);
75 assert_eq!(path_from_ids(399, 3), [399, 3]);
76 assert_eq!(path_from_ids(3, 399), [3, 399]);
77 assert_eq!(path_from_ids(399, 301), [399, 3, 301]);
78 }
79}