lox_ephem/
lib.rs

1// SPDX-FileCopyrightText: 2024 Helge Eichhorn <git@helgeeichhorn.de>
2//
3// SPDX-License-Identifier: MPL-2.0
4
5use 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}