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