1use super::{EPSILON, Float, approx_eq, lerp};
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
5
6#[derive(Debug, Clone, Copy, PartialEq, Default)]
8#[repr(C)]
9pub struct Vec2 {
10 pub x: Float,
12 pub y: Float,
14}
15
16impl Vec2 {
17 pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
19
20 pub const ONE: Self = Self { x: 1.0, y: 1.0 };
22
23 pub const X: Self = Self { x: 1.0, y: 0.0 };
25
26 pub const Y: Self = Self { x: 0.0, y: 1.0 };
28
29 #[inline]
31 #[must_use]
32 pub const fn new(x: Float, y: Float) -> Self {
33 Self { x, y }
34 }
35
36 #[inline]
38 #[must_use]
39 pub const fn splat(value: Float) -> Self {
40 Self { x: value, y: value }
41 }
42
43 #[inline]
45 #[must_use]
46 pub const fn from_array(arr: [Float; 2]) -> Self {
47 Self {
48 x: arr[0],
49 y: arr[1],
50 }
51 }
52
53 #[inline]
55 #[must_use]
56 pub const fn to_array(self) -> [Float; 2] {
57 [self.x, self.y]
58 }
59
60 #[inline]
62 #[must_use]
63 pub fn dot(self, other: Self) -> Float {
64 self.x * other.x + self.y * other.y
65 }
66
67 #[inline]
69 #[must_use]
70 pub fn length_squared(self) -> Float {
71 self.dot(self)
72 }
73
74 #[inline]
76 #[must_use]
77 pub fn length(self) -> Float {
78 self.length_squared().sqrt()
79 }
80
81 #[inline]
85 #[must_use]
86 pub fn normalize(self) -> Self {
87 let len = self.length();
88 if len > EPSILON {
89 self / len
90 } else {
91 Self::ZERO
92 }
93 }
94
95 #[inline]
97 #[must_use]
98 pub fn try_normalize(self) -> Option<Self> {
99 let len = self.length();
100 if len > EPSILON {
101 Some(self / len)
102 } else {
103 None
104 }
105 }
106
107 #[inline]
109 #[must_use]
110 pub fn distance(self, other: Self) -> Float {
111 (self - other).length()
112 }
113
114 #[inline]
116 #[must_use]
117 pub fn distance_squared(self, other: Self) -> Float {
118 (self - other).length_squared()
119 }
120
121 #[inline]
123 #[must_use]
124 pub fn lerp(self, other: Self, t: Float) -> Self {
125 Self {
126 x: lerp(self.x, other.x, t),
127 y: lerp(self.y, other.y, t),
128 }
129 }
130
131 #[inline]
133 #[must_use]
134 pub fn min(self, other: Self) -> Self {
135 Self {
136 x: self.x.min(other.x),
137 y: self.y.min(other.y),
138 }
139 }
140
141 #[inline]
143 #[must_use]
144 pub fn max(self, other: Self) -> Self {
145 Self {
146 x: self.x.max(other.x),
147 y: self.y.max(other.y),
148 }
149 }
150
151 #[inline]
153 #[must_use]
154 pub fn abs(self) -> Self {
155 Self {
156 x: self.x.abs(),
157 y: self.y.abs(),
158 }
159 }
160
161 #[inline]
163 #[must_use]
164 pub fn perpendicular(self) -> Self {
165 Self {
166 x: -self.y,
167 y: self.x,
168 }
169 }
170
171 #[inline]
173 #[must_use]
174 pub fn cross(self, other: Self) -> Float {
175 self.x * other.y - self.y * other.x
176 }
177
178 #[inline]
180 #[must_use]
181 pub fn angle_between(self, other: Self) -> Float {
182 let denom = (self.length_squared() * other.length_squared()).sqrt();
183 if denom < EPSILON {
184 0.0
185 } else {
186 (self.dot(other) / denom).clamp(-1.0, 1.0).acos()
187 }
188 }
189
190 #[inline]
192 #[must_use]
193 pub fn approx_eq(self, other: Self) -> bool {
194 approx_eq(self.x, other.x) && approx_eq(self.y, other.y)
195 }
196
197 #[inline]
199 #[must_use]
200 pub fn reflect(self, normal: Self) -> Self {
201 self - normal * (2.0 * self.dot(normal))
202 }
203}
204
205impl Add for Vec2 {
206 type Output = Self;
207
208 #[inline]
209 fn add(self, other: Self) -> Self {
210 Self {
211 x: self.x + other.x,
212 y: self.y + other.y,
213 }
214 }
215}
216
217impl AddAssign for Vec2 {
218 #[inline]
219 fn add_assign(&mut self, other: Self) {
220 self.x += other.x;
221 self.y += other.y;
222 }
223}
224
225impl Sub for Vec2 {
226 type Output = Self;
227
228 #[inline]
229 fn sub(self, other: Self) -> Self {
230 Self {
231 x: self.x - other.x,
232 y: self.y - other.y,
233 }
234 }
235}
236
237impl SubAssign for Vec2 {
238 #[inline]
239 fn sub_assign(&mut self, other: Self) {
240 self.x -= other.x;
241 self.y -= other.y;
242 }
243}
244
245impl Mul<Float> for Vec2 {
246 type Output = Self;
247
248 #[inline]
249 fn mul(self, scalar: Float) -> Self {
250 Self {
251 x: self.x * scalar,
252 y: self.y * scalar,
253 }
254 }
255}
256
257impl Mul<Vec2> for Float {
258 type Output = Vec2;
259
260 #[inline]
261 fn mul(self, vec: Vec2) -> Vec2 {
262 vec * self
263 }
264}
265
266impl MulAssign<Float> for Vec2 {
267 #[inline]
268 fn mul_assign(&mut self, scalar: Float) {
269 self.x *= scalar;
270 self.y *= scalar;
271 }
272}
273
274impl Mul for Vec2 {
275 type Output = Self;
276
277 #[inline]
278 fn mul(self, other: Self) -> Self {
279 Self {
280 x: self.x * other.x,
281 y: self.y * other.y,
282 }
283 }
284}
285
286impl Div<Float> for Vec2 {
287 type Output = Self;
288
289 #[inline]
290 fn div(self, scalar: Float) -> Self {
291 Self {
292 x: self.x / scalar,
293 y: self.y / scalar,
294 }
295 }
296}
297
298impl DivAssign<Float> for Vec2 {
299 #[inline]
300 fn div_assign(&mut self, scalar: Float) {
301 self.x /= scalar;
302 self.y /= scalar;
303 }
304}
305
306impl Neg for Vec2 {
307 type Output = Self;
308
309 #[inline]
310 fn neg(self) -> Self {
311 Self {
312 x: -self.x,
313 y: -self.y,
314 }
315 }
316}
317
318impl From<[Float; 2]> for Vec2 {
319 #[inline]
320 fn from(arr: [Float; 2]) -> Self {
321 Self::from_array(arr)
322 }
323}
324
325impl From<Vec2> for [Float; 2] {
326 #[inline]
327 fn from(v: Vec2) -> Self {
328 v.to_array()
329 }
330}
331
332impl From<(Float, Float)> for Vec2 {
333 #[inline]
334 fn from((x, y): (Float, Float)) -> Self {
335 Self { x, y }
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342
343 #[test]
344 fn test_new() {
345 let v = Vec2::new(1.0, 2.0);
346 assert_eq!(v.x, 1.0);
347 assert_eq!(v.y, 2.0);
348 }
349
350 #[test]
351 fn test_constants() {
352 assert!(Vec2::ZERO.approx_eq(Vec2::new(0.0, 0.0)));
353 assert!(Vec2::ONE.approx_eq(Vec2::new(1.0, 1.0)));
354 assert!(Vec2::X.approx_eq(Vec2::new(1.0, 0.0)));
355 assert!(Vec2::Y.approx_eq(Vec2::new(0.0, 1.0)));
356 }
357
358 #[test]
359 fn test_splat() {
360 let v = Vec2::splat(5.0);
361 assert!(v.approx_eq(Vec2::new(5.0, 5.0)));
362 }
363
364 #[test]
365 fn test_from_array() {
366 let v = Vec2::from_array([1.0, 2.0]);
367 assert!(v.approx_eq(Vec2::new(1.0, 2.0)));
368 }
369
370 #[test]
371 fn test_to_array() {
372 let v = Vec2::new(1.0, 2.0);
373 assert_eq!(v.to_array(), [1.0, 2.0]);
374 }
375
376 #[test]
377 fn test_dot() {
378 let a = Vec2::new(1.0, 2.0);
379 let b = Vec2::new(3.0, 4.0);
380 assert!(approx_eq(a.dot(b), 11.0));
381 }
382
383 #[test]
384 fn test_length() {
385 let v = Vec2::new(3.0, 4.0);
386 assert!(approx_eq(v.length_squared(), 25.0));
387 assert!(approx_eq(v.length(), 5.0));
388 }
389
390 #[test]
391 fn test_normalize() {
392 let v = Vec2::new(3.0, 4.0);
393 let n = v.normalize();
394 assert!(approx_eq(n.length(), 1.0));
395 assert!(n.approx_eq(Vec2::new(0.6, 0.8)));
396 }
397
398 #[test]
399 fn test_normalize_zero() {
400 let v = Vec2::ZERO;
401 assert!(v.normalize().approx_eq(Vec2::ZERO));
402 assert!(v.try_normalize().is_none());
403 }
404
405 #[test]
406 fn test_distance() {
407 let a = Vec2::new(0.0, 0.0);
408 let b = Vec2::new(3.0, 4.0);
409 assert!(approx_eq(a.distance(b), 5.0));
410 assert!(approx_eq(a.distance_squared(b), 25.0));
411 }
412
413 #[test]
414 fn test_lerp() {
415 let a = Vec2::new(0.0, 0.0);
416 let b = Vec2::new(10.0, 20.0);
417 assert!(a.lerp(b, 0.0).approx_eq(a));
418 assert!(a.lerp(b, 1.0).approx_eq(b));
419 assert!(a.lerp(b, 0.5).approx_eq(Vec2::new(5.0, 10.0)));
420 }
421
422 #[test]
423 fn test_min_max() {
424 let a = Vec2::new(1.0, 4.0);
425 let b = Vec2::new(3.0, 2.0);
426 assert!(a.min(b).approx_eq(Vec2::new(1.0, 2.0)));
427 assert!(a.max(b).approx_eq(Vec2::new(3.0, 4.0)));
428 }
429
430 #[test]
431 fn test_abs() {
432 let v = Vec2::new(-1.0, -2.0);
433 assert!(v.abs().approx_eq(Vec2::new(1.0, 2.0)));
434 }
435
436 #[test]
437 fn test_perpendicular() {
438 let v = Vec2::new(1.0, 0.0);
439 assert!(v.perpendicular().approx_eq(Vec2::new(0.0, 1.0)));
440 }
441
442 #[test]
443 fn test_cross() {
444 let a = Vec2::new(1.0, 0.0);
445 let b = Vec2::new(0.0, 1.0);
446 assert!(approx_eq(a.cross(b), 1.0));
447 assert!(approx_eq(b.cross(a), -1.0));
448 }
449
450 #[test]
451 fn test_angle_between() {
452 let a = Vec2::X;
453 let b = Vec2::Y;
454 assert!(approx_eq(
455 a.angle_between(b),
456 std::f32::consts::FRAC_PI_2 as Float
457 ));
458 }
459
460 #[test]
461 fn test_reflect() {
462 let v = Vec2::new(1.0, -1.0);
463 let n = Vec2::Y;
464 let r = v.reflect(n);
465 assert!(r.approx_eq(Vec2::new(1.0, 1.0)));
466 }
467
468 #[test]
469 fn test_add() {
470 let a = Vec2::new(1.0, 2.0);
471 let b = Vec2::new(3.0, 4.0);
472 assert!((a + b).approx_eq(Vec2::new(4.0, 6.0)));
473 }
474
475 #[test]
476 fn test_add_assign() {
477 let mut a = Vec2::new(1.0, 2.0);
478 a += Vec2::new(3.0, 4.0);
479 assert!(a.approx_eq(Vec2::new(4.0, 6.0)));
480 }
481
482 #[test]
483 fn test_sub() {
484 let a = Vec2::new(3.0, 4.0);
485 let b = Vec2::new(1.0, 2.0);
486 assert!((a - b).approx_eq(Vec2::new(2.0, 2.0)));
487 }
488
489 #[test]
490 fn test_mul_scalar() {
491 let v = Vec2::new(1.0, 2.0);
492 assert!((v * 2.0).approx_eq(Vec2::new(2.0, 4.0)));
493 assert!((2.0 * v).approx_eq(Vec2::new(2.0, 4.0)));
494 }
495
496 #[test]
497 fn test_mul_component() {
498 let a = Vec2::new(2.0, 3.0);
499 let b = Vec2::new(4.0, 5.0);
500 assert!((a * b).approx_eq(Vec2::new(8.0, 15.0)));
501 }
502
503 #[test]
504 fn test_div() {
505 let v = Vec2::new(4.0, 6.0);
506 assert!((v / 2.0).approx_eq(Vec2::new(2.0, 3.0)));
507 }
508
509 #[test]
510 fn test_neg() {
511 let v = Vec2::new(1.0, -2.0);
512 assert!((-v).approx_eq(Vec2::new(-1.0, 2.0)));
513 }
514
515 #[test]
516 fn test_from_tuple() {
517 let v: Vec2 = (1.0, 2.0).into();
518 assert!(v.approx_eq(Vec2::new(1.0, 2.0)));
519 }
520
521 #[test]
522 fn test_default() {
523 let v = Vec2::default();
524 assert!(v.approx_eq(Vec2::ZERO));
525 }
526}