celestial_pointing/terms/
altaz.rs1use 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}