Skip to main content

celestial_pointing/terms/
altaz.rs

1use super::{MountTypeFlags, Term};
2
3pub struct IA;
4pub struct IE;
5pub struct CA;
6pub struct NPAE;
7pub struct AN;
8pub struct AW;
9
10impl Term for IA {
11    fn name(&self) -> &str {
12        "IA"
13    }
14    fn description(&self) -> &str {
15        "Azimuth index error"
16    }
17    fn jacobian_equatorial(&self, _h: f64, _dec: f64, _lat: f64, _pier: f64) -> (f64, f64) {
18        (0.0, 0.0)
19    }
20    fn jacobian_altaz(&self, _az: f64, _el: f64, _lat: f64) -> (f64, f64) {
21        (-1.0, 0.0)
22    }
23    fn applicable_mounts(&self) -> MountTypeFlags {
24        MountTypeFlags::ALTAZ
25    }
26}
27
28impl Term for IE {
29    fn name(&self) -> &str {
30        "IE"
31    }
32    fn description(&self) -> &str {
33        "Elevation index error"
34    }
35    fn jacobian_equatorial(&self, _h: f64, _dec: f64, _lat: f64, _pier: f64) -> (f64, f64) {
36        (0.0, 0.0)
37    }
38    fn jacobian_altaz(&self, _az: f64, _el: f64, _lat: f64) -> (f64, f64) {
39        (0.0, 1.0)
40    }
41    fn applicable_mounts(&self) -> MountTypeFlags {
42        MountTypeFlags::ALTAZ
43    }
44}
45
46impl Term for CA {
47    fn name(&self) -> &str {
48        "CA"
49    }
50    fn description(&self) -> &str {
51        "Left-right collimation error"
52    }
53    fn jacobian_equatorial(&self, _h: f64, _dec: f64, _lat: f64, _pier: f64) -> (f64, f64) {
54        (0.0, 0.0)
55    }
56    fn jacobian_altaz(&self, _az: f64, el: f64, _lat: f64) -> (f64, f64) {
57        (-1.0 / libm::cos(el), 0.0)
58    }
59    fn applicable_mounts(&self) -> MountTypeFlags {
60        MountTypeFlags::ALTAZ
61    }
62}
63
64impl Term for NPAE {
65    fn name(&self) -> &str {
66        "NPAE"
67    }
68    fn description(&self) -> &str {
69        "Non-perpendicularity of az/el axes"
70    }
71    fn jacobian_equatorial(&self, _h: f64, _dec: f64, _lat: f64, _pier: f64) -> (f64, f64) {
72        (0.0, 0.0)
73    }
74    fn jacobian_altaz(&self, _az: f64, el: f64, _lat: f64) -> (f64, f64) {
75        (-libm::tan(el), 0.0)
76    }
77    fn applicable_mounts(&self) -> MountTypeFlags {
78        MountTypeFlags::ALTAZ
79    }
80}
81
82impl Term for AN {
83    fn name(&self) -> &str {
84        "AN"
85    }
86    fn description(&self) -> &str {
87        "Azimuth axis tilt north-south"
88    }
89    fn jacobian_equatorial(&self, _h: f64, _dec: f64, _lat: f64, _pier: f64) -> (f64, f64) {
90        (0.0, 0.0)
91    }
92    fn jacobian_altaz(&self, az: f64, el: f64, _lat: f64) -> (f64, f64) {
93        (-libm::sin(az) * libm::tan(el), libm::cos(az))
94    }
95    fn applicable_mounts(&self) -> MountTypeFlags {
96        MountTypeFlags::ALTAZ
97    }
98}
99
100impl Term for AW {
101    fn name(&self) -> &str {
102        "AW"
103    }
104    fn description(&self) -> &str {
105        "Azimuth axis tilt east-west"
106    }
107    fn jacobian_equatorial(&self, _h: f64, _dec: f64, _lat: f64, _pier: f64) -> (f64, f64) {
108        (0.0, 0.0)
109    }
110    fn jacobian_altaz(&self, az: f64, el: f64, _lat: f64) -> (f64, f64) {
111        (-libm::cos(az) * libm::tan(el), -libm::sin(az))
112    }
113    fn applicable_mounts(&self) -> MountTypeFlags {
114        MountTypeFlags::ALTAZ
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use std::f64::consts::{FRAC_PI_2, FRAC_PI_4};
122
123    #[test]
124    fn ia_jacobian() {
125        let (da, de) = IA.jacobian_altaz(0.0, 0.0, 0.0);
126        assert_eq!(da, -1.0);
127        assert_eq!(de, 0.0);
128    }
129
130    #[test]
131    fn ie_jacobian() {
132        let (da, de) = IE.jacobian_altaz(0.0, 0.0, 0.0);
133        assert_eq!(da, 0.0);
134        assert_eq!(de, 1.0);
135    }
136
137    #[test]
138    fn ca_at_zero_el() {
139        let (da, de) = CA.jacobian_altaz(0.0, 0.0, 0.0);
140        assert_eq!(da, -1.0);
141        assert_eq!(de, 0.0);
142    }
143
144    #[test]
145    fn npae_at_zero_el() {
146        let (da, de) = NPAE.jacobian_altaz(0.0, 0.0, 0.0);
147        assert_eq!(da, 0.0);
148        assert_eq!(de, 0.0);
149    }
150
151    #[test]
152    fn npae_at_45_el() {
153        let el = FRAC_PI_4;
154        let (da, de) = NPAE.jacobian_altaz(0.0, el, 0.0);
155        assert_eq!(da, -el.tan());
156        assert_eq!(de, 0.0);
157    }
158
159    #[test]
160    fn an_at_pi_over_2_az() {
161        let az = FRAC_PI_2;
162        let el = FRAC_PI_4;
163        let (da, de) = AN.jacobian_altaz(az, el, 0.0);
164        assert_eq!(da, -libm::sin(az) * el.tan());
165        assert_eq!(de, libm::cos(az));
166    }
167
168    #[test]
169    fn aw_at_zero_az() {
170        let el = FRAC_PI_4;
171        let (da, de) = AW.jacobian_altaz(0.0, el, 0.0);
172        assert_eq!(da, -el.tan());
173        assert_eq!(de, 0.0);
174    }
175
176    #[test]
177    fn altaz_terms_return_zero_for_equatorial() {
178        let terms: Vec<Box<dyn Term>> = vec![
179            Box::new(IA),
180            Box::new(IE),
181            Box::new(CA),
182            Box::new(NPAE),
183            Box::new(AN),
184            Box::new(AW),
185        ];
186        for term in &terms {
187            let (dh, dd) = term.jacobian_equatorial(1.0, 0.5, 0.7, 1.0);
188            assert_eq!(
189                (dh, dd),
190                (0.0, 0.0),
191                "term {} should return (0,0) for equatorial",
192                term.name()
193            );
194        }
195    }
196
197    #[test]
198    fn no_altaz_terms_are_pier_sensitive() {
199        assert!(!IA.pier_sensitive());
200        assert!(!IE.pier_sensitive());
201        assert!(!CA.pier_sensitive());
202        assert!(!NPAE.pier_sensitive());
203        assert!(!AN.pier_sensitive());
204        assert!(!AW.pier_sensitive());
205    }
206}