honeycomb_core/geometry/dim2/
vector.rs1use crate::geometry::{CoordsError, CoordsFloat};
6
7#[derive(Debug, Clone, Copy, Default, PartialEq)]
35pub struct Vector2<T: CoordsFloat>(pub T, pub T);
36
37unsafe impl<T: CoordsFloat> Send for Vector2<T> {}
38unsafe impl<T: CoordsFloat> Sync for Vector2<T> {}
39
40impl<T: CoordsFloat> Vector2<T> {
41 #[must_use = "unused return value"]
43 pub fn unit_x() -> Self {
44 Self(T::one(), T::zero())
45 }
46
47 #[must_use = "unused return value"]
49 pub fn unit_y() -> Self {
50 Self(T::zero(), T::one())
51 }
52
53 pub fn into_inner(self) -> (T, T) {
55 (self.0, self.1)
56 }
57
58 pub fn x(&self) -> T {
60 self.0
61 }
62
63 pub fn y(&self) -> T {
65 self.1
66 }
67
68 pub fn norm(&self) -> T {
70 self.0.hypot(self.1)
71 }
72
73 pub fn unit_dir(&self) -> Result<Self, CoordsError> {
79 let norm = self.norm();
80 if norm.is_zero() {
81 Err(CoordsError::InvalidUnitDir)
82 } else {
83 Ok(*self / norm)
84 }
85 }
86
87 pub fn normal_dir(&self) -> Result<Vector2<T>, CoordsError> {
93 Self(-self.1, self.0)
94 .unit_dir() .map_err(|_| CoordsError::InvalidNormDir)
96 }
97
98 pub fn dot(&self, other: &Vector2<T>) -> T {
100 self.0 * other.0 + self.1 * other.1
101 }
102}
103
104impl<T: CoordsFloat> From<(T, T)> for Vector2<T> {
107 fn from((x, y): (T, T)) -> Self {
108 Self(x, y)
109 }
110}
111
112impl<T: CoordsFloat> std::ops::Add<Vector2<T>> for Vector2<T> {
115 type Output = Self;
116
117 fn add(self, rhs: Vector2<T>) -> Self::Output {
118 Self(self.0 + rhs.0, self.1 + rhs.1)
119 }
120}
121
122impl<T: CoordsFloat> std::ops::AddAssign<Vector2<T>> for Vector2<T> {
123 fn add_assign(&mut self, rhs: Vector2<T>) {
124 self.0 += rhs.0;
125 self.1 += rhs.1;
126 }
127}
128
129impl<T: CoordsFloat> std::ops::Sub<Vector2<T>> for Vector2<T> {
130 type Output = Self;
131
132 fn sub(self, rhs: Vector2<T>) -> Self::Output {
133 Self(self.0 - rhs.0, self.1 - rhs.1)
134 }
135}
136
137impl<T: CoordsFloat> std::ops::SubAssign<Vector2<T>> for Vector2<T> {
138 fn sub_assign(&mut self, rhs: Vector2<T>) {
139 self.0 -= rhs.0;
140 self.0 -= rhs.0;
141 }
142}
143
144impl<T: CoordsFloat> std::ops::Mul<T> for Vector2<T> {
145 type Output = Self;
146
147 fn mul(self, rhs: T) -> Self::Output {
148 Self(self.0 * rhs, self.1 * rhs)
149 }
150}
151
152impl<T: CoordsFloat> std::ops::MulAssign<T> for Vector2<T> {
153 fn mul_assign(&mut self, rhs: T) {
154 self.0 *= rhs;
155 self.1 *= rhs;
156 }
157}
158
159impl<T: CoordsFloat> std::ops::Div<T> for Vector2<T> {
160 type Output = Self;
161
162 fn div(self, rhs: T) -> Self::Output {
163 assert!(!rhs.is_zero());
164 Self(self.0 / rhs, self.1 / rhs)
165 }
166}
167
168impl<T: CoordsFloat> std::ops::DivAssign<T> for Vector2<T> {
169 fn div_assign(&mut self, rhs: T) {
170 assert!(!rhs.is_zero());
171 self.0 /= rhs;
172 self.1 /= rhs;
173 }
174}
175
176impl<T: CoordsFloat> std::ops::Neg for Vector2<T> {
177 type Output = Self;
178
179 fn neg(self) -> Self::Output {
180 Self(-self.0, -self.1)
181 }
182}