1use std::fmt;
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
5use std::str::FromStr;
6
7use crate::utilities::math_utilities::{self, MathUtilities};
8use crate::utilities::span_helpers::InvariantF64;
9use crate::utilities::{FormatError, SpanStringTokenizer};
10use crate::Point;
11
12#[derive(Clone, Copy, Debug, PartialEq, Default)]
14pub struct Vector {
15 pub x: f64,
17 pub y: f64,
19}
20
21impl Vector {
22 pub const ZERO: Vector = Vector::new(0.0, 0.0);
24
25 pub const ONE: Vector = Vector::new(1.0, 1.0);
27
28 pub const UNIT_X: Vector = Vector::new(1.0, 0.0);
30
31 pub const UNIT_Y: Vector = Vector::new(0.0, 1.0);
33
34 #[inline]
36 pub const fn new(x: f64, y: f64) -> Self {
37 Self { x, y }
38 }
39
40 pub fn parse(s: &str) -> Result<Self, FormatError> {
42 SpanStringTokenizer::with_message(s, "Invalid Vector.")
43 .scope(|t| Ok(Vector::new(t.read_double()?, t.read_double()?)))
44 }
45
46 #[inline]
48 pub fn length(&self) -> f64 {
49 self.squared_length().sqrt()
50 }
51
52 #[inline]
54 pub fn squared_length(&self) -> f64 {
55 self.x * self.x + self.y * self.y
56 }
57
58 #[inline]
60 pub fn equals(&self, other: Vector) -> bool {
61 self.x == other.x && self.y == other.y
62 }
63
64 #[inline]
66 pub fn nearly_equals(&self, other: Vector) -> bool {
67 MathUtilities::are_close(self.x, other.x) && MathUtilities::are_close(self.y, other.y)
68 }
69
70 #[inline]
72 pub const fn with_x(&self, x: f64) -> Vector {
73 Vector::new(x, self.y)
74 }
75
76 #[inline]
78 pub const fn with_y(&self, y: f64) -> Vector {
79 Vector::new(self.x, y)
80 }
81
82 #[inline]
84 pub fn normalize(&self) -> Vector {
85 Vector::normalize_vector(*self)
86 }
87
88 #[inline]
90 pub fn negate(&self) -> Vector {
91 Vector::negate_vector(*self)
92 }
93
94 #[inline]
96 pub fn dot(a: Vector, b: Vector) -> f64 {
97 a.x * b.x + a.y * b.y
98 }
99
100 #[inline]
102 pub fn cross(a: Vector, b: Vector) -> f64 {
103 a.x * b.y - a.y * b.x
104 }
105
106 #[inline]
108 pub fn normalize_vector(vector: Vector) -> Vector {
109 Vector::divide_scalar(vector, vector.length())
110 }
111
112 #[inline]
114 pub fn divide(a: Vector, b: Vector) -> Vector {
115 Vector::new(a.x / b.x, a.y / b.y)
116 }
117
118 #[inline]
120 pub fn divide_scalar(vector: Vector, scalar: f64) -> Vector {
121 Vector::new(vector.x / scalar, vector.y / scalar)
122 }
123
124 #[inline]
126 pub fn multiply(a: Vector, b: Vector) -> Vector {
127 Vector::new(a.x * b.x, a.y * b.y)
128 }
129
130 #[inline]
132 pub fn multiply_scalar(vector: Vector, scalar: f64) -> Vector {
133 Vector::new(vector.x * scalar, vector.y * scalar)
134 }
135
136 #[inline]
138 #[allow(clippy::should_implement_trait)] pub fn add(a: Vector, b: Vector) -> Vector {
140 Vector::new(a.x + b.x, a.y + b.y)
141 }
142
143 #[inline]
145 pub fn subtract(a: Vector, b: Vector) -> Vector {
146 Vector::new(a.x - b.x, a.y - b.y)
147 }
148
149 #[inline]
151 pub fn negate_vector(vector: Vector) -> Vector {
152 Vector::new(-vector.x, -vector.y)
153 }
154
155 #[inline]
157 pub const fn deconstruct(&self) -> (f64, f64) {
158 (self.x, self.y)
159 }
160
161 #[inline]
164 pub fn abs(&self) -> Vector {
165 Vector::new(self.x.abs(), self.y.abs())
166 }
167
168 #[inline]
170 pub fn clamp(value: Vector, min: Vector, max: Vector) -> Vector {
171 Vector::min(Vector::max(value, min), max)
172 }
173
174 #[inline]
177 pub fn max(left: Vector, right: Vector) -> Vector {
178 Vector::new(
179 math_utilities::max(left.x, right.x),
180 math_utilities::max(left.y, right.y),
181 )
182 }
183
184 #[inline]
187 pub fn min(left: Vector, right: Vector) -> Vector {
188 Vector::new(
189 math_utilities::min(left.x, right.x),
190 math_utilities::min(left.y, right.y),
191 )
192 }
193
194 #[inline]
196 pub fn distance(value1: Vector, value2: Vector) -> f64 {
197 Vector::distance_squared(value1, value2).sqrt()
198 }
199
200 #[inline]
202 pub fn distance_squared(value1: Vector, value2: Vector) -> f64 {
203 let difference = value1 - value2;
204 Vector::dot(difference, difference)
205 }
206}
207
208impl From<Vector> for Point {
210 #[inline]
211 fn from(a: Vector) -> Point {
212 Point::new(a.x, a.y)
213 }
214}
215
216impl From<Vector> for (f64, f64) {
217 #[inline]
218 fn from(v: Vector) -> Self {
219 (v.x, v.y)
220 }
221}
222
223impl Mul for Vector {
225 type Output = f64;
226 #[inline]
227 fn mul(self, b: Vector) -> f64 {
228 Vector::dot(self, b)
229 }
230}
231
232impl Mul<f64> for Vector {
233 type Output = Vector;
234 #[inline]
235 fn mul(self, scale: f64) -> Vector {
236 Vector::multiply_scalar(self, scale)
237 }
238}
239
240impl Mul<Vector> for f64 {
241 type Output = Vector;
242 #[inline]
243 fn mul(self, vector: Vector) -> Vector {
244 Vector::multiply_scalar(vector, self)
245 }
246}
247
248impl Div<f64> for Vector {
249 type Output = Vector;
250 #[inline]
251 fn div(self, scale: f64) -> Vector {
252 Vector::divide_scalar(self, scale)
253 }
254}
255
256impl Neg for Vector {
257 type Output = Vector;
258 #[inline]
259 fn neg(self) -> Vector {
260 Vector::negate_vector(self)
261 }
262}
263
264impl Add for Vector {
265 type Output = Vector;
266 #[inline]
267 fn add(self, b: Vector) -> Vector {
268 Vector::add(self, b)
269 }
270}
271
272impl Sub for Vector {
273 type Output = Vector;
274 #[inline]
275 fn sub(self, b: Vector) -> Vector {
276 Vector::subtract(self, b)
277 }
278}
279
280impl AddAssign for Vector {
281 #[inline]
282 fn add_assign(&mut self, b: Vector) {
283 *self = *self + b;
284 }
285}
286
287impl SubAssign for Vector {
288 #[inline]
289 fn sub_assign(&mut self, b: Vector) {
290 *self = *self - b;
291 }
292}
293
294impl MulAssign<f64> for Vector {
295 #[inline]
296 fn mul_assign(&mut self, scale: f64) {
297 *self = *self * scale;
298 }
299}
300
301impl DivAssign<f64> for Vector {
302 #[inline]
303 fn div_assign(&mut self, scale: f64) {
304 *self = *self / scale;
305 }
306}
307
308impl FromStr for Vector {
309 type Err = FormatError;
310 #[inline]
311 fn from_str(s: &str) -> Result<Self, FormatError> {
312 Vector::parse(s)
313 }
314}
315
316impl fmt::Display for Vector {
317 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
318 write!(f, "{}, {}", InvariantF64(self.x), InvariantF64(self.y))
319 }
320}
321
322#[cfg(test)]
323mod tests {
324 use super::*;
325
326 #[test]
327 fn length_should_return_correct_length_of_vector() {
328 let vector = Vector::new(2.0, 4.0);
329 let length = ((2 * 2 + 4 * 4) as f64).sqrt();
330
331 assert_eq!(length, vector.length());
332 }
333
334 #[test]
335 fn length_squared_should_return_correct_length_of_vector() {
336 let vector_a = Vector::new(2.0, 4.0);
337 let squared_length_a = (2 * 2 + 4 * 4) as f64;
338
339 assert_eq!(squared_length_a, vector_a.squared_length());
340 }
341
342 #[test]
343 fn normalize_should_return_normalized_vector() {
344 let vector_a = Vector::new(13.0, 84.0);
347 let vector_b = Vector::new(-34.0, 345.0);
348 let vector_c = Vector::new(-34.0, -84.0);
349
350 assert_eq!(1.0, vector_a.normalize().length());
351 assert_eq!(1.0, vector_b.normalize().length());
352 assert_eq!(1.0, vector_c.normalize().length());
353 }
354
355 #[test]
356 fn negate_should_return_negated_vector() {
357 let vector = Vector::new(2.0, 4.0);
358 let negated = Vector::new(-2.0, -4.0);
359
360 assert_eq!(negated, vector.negate());
361 }
362
363 #[test]
364 fn dot_should_return_correct_value() {
365 let a = Vector::new(-6.0, 8.0);
366 let b = Vector::new(5.0, 12.0);
367
368 assert_eq!(66.0, Vector::dot(a, b));
369 }
370
371 #[test]
372 fn cross_should_return_correct_value() {
373 let a = Vector::new(-6.0, 8.0);
374 let b = Vector::new(5.0, 12.0);
375
376 assert_eq!(-112.0, Vector::cross(a, b));
377 }
378
379 #[test]
380 fn divied_by_vector_should_return_correct_value() {
381 let a = Vector::new(10.0, 2.0);
382 let b = Vector::new(5.0, 2.0);
383
384 let expected = Vector::new(2.0, 1.0);
385
386 assert_eq!(expected, Vector::divide(a, b));
387 }
388
389 #[test]
390 fn divied_should_return_correct_value() {
391 let vector = Vector::new(10.0, 2.0);
392 let expected = Vector::new(5.0, 1.0);
393
394 assert_eq!(expected, Vector::divide_scalar(vector, 2.0));
395 }
396
397 #[test]
398 fn multiply_by_vector_should_return_correct_value() {
399 let a = Vector::new(10.0, 2.0);
400 let b = Vector::new(2.0, 2.0);
401
402 let expected = Vector::new(20.0, 4.0);
403
404 assert_eq!(expected, Vector::multiply(a, b));
405 }
406
407 #[test]
408 fn multiply_should_return_correct_value() {
409 let vector = Vector::new(10.0, 2.0);
410
411 let expected = Vector::new(20.0, 4.0);
412
413 assert_eq!(expected, Vector::multiply_scalar(vector, 2.0));
414 }
415
416 #[test]
417 fn scale_vector_should_be_commutative() {
418 let vector = Vector::new(10.0, 2.0);
419
420 let expected = vector * 2.0;
421
422 assert_eq!(expected, 2.0 * vector);
423 }
424
425 #[test]
428 fn parse_display_and_helpers() {
429 assert_eq!(Vector::parse("1,2").unwrap(), Vector::new(1.0, 2.0));
430 assert_eq!(Vector::parse("x").unwrap_err().message(), "Invalid Vector.");
431 assert_eq!(Vector::new(1.0, 2.5).to_string(), "1, 2.5");
432 assert_eq!(Vector::new(-1.0, 2.0).abs(), Vector::new(1.0, 2.0));
433 assert_eq!(
434 Vector::clamp(Vector::new(-5.0, 5.0), Vector::ZERO, Vector::ONE),
435 Vector::new(0.0, 1.0)
436 );
437 assert_eq!(Vector::distance(Vector::ZERO, Vector::new(3.0, 4.0)), 5.0);
438 assert_eq!(Vector::new(1.0, 2.0) * Vector::new(3.0, 4.0), 11.0);
439 assert_eq!(Point::from(Vector::UNIT_X), Point::new(1.0, 0.0));
440 }
441}