nav_types/
enu.rs

1use crate::utils::RealFieldCopy;
2use crate::Access;
3use na::Vector3;
4use std::convert::Into;
5use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
6
7/// East North Up vector
8///
9/// This struct represents a vector in the ENU coordinate system.
10/// See: [ENU](https://en.wikipedia.org/wiki/Axes_conventions) for a general
11/// description.
12///
13/// # Note
14/// ENU implements `Into` on all operations. This means that any vector that
15/// can be converted to ENU with a `From` implementation will automatically
16/// be able to work with ENU at the cost of the `Into` conversion.
17#[derive(Debug, Copy, Clone, PartialEq)]
18pub struct ENU<N: RealFieldCopy>(Vector3<N>);
19
20impl<N: RealFieldCopy> ENU<N> {
21    /// Create a new ENU vector
22    pub fn new(e: N, n: N, u: N) -> ENU<N> {
23        ENU(Vector3::new(e, n, u))
24    }
25
26    /// Computes the L2 (Euclidean) norm of this vector
27    pub fn norm(&self) -> N {
28        self.0.norm()
29    }
30}
31
32impl<N: RealFieldCopy> ENU<N> {
33    /// Get the East component of this vector
34    pub fn east(&self) -> N {
35        self.0.x
36    }
37
38    /// Get the North component of this vector
39    pub fn north(&self) -> N {
40        self.0.y
41    }
42
43    /// Get the Up component of this vector
44    pub fn up(&self) -> N {
45        self.0.z
46    }
47}
48
49impl<N: RealFieldCopy + Add<N, Output = N>, T: Into<ENU<N>>> Add<T> for ENU<N> {
50    type Output = ENU<N>;
51    fn add(self, right: T) -> Self::Output {
52        ENU(self.0 + right.into().0)
53    }
54}
55
56impl<N: RealFieldCopy + AddAssign<N>, T: Into<ENU<N>>> AddAssign<T> for ENU<N> {
57    fn add_assign(&mut self, right: T) {
58        self.0 += right.into().0
59    }
60}
61
62impl<N: RealFieldCopy + Sub<N, Output = N>, T: Into<ENU<N>>> Sub<T> for ENU<N> {
63    type Output = ENU<N>;
64    fn sub(self, right: T) -> Self::Output {
65        ENU(self.0 - right.into().0)
66    }
67}
68
69impl<N: RealFieldCopy + SubAssign<N>, T: Into<ENU<N>>> SubAssign<T> for ENU<N> {
70    fn sub_assign(&mut self, right: T) {
71        self.0 -= right.into().0
72    }
73}
74
75impl<N: RealFieldCopy + Mul<N, Output = N>> Mul<N> for ENU<N> {
76    type Output = ENU<N>;
77    fn mul(self, right: N) -> Self::Output {
78        ENU(self.0 * right)
79    }
80}
81
82impl<N: RealFieldCopy + MulAssign<N>> MulAssign<N> for ENU<N> {
83    fn mul_assign(&mut self, right: N) {
84        self.0 *= right
85    }
86}
87
88impl<N: RealFieldCopy + Div<N, Output = N>> Div<N> for ENU<N> {
89    type Output = ENU<N>;
90    fn div(self, right: N) -> Self::Output {
91        ENU(self.0 / right)
92    }
93}
94
95impl<N: RealFieldCopy + DivAssign<N>> DivAssign<N> for ENU<N> {
96    fn div_assign(&mut self, right: N) {
97        self.0 /= right
98    }
99}
100
101impl<N: RealFieldCopy> Access<Vector3<N>> for ENU<N> {
102    fn access(self) -> Vector3<N> {
103        self.0
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110    use crate::ned::NED;
111
112    quickcheck! {
113        fn create_enu(e: f32, n: f32, u: f32) -> () {
114            ENU::new(e, n, u);
115        }
116
117        fn get_components(e: f32, n: f32, u: f32) -> () {
118            let vec = ENU::new(e, n, u);
119            assert_eq!(vec.east(), e);
120            assert_eq!(vec.north(), n);
121            assert_eq!(vec.up(), u);
122        }
123
124        fn from_ned(n: f32, e: f32, d: f32) -> () {
125            let ned = NED::new(n, e, d);
126            let enu = ENU::from(ned);
127            assert_eq!(enu.east(), e);
128            assert_eq!(enu.north(), n);
129            assert_eq!(enu.up(), -d);
130        }
131    }
132}