Skip to main content

rogalik_math/vectors/
vector2.rs

1use num_traits::Num;
2use std::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};
3
4#[cfg(feature = "serialize")]
5use serde::{Deserialize, Serialize};
6
7pub type Vector2i = Vector2<i32>;
8pub type Vector2f = Vector2<f32>;
9
10#[derive(Copy, Clone, Debug, Default, Ord, PartialOrd, PartialEq, Eq, Hash)]
11#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
12pub struct Vector2<T: Num + Copy> {
13    pub x: T,
14    pub y: T,
15}
16impl<T: Num + Copy> Vector2<T> {
17    pub fn new(x: T, y: T) -> Self {
18        Vector2::<T> { x, y }
19    }
20    pub fn splat(v: T) -> Self {
21        Vector2::<T> { x: v, y: v }
22    }
23    pub fn dot(&self, other: &Self) -> T {
24        self.x * other.x + self.y * other.y
25    }
26}
27
28impl Vector2<i32> {
29    pub const ZERO: Vector2<i32> = Vector2::<i32> { x: 0, y: 0 };
30    pub const UP: Vector2<i32> = Vector2::<i32> { x: 0, y: 1 };
31    pub const DOWN: Vector2<i32> = Vector2::<i32> { x: 0, y: -1 };
32    pub const LEFT: Vector2<i32> = Vector2::<i32> { x: -1, y: 0 };
33    pub const RIGHT: Vector2<i32> = Vector2::<i32> { x: 1, y: 0 };
34    pub fn manhattan(&self, other: Vector2<i32>) -> i32 {
35        (self.x - other.x).abs() + (self.y - other.y).abs()
36    }
37    pub fn as_f32(&self) -> Vector2<f32> {
38        Vector2::<f32>::new(self.x as f32, self.y as f32)
39    }
40    #[inline(always)]
41    pub fn len(&self) -> f32 {
42        self.as_f32().len()
43    }
44    #[inline(always)]
45    pub fn len_sq(&self) -> f32 {
46        self.as_f32().len_sq()
47    }
48    pub fn angle(&self, other: &Self) -> f32 {
49        self.as_f32().angle(&other.as_f32())
50    }
51    pub fn signed_angle(&self, other: &Self) -> f32 {
52        self.as_f32().signed_angle(&other.as_f32())
53    }
54    pub fn clamped(&self) -> Self {
55        let x = if self.x != 0 {
56            self.x / self.x.abs()
57        } else {
58            0
59        };
60        let y = if self.y != 0 {
61            self.y / self.y.abs()
62        } else {
63            0
64        };
65        Vector2i { x, y }
66    }
67}
68
69impl Vector2<f32> {
70    pub const UP: Vector2<f32> = Vector2::<f32> { x: 0., y: 1. };
71    pub const DOWN: Vector2<f32> = Vector2::<f32> { x: 0., y: -1. };
72    pub const LEFT: Vector2<f32> = Vector2::<f32> { x: -1., y: 0. };
73    pub const RIGHT: Vector2<f32> = Vector2::<f32> { x: 1., y: 0. };
74    pub const ZERO: Vector2<f32> = Vector2::<f32> { x: 0., y: 0. };
75
76    #[inline(always)]
77    pub fn len(&self) -> f32 {
78        self.len_sq().sqrt()
79    }
80    #[inline(always)]
81    pub fn len_sq(&self) -> f32 {
82        self.x * self.x + self.y * self.y
83    }
84    pub fn angle(&self, other: &Self) -> f32 {
85        (self.dot(other) / (self.len() * other.len())).acos()
86    }
87    pub fn signed_angle(&self, other: &Self) -> f32 {
88        other.y.atan2(other.x) - self.y.atan2(self.x)
89    }
90    pub fn lerp(&self, other: &Self, t: f32) -> Self {
91        Vector2f::new(lerp(self.x, other.x, t), lerp(self.y, other.y, t))
92    }
93    pub fn normalized(&self) -> Self {
94        let m = self.len();
95        if m == 0. {
96            return Self::ZERO;
97        };
98        Vector2f::new(self.x / m, self.y / m)
99    }
100    pub fn round(&self) -> Self {
101        Self {
102            x: self.x.round(),
103            y: self.y.round(),
104        }
105    }
106}
107
108impl<T: Num + Copy> Add for Vector2<T> {
109    type Output = Self;
110
111    fn add(self, other: Self) -> Self {
112        return Vector2::<T>::new(self.x + other.x, self.y + other.y);
113    }
114}
115
116impl<T: Num + Copy> AddAssign for Vector2<T> {
117    fn add_assign(&mut self, other: Self) {
118        *self = Self {
119            x: self.x + other.x,
120            y: self.y + other.y,
121        };
122    }
123}
124
125impl<T: Num + Copy> Sub for Vector2<T> {
126    type Output = Self;
127
128    fn sub(self, other: Self) -> Self {
129        return Vector2::<T>::new(self.x - other.x, self.y - other.y);
130    }
131}
132
133impl<T: Num + Copy> SubAssign for Vector2<T> {
134    fn sub_assign(&mut self, other: Self) {
135        *self = Self {
136            x: self.x - other.x,
137            y: self.y - other.y,
138        };
139    }
140}
141
142impl<T: Num + Copy> Div<T> for Vector2<T> {
143    type Output = Self;
144
145    fn div(self, other: T) -> Self {
146        return Vector2::<T>::new(self.x / other, self.y / other);
147    }
148}
149
150impl<T: Num + Copy> Mul<T> for Vector2<T> {
151    type Output = Self;
152
153    fn mul(self, other: T) -> Self {
154        return Vector2::<T>::new(self.x * other, self.y * other);
155    }
156}
157
158// generic reverse multiplication didn't work due to orphan rules
159impl Mul<Vector2<f32>> for f32 {
160    type Output = Vector2<f32>;
161
162    fn mul(self, other: Vector2<f32>) -> Vector2<f32> {
163        return Vector2::<f32>::new(other.x * self, other.y * self);
164    }
165}
166impl Mul<Vector2<i32>> for i32 {
167    type Output = Vector2<i32>;
168
169    fn mul(self, other: Vector2<i32>) -> Vector2<i32> {
170        return Vector2::<i32>::new(other.x * self, other.y * self);
171    }
172}
173
174pub const ORTHO_DIRECTIONS: [Vector2i; 4] = [
175    Vector2i::UP,
176    Vector2i::DOWN,
177    Vector2i::LEFT,
178    Vector2i::RIGHT,
179];
180
181fn lerp(a: f32, b: f32, t: f32) -> f32 {
182    a * (1.0 - t) + t * b
183}