bymsdfgen_core/math/
vector2.rs1use std::ops::{Add, Div, Mul, Neg, Sub};
10
11#[derive(Debug, Clone, Copy, PartialEq, Default)]
13pub struct Vector2 {
14 pub x: f64,
15 pub y: f64,
16}
17
18pub type Point2 = Vector2;
20
21impl Vector2 {
22 pub const ZERO: Vector2 = Vector2 { x: 0.0, y: 0.0 };
23
24 #[inline]
25 pub const fn new(x: f64, y: f64) -> Self {
26 Vector2 { x, y }
27 }
28
29 #[inline]
31 pub const fn splat(v: f64) -> Self {
32 Vector2 { x: v, y: v }
33 }
34
35 #[inline]
36 pub fn squared_length(self) -> f64 {
37 self.x * self.x + self.y * self.y
38 }
39
40 #[inline]
41 pub fn length(self) -> f64 {
42 self.squared_length().sqrt()
43 }
44
45 #[inline]
50 pub fn normalize(self, allow_zero: bool) -> Vector2 {
51 let len = self.length();
52 if len != 0.0 {
53 Vector2::new(self.x / len, self.y / len)
54 } else {
55 Vector2::new(0.0, if allow_zero { 0.0 } else { 1.0 })
56 }
57 }
58
59 #[inline]
61 pub fn orthogonal(self, polarity: bool) -> Vector2 {
62 if polarity {
63 Vector2::new(-self.y, self.x)
64 } else {
65 Vector2::new(self.y, -self.x)
66 }
67 }
68
69 #[inline]
71 pub fn orthonormal(self, polarity: bool, allow_zero: bool) -> Vector2 {
72 let len = self.length();
73 if len != 0.0 {
74 if polarity {
75 Vector2::new(-self.y / len, self.x / len)
76 } else {
77 Vector2::new(self.y / len, -self.x / len)
78 }
79 } else {
80 let z = if allow_zero { 0.0 } else { 1.0 };
81 if polarity {
82 Vector2::new(0.0, z)
83 } else {
84 Vector2::new(0.0, -z)
85 }
86 }
87 }
88
89 #[inline]
91 pub fn is_nonzero(self) -> bool {
92 self.x != 0.0 || self.y != 0.0
93 }
94}
95
96#[inline]
98pub fn dot(a: Vector2, b: Vector2) -> f64 {
99 a.x * b.x + a.y * b.y
100}
101
102#[inline]
104pub fn cross(a: Vector2, b: Vector2) -> f64 {
105 a.x * b.y - a.y * b.x
106}
107
108impl Add for Vector2 {
109 type Output = Vector2;
110 #[inline]
111 fn add(self, o: Vector2) -> Vector2 {
112 Vector2::new(self.x + o.x, self.y + o.y)
113 }
114}
115
116impl Sub for Vector2 {
117 type Output = Vector2;
118 #[inline]
119 fn sub(self, o: Vector2) -> Vector2 {
120 Vector2::new(self.x - o.x, self.y - o.y)
121 }
122}
123
124impl Neg for Vector2 {
125 type Output = Vector2;
126 #[inline]
127 fn neg(self) -> Vector2 {
128 Vector2::new(-self.x, -self.y)
129 }
130}
131
132impl Mul for Vector2 {
134 type Output = Vector2;
135 #[inline]
136 fn mul(self, o: Vector2) -> Vector2 {
137 Vector2::new(self.x * o.x, self.y * o.y)
138 }
139}
140
141impl Div for Vector2 {
142 type Output = Vector2;
143 #[inline]
144 fn div(self, o: Vector2) -> Vector2 {
145 Vector2::new(self.x / o.x, self.y / o.y)
146 }
147}
148
149impl Mul<f64> for Vector2 {
151 type Output = Vector2;
152 #[inline]
153 fn mul(self, s: f64) -> Vector2 {
154 Vector2::new(self.x * s, self.y * s)
155 }
156}
157
158impl Div<f64> for Vector2 {
159 type Output = Vector2;
160 #[inline]
161 fn div(self, s: f64) -> Vector2 {
162 Vector2::new(self.x / s, self.y / s)
163 }
164}
165
166impl Mul<Vector2> for f64 {
168 type Output = Vector2;
169 #[inline]
170 fn mul(self, v: Vector2) -> Vector2 {
171 Vector2::new(self * v.x, self * v.y)
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178
179 #[test]
180 fn length_and_normalize() {
181 let v = Vector2::new(3.0, 4.0);
182 assert_eq!(v.length(), 5.0);
183 let n = v.normalize(false);
184 assert!((n.length() - 1.0).abs() < 1e-12);
185 }
186
187 #[test]
188 fn zero_normalize() {
189 assert_eq!(Vector2::ZERO.normalize(true), Vector2::ZERO);
190 assert_eq!(Vector2::ZERO.normalize(false), Vector2::new(0.0, 1.0));
191 }
192
193 #[test]
194 fn dot_and_cross() {
195 let a = Vector2::new(1.0, 2.0);
196 let b = Vector2::new(3.0, 4.0);
197 assert_eq!(dot(a, b), 11.0);
198 assert_eq!(cross(a, b), -2.0);
199 }
200
201 #[test]
202 fn orthogonal_polarity() {
203 let v = Vector2::new(1.0, 0.0);
204 assert_eq!(v.orthogonal(true), Vector2::new(0.0, 1.0));
205 assert_eq!(v.orthogonal(false), Vector2::new(0.0, -1.0));
206 }
207}