coordinate_frame/
traits.rs

1use crate::{CoordinateFrameType, EastNorthUp, NorthEastDown};
2
3/// A coordinate frame.
4pub trait CoordinateFrame {
5    /// The type of each coordinate value.
6    type Type;
7
8    /// The coordinate frame type.
9    const COORDINATE_FRAME: CoordinateFrameType;
10
11    /// Returns the coordinate frame of this instance.
12    fn coordinate_frame(&self) -> CoordinateFrameType;
13
14    /// Converts this type to a [`NorthEastDown`] instance.
15    fn to_ned(&self) -> NorthEastDown<Self::Type>
16    where
17        Self::Type: Copy + SaturatingNeg<Output = Self::Type>;
18
19    /// Converts this type to an [`EastNorthUp`] instance.
20    fn to_enu(&self) -> EastNorthUp<Self::Type>
21    where
22        Self::Type: Copy + SaturatingNeg<Output = Self::Type>;
23
24    /// Gets the value of the first dimension.
25    fn x(&self) -> Self::Type
26    where
27        Self::Type: Clone;
28
29    /// Gets the value of the second dimension.
30    fn y(&self) -> Self::Type
31    where
32        Self::Type: Clone;
33
34    /// Gets the value of the third dimension.
35    fn z(&self) -> Self::Type
36    where
37        Self::Type: Clone;
38
39    /// Gets a reference to the value of the first dimension.
40    fn x_ref(&self) -> &Self::Type;
41
42    /// Gets a reference to the value of the second dimension.
43    fn y_ref(&self) -> &Self::Type;
44
45    /// Gets a reference to the value of the third dimension.
46    fn z_ref(&self) -> &Self::Type;
47
48    /// Gets a mutable reference to the value of the first dimension.
49    fn x_mut(&mut self) -> &mut Self::Type;
50
51    /// Gets a mutable reference to the value of the second dimension.
52    fn y_mut(&mut self) -> &mut Self::Type;
53
54    /// Gets a mutable reference to the value of the third dimension.
55    fn z_mut(&mut self) -> &mut Self::Type;
56
57    /// Indicates whether this coordinate system is right-handed or left-handed.
58    fn right_handed(&self) -> bool;
59
60    /// Returns the base vector for the `x` axis in the global frame.
61    fn x_axis() -> [Self::Type; 3]
62    where
63        Self::Type: ZeroOne<Output = Self::Type> + core::ops::Neg<Output = Self::Type>;
64
65    /// Returns the base vector for the `y` axis in the global frame.
66    fn y_axis() -> [Self::Type; 3]
67    where
68        Self::Type: ZeroOne<Output = Self::Type> + core::ops::Neg<Output = Self::Type>;
69
70    /// Returns the base vector for the `z` axis in the global frame.
71    fn z_axis() -> [Self::Type; 3]
72    where
73        Self::Type: ZeroOne<Output = Self::Type> + core::ops::Neg<Output = Self::Type>;
74}
75
76/// Marks a right-handed coordinate system.
77pub trait RightHanded {}
78
79/// Marks a left-handed coordinate system.
80pub trait LeftHanded {}
81
82/// Provides the values zero and one.
83pub trait ZeroOne {
84    type Output;
85
86    /// Provides the value zero (`0`).
87    fn zero() -> Self::Output;
88
89    /// Provides the value one (`1`).
90    fn one() -> Self::Output;
91}
92
93/// Performs a saturating negation.
94pub trait SaturatingNeg {
95    type Output;
96
97    /// Like [`Neg`](core::ops::Neg), but returns the maximum value on negation of
98    /// a minimum value instead of overflowing.
99    fn saturating_neg(self) -> Self::Output;
100}
101
102impl SaturatingNeg for i8 {
103    type Output = Self;
104
105    fn saturating_neg(self) -> Self {
106        self.saturating_neg()
107    }
108}
109
110impl SaturatingNeg for i16 {
111    type Output = Self;
112
113    fn saturating_neg(self) -> Self {
114        self.saturating_neg()
115    }
116}
117impl SaturatingNeg for i32 {
118    type Output = Self;
119
120    fn saturating_neg(self) -> Self {
121        self.saturating_neg()
122    }
123}
124
125impl SaturatingNeg for i64 {
126    type Output = Self;
127
128    fn saturating_neg(self) -> Self {
129        self.saturating_neg()
130    }
131}
132
133impl SaturatingNeg for i128 {
134    type Output = Self;
135
136    fn saturating_neg(self) -> Self {
137        self.saturating_neg()
138    }
139}
140
141impl SaturatingNeg for f32 {
142    type Output = Self;
143
144    fn saturating_neg(self) -> Self {
145        -self
146    }
147}
148
149impl SaturatingNeg for f64 {
150    type Output = Self;
151
152    fn saturating_neg(self) -> Self {
153        -self
154    }
155}
156
157#[cfg(not(feature = "num-traits"))]
158impl ZeroOne for u8 {
159    type Output = Self;
160
161    fn zero() -> Self::Output {
162        0
163    }
164
165    fn one() -> Self::Output {
166        1
167    }
168}
169
170#[cfg(not(feature = "num-traits"))]
171impl ZeroOne for i8 {
172    type Output = Self;
173
174    fn zero() -> Self::Output {
175        0
176    }
177
178    fn one() -> Self::Output {
179        1
180    }
181}
182
183#[cfg(not(feature = "num-traits"))]
184impl ZeroOne for u16 {
185    type Output = Self;
186
187    fn zero() -> Self::Output {
188        0
189    }
190
191    fn one() -> Self::Output {
192        1
193    }
194}
195
196#[cfg(not(feature = "num-traits"))]
197impl ZeroOne for i16 {
198    type Output = Self;
199
200    fn zero() -> Self::Output {
201        0
202    }
203
204    fn one() -> Self::Output {
205        1
206    }
207}
208
209#[cfg(not(feature = "num-traits"))]
210impl ZeroOne for u32 {
211    type Output = Self;
212
213    fn zero() -> Self::Output {
214        0
215    }
216
217    fn one() -> Self::Output {
218        1
219    }
220}
221
222#[cfg(not(feature = "num-traits"))]
223impl ZeroOne for i32 {
224    type Output = Self;
225
226    fn zero() -> Self::Output {
227        0
228    }
229
230    fn one() -> Self::Output {
231        1
232    }
233}
234
235#[cfg(not(feature = "num-traits"))]
236impl ZeroOne for u64 {
237    type Output = Self;
238
239    fn zero() -> Self::Output {
240        0
241    }
242
243    fn one() -> Self::Output {
244        1
245    }
246}
247
248#[cfg(not(feature = "num-traits"))]
249impl ZeroOne for i64 {
250    type Output = Self;
251
252    fn zero() -> Self::Output {
253        0
254    }
255
256    fn one() -> Self::Output {
257        1
258    }
259}
260
261#[cfg(not(feature = "num-traits"))]
262impl ZeroOne for u128 {
263    type Output = Self;
264
265    fn zero() -> Self::Output {
266        0
267    }
268
269    fn one() -> Self::Output {
270        1
271    }
272}
273
274#[cfg(not(feature = "num-traits"))]
275impl ZeroOne for i128 {
276    type Output = Self;
277
278    fn zero() -> Self::Output {
279        0
280    }
281
282    fn one() -> Self::Output {
283        1
284    }
285}
286
287#[cfg(not(feature = "num-traits"))]
288impl ZeroOne for f32 {
289    type Output = Self;
290
291    fn zero() -> Self::Output {
292        0.0
293    }
294
295    fn one() -> Self::Output {
296        1.0
297    }
298}
299
300#[cfg(not(feature = "num-traits"))]
301impl ZeroOne for f64 {
302    type Output = Self;
303
304    fn zero() -> Self::Output {
305        0.0
306    }
307
308    fn one() -> Self::Output {
309        1.0
310    }
311}
312
313#[cfg(feature = "num-traits")]
314impl<T> ZeroOne for T
315where
316    T: num_traits::Zero + num_traits::One,
317{
318    type Output = T;
319
320    fn zero() -> Self::Output {
321        <T as num_traits::Zero>::zero()
322    }
323
324    fn one() -> Self::Output {
325        <T as num_traits::One>::one()
326    }
327}