1use crate::libs::{
4 angle::AbstractAngle,
5 cs::{
6 abstracts::{AbstractMathCs3, AbstractSignStrExt},
7 model::Cs,
8 },
9 tolerance,
10};
11
12impl AbstractMathCs3 for Cs<3> {
13 #[rustfmt::skip] #[inline] fn rxy(&self) -> f64 { self.0[0].hypot(self.0[1]) }
16
17 #[rustfmt::skip] #[inline] fn rxz(&self) -> f64 { self.0[0].hypot(self.0[2]) }
20
21 #[rustfmt::skip] #[inline] fn ryz(&self) -> f64 { self.0[1].hypot(self.0[2]) }
24
25 #[rustfmt::skip] #[inline] fn rxyz(&self) -> f64 { self.0[0].hypot(self.0[1]).hypot(self.0[2]) }
28
29 #[rustfmt::skip] #[inline] fn arctan_y_x(&self) -> f64 { self.0[1].atan2(self.0[0]) }
34
35 #[rustfmt::skip] #[inline] fn arctan_z_x(&self) -> f64 { self.0[2].atan2(self.0[0]) }
38
39 #[rustfmt::skip] #[inline] fn arctan_z_y(&self) -> f64 { self.0[2].atan2(self.0[1]) }
42
43 #[rustfmt::skip] #[inline] fn arctan_x_y(&self) -> f64 { self.0[0].atan2(self.0[1]) }
48
49 #[rustfmt::skip] #[inline] fn arctan_x_z(&self) -> f64 { self.0[0].atan2(self.0[2]) }
52
53 #[rustfmt::skip] #[inline] fn arctan_y_z(&self) -> f64 { self.0[1].atan2(self.0[2]) }
56
57 #[rustfmt::skip] #[inline] fn arccos_x_rxyz(&self) -> f64 { let r = self.rxyz(); if tolerance::is_zero(r) { 0.0 } else { (self.0[0] / r).clamp(-1.0, 1.0).acos() } }
62
63 #[rustfmt::skip] #[inline] fn arccos_y_rxyz(&self) -> f64 { let r = self.rxyz(); if tolerance::is_zero(r) { 0.0 } else { (self.0[1] / r).clamp(-1.0, 1.0).acos() } }
66
67 #[rustfmt::skip] #[inline] fn arccos_z_rxyz(&self) -> f64 { let r = self.rxyz(); if tolerance::is_zero(r) { 0.0 } else { (self.0[2] / r).clamp(-1.0, 1.0).acos() } }
70
71 #[rustfmt::skip] #[inline] fn to_rf_from_xy(&self) -> Cs<2> { Cs([self.rxy(), self.arctan_y_x()]) }
76
77 #[rustfmt::skip] #[inline] fn to_rf_from_xz(&self) -> Cs<2> { Cs([self.rxz(), self.arctan_z_x()]) }
80
81 #[rustfmt::skip] #[inline] fn to_rf_from_yz(&self) -> Cs<2> { Cs([self.ryz(), self.arctan_z_y()]) }
84
85 #[rustfmt::skip] #[inline] fn to_rfx_from_xyz(&self) -> Cs<3> { Cs([self.ryz(), self.arctan_z_y(), self.0[0]]) }
90
91 #[rustfmt::skip] #[inline] fn to_rfy_from_xyz(&self) -> Cs<3> { Cs([self.rxz(), self.arctan_z_x(), self.0[1]]) }
94
95 #[rustfmt::skip] #[inline] fn to_rfz_from_xyz(&self) -> Cs<3> { Cs([self.rxy(), self.arctan_y_x(), self.0[2]]) }
98
99 #[rustfmt::skip] #[inline] fn to_rft_from_xyz(&self) -> Cs<3> { Cs([self.rxyz(), self.arctan_y_x(), self.arccos_z_rxyz()]) }
102
103 #[rustfmt::skip]
108 fn to_ecef_from_dms_sn_we(
109 sn_d: i16, sn_m: u8, sn_s: f32,
110 we_d: i16, we_m: u8, we_s: f32,
111 r: f64
112 ) -> Self {
113 use crate::libs::angle::Angle;
114 let lat_rad = Angle::from_dms(sn_d, sn_m, sn_s).rad();
115 let lon_rad = Angle::from_dms(we_d, we_m, we_s).rad();
116
117 let (sin_lat, cos_lat) = lat_rad.sin_cos();
118 let (sin_lon, cos_lon) = lon_rad.sin_cos();
119
120 Cs([
121 r * cos_lat * cos_lon,
122 r * cos_lat * sin_lon,
123 r * sin_lat
124 ])
125 }
126
127 #[rustfmt::skip]
130 fn to_dms_sn_we_from_xyz(&self) -> crate::libs::cs::model::CoordsSphericalEcefSnWeDms {
131 use crate::libs::angle::Angle;
132 use crate::libs::tolerance;
133
134 let r = self.rxyz();
135
136 let (lat_rad, lon_rad) = if tolerance::is_zero(r) {
138 (0.0, 0.0)
139 } else {
140 (
141 (self.0[2] / r).clamp(-1.0, 1.0).asin(), self.0[1].atan2(self.0[0]) )
144 };
145
146 let lat_angle = Angle::from_rad(lat_rad);
148 let lon_angle = Angle::from_rad(lon_rad);
149
150 let (lat_d, lat_m, lat_s) = lat_angle.to_dms();
152 let (lon_d, lon_m, lon_s) = lon_angle.to_dms();
153
154 crate::libs::cs::model::CoordsSphericalEcefSnWeDms {
156 sn_lat_d: lat_d as i8,
157 sn_lat_m: lat_m,
158 sn_lat_s: lat_s,
159 we_lon_d: lon_d,
160 we_lon_m: lon_m,
161 we_lon_s: lon_s,
162 }
163 }
164
165 #[rustfmt::skip] #[inline]
170 fn q(&self) -> u8 {
171 match (self.0[0] >= 0.0, self.0[1] >= 0.0, self.0[2] >= 0.0) {
172 (true, true, true) => 1, (false, true, true) => 2, (false, false, true) => 3, (true, false, true) => 4,
173 (true, true, false) => 5, (false, true, false) => 6, (false, false, false)=> 7, (true, false, false) => 8,
174 }
175 }
176
177 #[rustfmt::skip] #[inline]
180 fn q_sign(&self) -> [&'static str; 3] {
181 [self.0[0].sign_str(), self.0[1].sign_str(), self.0[2].sign_str()]
182 }
183
184 #[rustfmt::skip] #[inline] fn rxyz_sq(&self) -> f64 { self.0[0] * self.0[0] + self.0[1] * self.0[1] + self.0[2] * self.0[2] }
187
188 #[rustfmt::skip] #[inline] fn rxy_sq(&self) -> f64 { self.0[0] * self.0[0] + self.0[1] * self.0[1] }
191
192 #[rustfmt::skip] #[inline] fn rxz_sq(&self) -> f64 { self.0[0] * self.0[0] + self.0[2] * self.0[2] }
195
196 #[rustfmt::skip] #[inline] fn ryz_sq(&self) -> f64 { self.0[1] * self.0[1] + self.0[2] * self.0[2] }
199
200 #[rustfmt::skip] #[inline]
205 fn normalize_rxy_projection(&self) -> Cs<3> {
206 let r = self.rxy();
207 if tolerance::is_zero(r) { Cs([0.0, 0.0, self.0[2]]) } else { Cs([self.0[0] / r, self.0[1] / r, self.0[2]]) }
208 }
209
210 #[rustfmt::skip] #[inline]
213 fn normalize_rxz_projection(&self) -> Cs<3> {
214 let r = self.rxz();
215 if tolerance::is_zero(r) { Cs([0.0, self.0[1], 0.0]) } else { Cs([self.0[0] / r, self.0[1], self.0[2] / r]) }
216 }
217
218 #[rustfmt::skip] #[inline]
221 fn normalize_ryz_projection(&self) -> Cs<3> {
222 let r = self.ryz();
223 if tolerance::is_zero(r) { Cs([self.0[0], 0.0, 0.0]) } else { Cs([self.0[0], self.0[1] / r, self.0[2] / r]) }
224 }
225
226 #[rustfmt::skip] #[inline]
229 fn cross(&self, other: &Cs<3>) -> Cs<3> {
230 Cs([
231 self.0[1] * other.0[2] - self.0[2] * other.0[1],
232 self.0[2] * other.0[0] - self.0[0] * other.0[2],
233 self.0[0] * other.0[1] - self.0[1] * other.0[0]
234 ])
235 }
236}