rogalik_math/vectors/
vector2.rs1use 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
158impl 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}