Skip to main content

celestial_pointing/terms/
mod.rs

1pub mod altaz;
2pub mod equatorial;
3pub mod harmonic;
4
5use crate::error::{Error, Result};
6use bitflags::bitflags;
7
8bitflags! {
9    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
10    pub struct MountTypeFlags: u8 {
11        const EQUATORIAL = 0b001;
12        const ALTAZ = 0b010;
13        const ALL = 0b111;
14    }
15}
16
17pub trait Term: Send + Sync {
18    fn name(&self) -> &str;
19    fn description(&self) -> &str;
20
21    fn jacobian_equatorial(&self, h: f64, dec: f64, lat: f64, pier: f64) -> (f64, f64);
22    fn jacobian_altaz(&self, az: f64, el: f64, lat: f64) -> (f64, f64);
23
24    fn pier_sensitive(&self) -> bool {
25        false
26    }
27    fn applicable_mounts(&self) -> MountTypeFlags;
28}
29
30pub fn create_term(name: &str) -> Result<Box<dyn Term>> {
31    match name.to_uppercase().as_str() {
32        "IH" => Ok(Box::new(equatorial::IH)),
33        "ID" => Ok(Box::new(equatorial::ID)),
34        "CH" => Ok(Box::new(equatorial::CH)),
35        "NP" => Ok(Box::new(equatorial::NP)),
36        "MA" => Ok(Box::new(equatorial::MA)),
37        "ME" => Ok(Box::new(equatorial::ME)),
38        "TF" => Ok(Box::new(equatorial::TF)),
39        "TX" => Ok(Box::new(equatorial::TX)),
40        "DAF" => Ok(Box::new(equatorial::DAF)),
41        "FO" => Ok(Box::new(equatorial::FO)),
42        "HCES" => Ok(Box::new(equatorial::HCES)),
43        "HCEC" => Ok(Box::new(equatorial::HCEC)),
44        "DCES" => Ok(Box::new(equatorial::DCES)),
45        "DCEC" => Ok(Box::new(equatorial::DCEC)),
46        "IA" => Ok(Box::new(altaz::IA)),
47        "IE" => Ok(Box::new(altaz::IE)),
48        "CA" => Ok(Box::new(altaz::CA)),
49        "NPAE" => Ok(Box::new(altaz::NPAE)),
50        "AN" => Ok(Box::new(altaz::AN)),
51        "AW" => Ok(Box::new(altaz::AW)),
52        name if name.starts_with('H') => {
53            let spec = harmonic::parse_harmonic(name)?;
54            Ok(Box::new(spec))
55        }
56        _ => Err(Error::UnknownTerm(name.to_string())),
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn create_known_equatorial_terms() {
66        let names = [
67            "IH", "ID", "CH", "NP", "MA", "ME", "TF", "TX", "DAF", "FO", "HCES", "HCEC", "DCES",
68            "DCEC",
69        ];
70        for name in &names {
71            let term = create_term(name).unwrap();
72            assert_eq!(term.name(), *name);
73            assert_eq!(term.applicable_mounts(), MountTypeFlags::EQUATORIAL);
74        }
75    }
76
77    #[test]
78    fn create_known_altaz_terms() {
79        let names = ["IA", "IE", "CA", "NPAE", "AN", "AW"];
80        for name in &names {
81            let term = create_term(name).unwrap();
82            assert_eq!(term.name(), *name);
83            assert_eq!(term.applicable_mounts(), MountTypeFlags::ALTAZ);
84        }
85    }
86
87    #[test]
88    fn create_harmonic_term() {
89        let term = create_term("HDSH").unwrap();
90        assert_eq!(term.name(), "HDSH");
91        assert_eq!(term.applicable_mounts(), MountTypeFlags::EQUATORIAL);
92    }
93
94    #[test]
95    fn unknown_term_returns_error() {
96        let result = create_term("ZZZZ");
97        assert!(result.is_err());
98    }
99
100    #[test]
101    fn case_insensitive_lookup() {
102        let term = create_term("ih").unwrap();
103        assert_eq!(term.name(), "IH");
104    }
105}