1use lox_bodies::{Origin, RotationalElements, TryRotationalElements, UndefinedOriginPropertyError};
6
7use crate::{
8 iers::IersSystem,
9 traits::{BodyFixed, QuasiInertial, ReferenceFrame},
10};
11
12const ICRF_ID: usize = 0;
13const CIRF_ID: usize = 1;
14const TIRF_ID: usize = 2;
15const ITRF_ID: usize = 3;
16const J2000_ID: usize = 4;
17
18const MOD_ID: usize = 11;
19const TOD_ID: usize = 12;
20const PEF_ID: usize = 13;
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub struct Icrf;
26
27impl ReferenceFrame for Icrf {
28 fn name(&self) -> String {
29 "International Celestial Reference Frame".to_string()
30 }
31
32 fn abbreviation(&self) -> String {
33 "ICRF".to_string()
34 }
35
36 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
37 Some(ICRF_ID)
38 }
39}
40
41impl QuasiInertial for Icrf {}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46pub struct J2000;
47
48impl ReferenceFrame for J2000 {
49 fn name(&self) -> String {
50 "J2000 Mean Equator and Equinox".to_string()
51 }
52
53 fn abbreviation(&self) -> String {
54 "J2000".to_string()
55 }
56
57 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
58 Some(J2000_ID)
59 }
60}
61
62impl QuasiInertial for J2000 {}
63
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
66#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67pub struct Cirf;
68
69impl ReferenceFrame for Cirf {
70 fn name(&self) -> String {
71 "Celestial Intermediate Reference Frame".to_string()
72 }
73
74 fn abbreviation(&self) -> String {
75 "CIRF".to_string()
76 }
77
78 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
79 Some(CIRF_ID)
80 }
81}
82
83#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
86pub struct Tirf;
87
88impl ReferenceFrame for Tirf {
89 fn name(&self) -> String {
90 "Terrestrial Intermediate Reference Frame".to_string()
91 }
92
93 fn abbreviation(&self) -> String {
94 "TIRF".to_string()
95 }
96
97 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
98 Some(TIRF_ID)
99 }
100}
101
102#[derive(Clone, Copy, Debug, PartialEq, Eq)]
104#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
105pub struct Itrf;
106
107impl ReferenceFrame for Itrf {
108 fn name(&self) -> String {
109 "International Terrestrial Reference Frame".to_string()
110 }
111
112 fn abbreviation(&self) -> String {
113 "ITRF".to_string()
114 }
115
116 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
117 Some(ITRF_ID)
118 }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
124pub struct Mod<T: IersSystem>(pub T);
125
126impl<T> ReferenceFrame for Mod<T>
127where
128 T: IersSystem,
129{
130 fn name(&self) -> String {
131 format!("{} Mean of Date Frame", self.0.name())
132 }
133
134 fn abbreviation(&self) -> String {
135 format!("MOD({})", self.0.name())
136 }
137
138 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
139 Some(MOD_ID * 10 + self.0.id())
140 }
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq)]
145#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
146pub struct Tod<T: IersSystem>(pub T);
147
148impl<T> ReferenceFrame for Tod<T>
149where
150 T: IersSystem,
151{
152 fn name(&self) -> String {
153 format!("{} True of Date Frame", self.0.name())
154 }
155
156 fn abbreviation(&self) -> String {
157 format!("TOD({})", self.0.name())
158 }
159
160 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
161 Some(TOD_ID * 10 + self.0.id())
162 }
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq)]
167#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
168pub struct Pef<T: IersSystem>(pub T);
169
170impl<T> ReferenceFrame for Pef<T>
171where
172 T: IersSystem,
173{
174 fn name(&self) -> String {
175 format!("{} Pseudo-Earth Fixed Frame", self.0.name())
176 }
177
178 fn abbreviation(&self) -> String {
179 format!("PEF({})", self.0.name())
180 }
181
182 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
183 Some(PEF_ID * 10 + self.0.id())
184 }
185}
186
187#[derive(Debug, Clone, Copy, PartialEq, Eq)]
189#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
190pub struct Teme;
191
192impl ReferenceFrame for Teme {
193 fn name(&self) -> String {
194 "True Equator Mean Equinox".to_owned()
195 }
196
197 fn abbreviation(&self) -> String {
198 "TEME".to_owned()
199 }
200
201 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
202 Some(7)
203 }
204}
205
206impl BodyFixed for Itrf {}
207
208#[derive(Clone, Copy, Debug, PartialEq, Eq)]
210#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
211pub struct Iau<T: TryRotationalElements>(T);
212
213impl<T> Iau<T>
214where
215 T: RotationalElements,
216{
217 pub fn new(body: T) -> Self {
219 Self(body)
220 }
221}
222
223impl<T> Iau<T>
224where
225 T: TryRotationalElements,
226{
227 pub fn try_new(body: T) -> Result<Self, UndefinedOriginPropertyError> {
229 let _ = body.try_right_ascension(0.0)?;
230 Ok(Self(body))
231 }
232
233 pub fn body(&self) -> T
235 where
236 T: Copy,
237 {
238 self.0
239 }
240
241 pub fn rotational_elements(&self, j2000: f64) -> (f64, f64, f64) {
244 self.0.try_rotational_elements(j2000).unwrap()
245 }
246
247 pub fn rotational_element_rates(&self, j2000: f64) -> (f64, f64, f64) {
249 self.0.try_rotational_element_rates(j2000).unwrap()
250 }
251}
252
253impl<T: TryRotationalElements> BodyFixed for Iau<T> {}
254
255impl<T> ReferenceFrame for Iau<T>
256where
257 T: TryRotationalElements + Origin,
258{
259 fn name(&self) -> String {
260 let body = self.0.name();
261 match body {
262 "Sun" | "Moon" => format!("IAU Body-Fixed Reference Frame for the {body}"),
263 _ => format!("IAU Body-Fixed Reference Frame for {body}"),
264 }
265 }
266
267 fn abbreviation(&self) -> String {
268 let body = self.0.name().replace([' ', '-'], "_").to_uppercase();
269 format!("IAU_{body}")
270 }
271
272 fn frame_id(&self, _: crate::traits::private::Internal) -> Option<usize> {
273 Some(1000 + self.0.id().0 as usize)
274 }
275}