1use std::fmt;
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
3
4use crate::Vec2b;
5
6#[repr(C)]
13#[derive(Clone, Copy, Default, PartialEq)]
14#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
15#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
16pub struct Vec2 {
17 pub x: f32,
19
20 pub y: f32,
22}
23
24#[inline(always)]
26pub const fn vec2(x: f32, y: f32) -> Vec2 {
27 Vec2 { x, y }
28}
29
30impl From<[f32; 2]> for Vec2 {
34 #[inline(always)]
35 fn from(v: [f32; 2]) -> Self {
36 Self { x: v[0], y: v[1] }
37 }
38}
39
40impl From<&[f32; 2]> for Vec2 {
41 #[inline(always)]
42 fn from(v: &[f32; 2]) -> Self {
43 Self { x: v[0], y: v[1] }
44 }
45}
46
47impl From<Vec2> for [f32; 2] {
48 #[inline(always)]
49 fn from(v: Vec2) -> Self {
50 [v.x, v.y]
51 }
52}
53
54impl From<&Vec2> for [f32; 2] {
55 #[inline(always)]
56 fn from(v: &Vec2) -> Self {
57 [v.x, v.y]
58 }
59}
60
61impl From<(f32, f32)> for Vec2 {
65 #[inline(always)]
66 fn from(v: (f32, f32)) -> Self {
67 Self { x: v.0, y: v.1 }
68 }
69}
70
71impl From<&(f32, f32)> for Vec2 {
72 #[inline(always)]
73 fn from(v: &(f32, f32)) -> Self {
74 Self { x: v.0, y: v.1 }
75 }
76}
77
78impl From<Vec2> for (f32, f32) {
79 #[inline(always)]
80 fn from(v: Vec2) -> Self {
81 (v.x, v.y)
82 }
83}
84
85impl From<&Vec2> for (f32, f32) {
86 #[inline(always)]
87 fn from(v: &Vec2) -> Self {
88 (v.x, v.y)
89 }
90}
91
92impl From<Vec2b> for Vec2 {
93 #[inline(always)]
94 fn from(v: Vec2b) -> Self {
95 Self {
96 x: v.x as i32 as f32,
97 y: v.y as i32 as f32,
98 }
99 }
100}
101
102#[cfg(feature = "mint")]
106impl From<mint::Vector2<f32>> for Vec2 {
107 #[inline]
108 fn from(v: mint::Vector2<f32>) -> Self {
109 Self::new(v.x, v.y)
110 }
111}
112
113#[cfg(feature = "mint")]
114impl From<Vec2> for mint::Vector2<f32> {
115 #[inline]
116 fn from(v: Vec2) -> Self {
117 Self { x: v.x, y: v.y }
118 }
119}
120
121impl Vec2 {
124 pub const X: Self = Self { x: 1.0, y: 0.0 };
126
127 pub const Y: Self = Self { x: 0.0, y: 1.0 };
129
130 pub const RIGHT: Self = Self { x: 1.0, y: 0.0 };
132
133 pub const LEFT: Self = Self { x: -1.0, y: 0.0 };
135
136 pub const UP: Self = Self { x: 0.0, y: -1.0 };
138
139 pub const DOWN: Self = Self { x: 0.0, y: 1.0 };
141
142 pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
143 pub const INFINITY: Self = Self::splat(f32::INFINITY);
144 pub const NAN: Self = Self::splat(f32::NAN);
145
146 #[inline(always)]
147 pub const fn new(x: f32, y: f32) -> Self {
148 Self { x, y }
149 }
150
151 #[inline(always)]
153 pub const fn splat(v: f32) -> Self {
154 Self { x: v, y: v }
155 }
156
157 #[inline(always)]
160 pub fn to_pos2(self) -> crate::Pos2 {
161 crate::Pos2 {
162 x: self.x,
163 y: self.y,
164 }
165 }
166
167 #[must_use]
169 #[inline(always)]
170 pub fn normalized(self) -> Self {
171 let len = self.length();
172 if len <= 0.0 {
173 self
174 } else {
175 self / len
176 }
177 }
178
179 #[inline(always)]
181 pub fn is_normalized(self) -> bool {
182 (self.length_sq() - 1.0).abs() < 2e-6
183 }
184
185 #[inline(always)]
188 pub fn rot90(self) -> Self {
189 vec2(self.y, -self.x)
190 }
191
192 #[inline(always)]
193 pub fn length(self) -> f32 {
194 self.x.hypot(self.y)
195 }
196
197 #[inline(always)]
198 pub fn length_sq(self) -> f32 {
199 self.x * self.x + self.y * self.y
200 }
201
202 #[inline(always)]
219 pub fn angle(self) -> f32 {
220 self.y.atan2(self.x)
221 }
222
223 #[inline(always)]
235 pub fn angled(angle: f32) -> Self {
236 let (sin, cos) = angle.sin_cos();
237 vec2(cos, sin)
238 }
239
240 #[must_use]
241 #[inline(always)]
242 pub fn floor(self) -> Self {
243 vec2(self.x.floor(), self.y.floor())
244 }
245
246 #[must_use]
247 #[inline(always)]
248 pub fn round(self) -> Self {
249 vec2(self.x.round(), self.y.round())
250 }
251
252 #[must_use]
253 #[inline(always)]
254 pub fn ceil(self) -> Self {
255 vec2(self.x.ceil(), self.y.ceil())
256 }
257
258 #[must_use]
259 #[inline]
260 pub fn abs(self) -> Self {
261 vec2(self.x.abs(), self.y.abs())
262 }
263
264 #[inline(always)]
266 pub fn is_finite(self) -> bool {
267 self.x.is_finite() && self.y.is_finite()
268 }
269
270 #[inline(always)]
272 pub fn any_nan(self) -> bool {
273 self.x.is_nan() || self.y.is_nan()
274 }
275
276 #[must_use]
277 #[inline]
278 pub fn min(self, other: Self) -> Self {
279 vec2(self.x.min(other.x), self.y.min(other.y))
280 }
281
282 #[must_use]
283 #[inline]
284 pub fn max(self, other: Self) -> Self {
285 vec2(self.x.max(other.x), self.y.max(other.y))
286 }
287
288 #[inline]
290 pub fn dot(self, other: Self) -> f32 {
291 self.x * other.x + self.y * other.y
292 }
293
294 #[must_use]
296 #[inline(always)]
297 pub fn min_elem(self) -> f32 {
298 self.x.min(self.y)
299 }
300
301 #[inline(always)]
303 #[must_use]
304 pub fn max_elem(self) -> f32 {
305 self.x.max(self.y)
306 }
307
308 #[inline]
310 #[must_use]
311 pub fn yx(self) -> Self {
312 Self {
313 x: self.y,
314 y: self.x,
315 }
316 }
317
318 #[must_use]
319 #[inline]
320 pub fn clamp(self, min: Self, max: Self) -> Self {
321 Self {
322 x: self.x.clamp(min.x, max.x),
323 y: self.y.clamp(min.y, max.y),
324 }
325 }
326}
327
328impl std::ops::Index<usize> for Vec2 {
329 type Output = f32;
330
331 #[inline(always)]
332 fn index(&self, index: usize) -> &f32 {
333 match index {
334 0 => &self.x,
335 1 => &self.y,
336 _ => panic!("Vec2 index out of bounds: {index}"),
337 }
338 }
339}
340
341impl std::ops::IndexMut<usize> for Vec2 {
342 #[inline(always)]
343 fn index_mut(&mut self, index: usize) -> &mut f32 {
344 match index {
345 0 => &mut self.x,
346 1 => &mut self.y,
347 _ => panic!("Vec2 index out of bounds: {index}"),
348 }
349 }
350}
351
352impl Eq for Vec2 {}
353
354impl Neg for Vec2 {
355 type Output = Self;
356
357 #[inline(always)]
358 fn neg(self) -> Self {
359 vec2(-self.x, -self.y)
360 }
361}
362
363impl AddAssign for Vec2 {
364 #[inline(always)]
365 fn add_assign(&mut self, rhs: Self) {
366 *self = Self {
367 x: self.x + rhs.x,
368 y: self.y + rhs.y,
369 };
370 }
371}
372
373impl SubAssign for Vec2 {
374 #[inline(always)]
375 fn sub_assign(&mut self, rhs: Self) {
376 *self = Self {
377 x: self.x - rhs.x,
378 y: self.y - rhs.y,
379 };
380 }
381}
382
383impl Add for Vec2 {
384 type Output = Self;
385
386 #[inline(always)]
387 fn add(self, rhs: Self) -> Self {
388 Self {
389 x: self.x + rhs.x,
390 y: self.y + rhs.y,
391 }
392 }
393}
394
395impl Sub for Vec2 {
396 type Output = Self;
397
398 #[inline(always)]
399 fn sub(self, rhs: Self) -> Self {
400 Self {
401 x: self.x - rhs.x,
402 y: self.y - rhs.y,
403 }
404 }
405}
406
407impl Mul<Self> for Vec2 {
409 type Output = Self;
410
411 #[inline(always)]
412 fn mul(self, vec: Self) -> Self {
413 Self {
414 x: self.x * vec.x,
415 y: self.y * vec.y,
416 }
417 }
418}
419
420impl Div<Self> for Vec2 {
422 type Output = Self;
423
424 #[inline(always)]
425 fn div(self, rhs: Self) -> Self {
426 Self {
427 x: self.x / rhs.x,
428 y: self.y / rhs.y,
429 }
430 }
431}
432
433impl MulAssign<f32> for Vec2 {
434 #[inline(always)]
435 fn mul_assign(&mut self, rhs: f32) {
436 self.x *= rhs;
437 self.y *= rhs;
438 }
439}
440
441impl DivAssign<f32> for Vec2 {
442 #[inline(always)]
443 fn div_assign(&mut self, rhs: f32) {
444 self.x /= rhs;
445 self.y /= rhs;
446 }
447}
448
449impl Mul<f32> for Vec2 {
450 type Output = Self;
451
452 #[inline(always)]
453 fn mul(self, factor: f32) -> Self {
454 Self {
455 x: self.x * factor,
456 y: self.y * factor,
457 }
458 }
459}
460
461impl Mul<Vec2> for f32 {
462 type Output = Vec2;
463
464 #[inline(always)]
465 fn mul(self, vec: Vec2) -> Vec2 {
466 Vec2 {
467 x: self * vec.x,
468 y: self * vec.y,
469 }
470 }
471}
472
473impl Div<f32> for Vec2 {
474 type Output = Self;
475
476 #[inline(always)]
477 fn div(self, factor: f32) -> Self {
478 Self {
479 x: self.x / factor,
480 y: self.y / factor,
481 }
482 }
483}
484
485impl fmt::Debug for Vec2 {
486 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487 if let Some(precision) = f.precision() {
488 write!(f, "[{1:.0$} {2:.0$}]", precision, self.x, self.y)
489 } else {
490 write!(f, "[{:.1} {:.1}]", self.x, self.y)
491 }
492 }
493}
494
495impl fmt::Display for Vec2 {
496 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
497 f.write_str("[")?;
498 self.x.fmt(f)?;
499 f.write_str(" ")?;
500 self.y.fmt(f)?;
501 f.write_str("]")?;
502 Ok(())
503 }
504}
505
506#[cfg(test)]
507mod test {
508 use super::*;
509
510 macro_rules! almost_eq {
511 ($left: expr, $right: expr) => {
512 let left = $left;
513 let right = $right;
514 assert!((left - right).abs() < 1e-6, "{} != {}", left, right);
515 };
516 }
517
518 #[test]
519 fn test_vec2() {
520 use std::f32::consts::TAU;
521
522 assert_eq!(Vec2::ZERO.angle(), 0.0);
523 assert_eq!(Vec2::angled(0.0).angle(), 0.0);
524 assert_eq!(Vec2::angled(1.0).angle(), 1.0);
525 assert_eq!(Vec2::X.angle(), 0.0);
526 assert_eq!(Vec2::Y.angle(), 0.25 * TAU);
527
528 assert_eq!(Vec2::RIGHT.angle(), 0.0);
529 assert_eq!(Vec2::DOWN.angle(), 0.25 * TAU);
530 almost_eq!(Vec2::LEFT.angle(), 0.50 * TAU);
531 assert_eq!(Vec2::UP.angle(), -0.25 * TAU);
532
533 let mut assignment = vec2(1.0, 2.0);
534 assignment += vec2(3.0, 4.0);
535 assert_eq!(assignment, vec2(4.0, 6.0));
536
537 let mut assignment = vec2(4.0, 6.0);
538 assignment -= vec2(1.0, 2.0);
539 assert_eq!(assignment, vec2(3.0, 4.0));
540
541 let mut assignment = vec2(1.0, 2.0);
542 assignment *= 2.0;
543 assert_eq!(assignment, vec2(2.0, 4.0));
544
545 let mut assignment = vec2(2.0, 4.0);
546 assignment /= 2.0;
547 assert_eq!(assignment, vec2(1.0, 2.0));
548 }
549
550 #[test]
551 fn test_vec2_normalized() {
552 fn generate_spiral(n: usize, start: Vec2, end: Vec2) -> impl Iterator<Item = Vec2> {
553 let angle_step = 2.0 * std::f32::consts::PI / n as f32;
554 let radius_step = (end.length() - start.length()) / n as f32;
555
556 (0..n).map(move |i| {
557 let angle = i as f32 * angle_step;
558 let radius = start.length() + i as f32 * radius_step;
559 let x = radius * angle.cos();
560 let y = radius * angle.sin();
561 vec2(x, y)
562 })
563 }
564
565 for v in generate_spiral(40, Vec2::splat(0.1), Vec2::splat(2.0)) {
566 let vn = v.normalized();
567 almost_eq!(vn.length(), 1.0);
568 assert!(vn.is_normalized());
569 }
570 }
571}