siege_math/vector/
direction.rs1
2use std::ops::{Deref, Neg};
3use float_cmp::{Ulps, ApproxEq};
4use super::{Vec2, Vec3, Vec4};
5use {Angle, FullFloat};
6
7#[repr(C)]
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10#[derive(Serialize, Deserialize)]
11pub struct Direction2<F>(Vec2<F>);
12
13#[repr(C)]
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16#[derive(Serialize, Deserialize)]
17pub struct Direction3<F>(Vec3<F>);
18
19pub const X_AXIS_F32: Direction3<f32> = Direction3::<f32>(
20 Vec3::<f32> { x: 1.0, y: 0.0, z: 0.0 }
21);
22pub const Y_AXIS_F32: Direction3<f32> = Direction3::<f32>(
23 Vec3::<f32> { x: 0.0, y: 1.0, z: 0.0 }
24);
25pub const Z_AXIS_F32: Direction3<f32> = Direction3::<f32>(
26 Vec3::<f32> { x: 0.0, y: 0.0, z: 1.0 }
27);
28pub const X_AXIS_F64: Direction3<f64> = Direction3::<f64>(
29 Vec3::<f64> { x: 1.0, y: 0.0, z: 0.0 }
30);
31pub const Y_AXIS_F64: Direction3<f64> = Direction3::<f64>(
32 Vec3::<f64> { x: 0.0, y: 1.0, z: 0.0 }
33);
34pub const Z_AXIS_F64: Direction3<f64> = Direction3::<f64>(
35 Vec3::<f64> { x: 0.0, y: 0.0, z: 1.0 }
36);
37
38impl<F: FullFloat> Direction2<F> {
39 #[inline]
40 pub fn new_isnormal(x: F, y: F) -> Direction2<F> {
41 let d = Direction2(Vec2::new(x,y));
42 assert!(d.0.is_normal());
43 d
44 }
45}
46
47impl<F: FullFloat> Direction3<F> {
48 #[inline]
49 pub fn new_isnormal(x: F, y: F, z: F) -> Direction3<F> {
50 let d = Direction3(Vec3::new(x,y,z));
51 assert!(d.0.is_normal());
52 d
53 }
54}
55
56impl<F: FullFloat> Deref for Direction2<F> {
57 type Target = Vec2<F>;
58
59 fn deref(&self) -> &Vec2<F>
60 {
61 &self.0
62 }
63}
64
65impl<F: FullFloat> Deref for Direction3<F> {
66 type Target = Vec3<F>;
67
68 fn deref(&self) -> &Vec3<F>
69 {
70 &self.0
71 }
72}
73
74impl<F: FullFloat> From<Direction2<F>> for Vec2<F> {
75 fn from(v: Direction2<F>) -> Vec2<F> {
76 v.0
77 }
78}
79impl<F: FullFloat> From<Direction3<F>> for Vec3<F> {
80 fn from(v: Direction3<F>) -> Vec3<F> {
81 v.0
82 }
83}
84impl<F: FullFloat> From<Direction3<F>> for Vec4<F> {
85 fn from(v: Direction3<F>) -> Vec4<F> {
86 Vec4::new(v.0.x, v.0.y, v.0.z, F::zero())
87 }
88}
89
90impl<F: FullFloat> From<Vec2<F>> for Direction2<F> {
91 fn from(mut v: Vec2<F>) -> Direction2<F> {
92 let mag = v.magnitude();
93 v.x /= mag;
94 v.y /= mag;
95 Direction2(v)
96 }
97}
98impl<F: FullFloat> From<Vec3<F>> for Direction3<F> {
99 fn from(mut v: Vec3<F>) -> Direction3<F> {
100 let mag = v.magnitude();
101 v.x /= mag;
102 v.y /= mag;
103 v.z /= mag;
104 Direction3(v)
105 }
106}
107
108impl<F: FullFloat> Direction3<F> {
109 #[allow(dead_code)]
110 #[inline]
111 fn from_vec4(v: Vec4<F>) -> Option<Direction3<F>> {
112 if v.w != F::zero() { return None; }
113 Some(Direction3(v.truncate_w()))
114 }
115}
116
117impl<F: FullFloat> Direction3<F> {
118 #[inline]
119 pub fn cross(&self, rhs: Direction3<F>) -> Vec3<F> {
120 self.0.cross(rhs.0)
121 }
122}
123
124impl<F: FullFloat> Direction3<F> {
125 #[inline]
126 pub fn dot(&self, rhs: Direction3<F>) -> F {
127 self.0.dot(rhs.0)
128 }
129}
130
131impl<F: FullFloat> Neg for Direction3<F> {
132 type Output = Direction3<F>;
133
134 #[inline]
135 fn neg(self) -> Direction3<F> {
136 Direction3(-self.0)
137 }
138}
139
140impl<F: FullFloat> ApproxEq for Direction2<F> {
141 type Flt = F;
142
143 fn approx_eq(&self, other: &Self,
144 epsilon: <F as ApproxEq>::Flt,
145 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
146 {
147 self.0.approx_eq(&other.0, epsilon, ulps)
148 }
149}
150
151impl<F: FullFloat> ApproxEq for Direction3<F> {
152 type Flt = F;
153
154 fn approx_eq(&self, other: &Self,
155 epsilon: <F as ApproxEq>::Flt,
156 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
157 {
158 self.0.approx_eq(&other.0, epsilon, ulps)
159 }
160}
161
162impl<F: FullFloat> Direction3<F> {
163 pub fn from_lat_long(latitude: Angle<F>, longitude: Angle<F>) -> Direction3<F>
164 {
165 let (slat,clat) = latitude.as_radians().sin_cos();
166 let (slon,clon) = longitude.as_radians().sin_cos();
167 Direction3(Vec3 {
168 x: clat * slon,
169 y: slat,
170 z: slat * clon,
171 })
172 }
173
174 pub fn to_lat_long(&self) -> (Angle<F>, Angle<F>) {
175 let lat = self.0.y.acos();
176 let lon = (self.0.z / self.0.y).acos();
177 (Angle::from_radians(lat), Angle::from_radians(lon))
178 }
179}