1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#![allow(clippy::len_without_is_empty)] use std::ops; #[derive(Copy, Clone, Debug, PartialEq)] pub struct Vec2 { pub x: f32, pub y: f32, } impl Default for Vec2 { fn default() -> Self { Self::ZERO } } impl Vec2 { pub const ZERO: Self = Vec2 { x: 0.0, y: 0.0 }; pub const UNIT: Self = Vec2 { x: 1.0, y: 1.0 }; #[inline] pub fn new(x: f32, y: f32) -> Self { Vec2 { x, y } } #[inline] pub fn dot(self, other: Self) -> f32 { self.x * other.x + self.y * other.y } #[inline] pub fn len(self) -> f32 { self.dot(self).sqrt() } #[inline] pub fn angle(self, other: Self) -> f32 { (self.dot(other) / (self.len() * other.len())).acos() } #[inline] pub fn perpendicular(self) -> Vec2 { Vec2 { x: self.y, y: -self.x } } #[inline] pub fn scale(self, scalar: f32) -> Vec2 { Vec2 { x: self.x * scalar, y: self.y * scalar } } #[inline] pub fn normalized(self) -> Option<Vec2> { let len = self.len(); if len >= std::f32::EPSILON { let inv_len = 1.0 / len; return Some(Vec2 { x: self.x * inv_len, y: self.y * inv_len, }); } None } } impl ops::Add<Self> for Vec2 { type Output = Self; fn add(self, b: Self) -> Self { Self { x: self.x + b.x, y: self.y + b.y, } } } impl ops::AddAssign<Self> for Vec2 { fn add_assign(&mut self, b: Self) { self.x += b.x; self.y += b.y; } } impl ops::Sub<Self> for Vec2 { type Output = Self; fn sub(self, b: Self) -> Self { Self { x: self.x - b.x, y: self.y - b.y, } } } impl ops::SubAssign<Self> for Vec2 { fn sub_assign(&mut self, b: Self) { self.x -= b.x; self.y -= b.y; } }