honeycomb_core/geometry/dim3/
vector.rs1use crate::geometry::{CoordsError, CoordsFloat, Vector2};
2
3#[derive(Debug, Clone, Copy, Default, PartialEq)]
38pub struct Vector3<T: CoordsFloat>(pub T, pub T, pub T);
39
40unsafe impl<T: CoordsFloat> Send for Vector3<T> {}
41unsafe impl<T: CoordsFloat> Sync for Vector3<T> {}
42
43impl<T: CoordsFloat> Vector3<T> {
44 #[must_use = "unused return value"]
46 pub fn unit_x() -> Self {
47 Self(T::one(), T::zero(), T::zero())
48 }
49
50 #[must_use = "unused return value"]
52 pub fn unit_y() -> Self {
53 Self(T::zero(), T::one(), T::zero())
54 }
55
56 #[must_use = "unused return value"]
58 pub fn unit_z() -> Self {
59 Self(T::zero(), T::zero(), T::one())
60 }
61
62 pub fn into_inner(self) -> (T, T, T) {
64 (self.0, self.1, self.2)
65 }
66
67 pub fn to_f32(self) -> Option<Vector3<f32>> {
69 match (self.0.to_f32(), self.1.to_f32(), self.2.to_f32()) {
70 (Some(x), Some(y), Some(z)) => Some(Vector3(x, y, z)),
71 _ => None,
72 }
73 }
74
75 pub fn to_f64(self) -> Option<Vector3<f64>> {
77 match (self.0.to_f64(), self.1.to_f64(), self.2.to_f64()) {
78 (Some(x), Some(y), Some(z)) => Some(Vector3(x, y, z)),
79 _ => None,
80 }
81 }
82
83 pub fn x(&self) -> T {
85 self.0
86 }
87
88 pub fn y(&self) -> T {
90 self.1
91 }
92
93 pub fn z(&self) -> T {
95 self.2
96 }
97
98 pub fn norm(&self) -> T {
100 (self.0 * self.0 + self.1 * self.1 + self.2 * self.2).sqrt()
101 }
102
103 pub fn unit_dir(&self) -> Result<Self, CoordsError> {
109 let norm = self.norm();
110 if norm.is_zero() {
111 Err(CoordsError::InvalidUnitDir)
112 } else {
113 Ok(*self / norm)
114 }
115 }
116 pub fn dot(&self, other: &Vector3<T>) -> T {
118 self.0 * other.0 + self.1 * other.1 + self.2 * other.2
119 }
120
121 #[must_use = "unused return value"]
123 pub fn cross(&self, other: &Vector3<T>) -> Self {
124 Self(
125 self.1 * other.2 - self.2 * other.1,
126 self.2 * other.0 - self.0 * other.2,
127 self.0 * other.1 - self.1 * other.0,
128 )
129 }
130}
131
132impl<T: CoordsFloat> From<(T, T, T)> for Vector3<T> {
135 fn from((x, y, z): (T, T, T)) -> Self {
136 Self(x, y, z)
137 }
138}
139
140impl<T: CoordsFloat> From<Vector2<T>> for Vector3<T> {
141 fn from(v: Vector2<T>) -> Self {
142 Self(v.0, v.1, T::zero())
143 }
144}
145
146impl<T: CoordsFloat> std::ops::Add<Vector3<T>> for Vector3<T> {
149 type Output = Self;
150 fn add(self, rhs: Vector3<T>) -> Self::Output {
151 Self(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
152 }
153}
154
155impl<T: CoordsFloat> std::ops::AddAssign<Vector3<T>> for Vector3<T> {
156 fn add_assign(&mut self, rhs: Vector3<T>) {
157 self.0 += rhs.0;
158 self.1 += rhs.1;
159 self.2 += rhs.2;
160 }
161}
162
163impl<T: CoordsFloat> std::ops::Sub<Vector3<T>> for Vector3<T> {
164 type Output = Self;
165 fn sub(self, rhs: Vector3<T>) -> Self::Output {
166 Self(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
167 }
168}
169
170impl<T: CoordsFloat> std::ops::SubAssign<Vector3<T>> for Vector3<T> {
171 fn sub_assign(&mut self, rhs: Vector3<T>) {
172 self.0 -= rhs.0;
173 self.1 -= rhs.1;
174 self.2 -= rhs.2;
175 }
176}
177
178impl<T: CoordsFloat> std::ops::Mul<T> for Vector3<T> {
179 type Output = Self;
180 fn mul(self, rhs: T) -> Self::Output {
181 Self(self.0 * rhs, self.1 * rhs, self.2 * rhs)
182 }
183}
184
185impl<T: CoordsFloat> std::ops::MulAssign<T> for Vector3<T> {
186 fn mul_assign(&mut self, rhs: T) {
187 self.0 *= rhs;
188 self.1 *= rhs;
189 self.2 *= rhs;
190 }
191}
192
193impl<T: CoordsFloat> std::ops::Div<T> for Vector3<T> {
194 type Output = Self;
195 fn div(self, rhs: T) -> Self::Output {
196 assert!(!rhs.is_zero());
197 Self(self.0 / rhs, self.1 / rhs, self.2 / rhs)
198 }
199}
200
201impl<T: CoordsFloat> std::ops::DivAssign<T> for Vector3<T> {
202 fn div_assign(&mut self, rhs: T) {
203 assert!(!rhs.is_zero());
204 self.0 /= rhs;
205 self.1 /= rhs;
206 self.2 /= rhs;
207 }
208}
209
210impl<T: CoordsFloat> std::ops::Neg for Vector3<T> {
211 type Output = Self;
212 fn neg(self) -> Self::Output {
213 Self(-self.0, -self.1, -self.2)
214 }
215}