rsm_lib/vec2.rs
1use num_traits::{
2 NumAssign, Float
3};
4
5use std::slice::{
6 Iter,
7 IterMut
8};
9
10use std::ops::{
11 Neg, Add, Sub, Mul, Div,
12 AddAssign, SubAssign, MulAssign, DivAssign,
13 Index, IndexMut
14};
15
16use std::fmt;
17
18use crate::vec3::Vec3;
19use crate::vec4::Vec4;
20use crate::mat2::Mat2;
21use crate::mat3::Mat3;
22
23/// Represents a 2D vector with generic numeric components.
24///
25/// `Vec2` is a generic structure that represents a 2-dimensional vector with components `x` and `y`.
26/// It provides a variety of methods for vector operations, including vector arithmetic,
27/// normalization, dot product, distance calculation, and linear interpolation.
28///
29/// # Type Parameters
30///
31/// - `T`: The numeric type of the vector components. This type must implement certain traits
32/// such as `Zero`, `One`, `NumAssign`, `Copy`, and others depending on the method.
33#[derive(Debug, Default, Copy, Clone, PartialEq)]
34pub struct Vec2<T> {
35 pub x: T,
36 pub y: T,
37}
38
39impl<T> Vec2<T>
40where
41 T: NumAssign + Copy,
42{
43 /// Creates a new vector with the given `x` and `y` components.
44 ///
45 /// # Parameters
46 ///
47 /// - `x`: The x-coordinate of the vector.
48 /// - `y`: The y-coordinate of the vector.
49 ///
50 /// # Returns
51 ///
52 /// A `Vec2` instance with the specified `x` and `y` components.
53 ///
54 /// # Example
55 ///
56 /// ```
57 /// let vec = Vec2::new(3.0, 4.0);
58 /// assert_eq!(vec.x, 3.0);
59 /// assert_eq!(vec.y, 4.0);
60 /// ```
61 #[inline]
62 pub fn new(x: T, y: T) -> Self {
63 Self { x, y }
64 }
65
66 /// Returns a vector with both components set to zero.
67 ///
68 /// This is commonly used to initialize or reset a vector to a zero state.
69 ///
70 /// # Returns
71 ///
72 /// A `Vec2` instance where both components are zero.
73 ///
74 /// # Example
75 ///
76 /// ```
77 /// let vec = Vec2::zero();
78 /// assert_eq!(vec.x, 0.0);
79 /// assert_eq!(vec.y, 0.0);
80 /// ```
81 #[inline]
82 pub fn zero() -> Self {
83 Self::new(T::zero(), T::zero())
84 }
85
86 /// Returns a vector with both components set to one.
87 ///
88 /// This is useful for initializing or scaling vectors to a unit state.
89 ///
90 /// # Returns
91 ///
92 /// A `Vec2` instance where both components are one.
93 ///
94 /// # Example
95 ///
96 /// ```
97 /// let vec = Vec2::one();
98 /// assert_eq!(vec.x, 1.0);
99 /// assert_eq!(vec.y, 1.0);
100 /// ```
101 #[inline]
102 pub fn one() -> Self {
103 Self::new(T::one(), T::one())
104 }
105
106 /// Creates a vector with both components set to the given value `v`.
107 ///
108 /// # Parameters
109 ///
110 /// - `v`: The value to be assigned to both the x and y components of the vector.
111 ///
112 /// # Returns
113 ///
114 /// A `Vec2` instance where both components are initialized to `v`.
115 ///
116 /// # Example
117 ///
118 /// ```
119 /// let vec = Vec2::set(5.0);
120 /// assert_eq!(vec.x, 5.0);
121 /// assert_eq!(vec.y, 5.0);
122 /// ```
123 #[inline]
124 pub fn set(v: T) -> Self {
125 Self { x: v, y: v }
126 }
127
128 /// Creates a `Vec2` from a `Vec3` by using the `x` and `y` components of the `Vec3`.
129 ///
130 /// This is useful when you want to convert a 3-dimensional vector to a 2-dimensional vector,
131 /// discarding the `z` component.
132 ///
133 /// # Parameters
134 ///
135 /// - `v`: A reference to a `Vec3` instance from which the `x` and `y` components will be used.
136 ///
137 /// # Returns
138 ///
139 /// A `Vec2` instance with the `x` and `y` components taken from the `Vec3` instance.
140 ///
141 /// # Example
142 ///
143 /// ```
144 /// let vec3 = Vec3::new(1.0, 2.0, 3.0);
145 /// let vec2 = Vec2::from_vec3(&vec3);
146 /// assert_eq!(vec2.x, 1.0);
147 /// assert_eq!(vec2.y, 2.0);
148 /// ```
149 ///
150 #[inline]
151 pub fn from_vec3(v: &Vec3<T>) -> Self {
152 Self::new(v.x, v.y)
153 }
154
155 /// Creates a `Vec2` from a `Vec4` by using the `x` and `y` components of the `Vec4`.
156 ///
157 /// This is useful when you want to convert a 4-dimensional vector to a 2-dimensional vector,
158 /// discarding the `z` and `w` components.
159 ///
160 /// # Parameters
161 ///
162 /// - `v`: A reference to a `Vec4` instance from which the `x` and `y` components will be used.
163 ///
164 /// # Returns
165 ///
166 /// A `Vec2` instance with the `x` and `y` components taken from the `Vec4` instance.
167 ///
168 /// # Example
169 ///
170 /// ```
171 /// let vec4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
172 /// let vec2 = Vec2::from_vec4(&vec4);
173 /// assert_eq!(vec2.x, 1.0);
174 /// assert_eq!(vec2.y, 2.0);
175 /// ```
176 #[inline]
177 pub fn from_vec4(v: &Vec4<T>) -> Self {
178 Self::new(v.x, v.y)
179 }
180
181 /// Computes the dot product of the vector with another vector.
182 ///
183 /// The dot product is calculated as the sum of the products of the corresponding components of the two vectors.
184 /// It is a measure of how much one vector extends in the direction of another. The result is a scalar value.
185 ///
186 /// # Arguments
187 ///
188 /// - `other`: The other vector with which to compute the dot product.
189 ///
190 /// # Returns
191 ///
192 /// The dot product of the two vectors as a value of type `T`.
193 ///
194 /// # Constraints
195 ///
196 /// - `T` must implement the `Mul` and `Add` traits to support multiplication and addition operations.
197 ///
198 /// # Example
199 ///
200 /// ```
201 /// let vec1 = Vec2::new(1.0, 2.0);
202 /// let vec2 = Vec2::new(3.0, 4.0);
203 /// assert_eq!(vec1.dot(&vec2), 11.0);
204 /// ```
205 #[inline]
206 pub fn dot(&self, other: &Self) -> T {
207 self.x * other.x + self.y * other.y
208 }
209
210 /// Computes the squared length (or magnitude) of the vector.
211 ///
212 /// The squared length is calculated as the sum of the squares of the components of the vector.
213 /// This is often used in computations where you need the length of the vector but want to avoid
214 /// the overhead of computing the square root.
215 ///
216 /// # Returns
217 ///
218 /// The squared length of the vector as a value of type `T`. This is the result of the expression
219 /// `x * x + y * y`.
220 ///
221 /// # Constraints
222 ///
223 /// - `T` must implement the `Mul` and `Add` traits to support multiplication and addition operations.
224 ///
225 /// # Example
226 ///
227 /// ```
228 /// let vec = Vec2::new(3.0, 4.0);
229 /// assert_eq!(vec.length_squared(), 25.0);
230 /// ```
231 ///
232 #[inline]
233 pub fn length_squared(&self) -> T {
234 self.x * self.x + self.y * self.y
235 }
236
237 /// Computes the squared distance between this vector and another vector.
238 ///
239 /// This method calculates the squared distance between the two vectors without computing the square root,
240 /// which can be more efficient, especially when comparing distances or performing multiple distance calculations.
241 ///
242 /// # Arguments
243 ///
244 /// - `other`: The other vector to which the squared distance is calculated.
245 ///
246 /// # Returns
247 ///
248 /// The squared distance between the two vectors as a value of type `T`.
249 ///
250 /// # Constraints
251 ///
252 /// - `T` must implement the `Sub` and `Mul` traits to support subtraction and multiplication operations.
253 ///
254 /// # Example
255 ///
256 /// ```
257 /// let vec1 = Vec2::new(1.0, 2.0);
258 /// let vec2 = Vec2::new(4.0, 6.0);
259 /// assert_eq!(vec1.distance_squared(&vec2), 25.0);
260 /// ```
261 #[inline]
262 pub fn distance_squared(&self, other: &Self) -> T {
263 (self.x - other.x) * (self.x - other.x) +
264 (self.y - other.y) * (self.y - other.y)
265 }
266
267 /// Transforms a 2D vector using a 2x2 matrix.
268 ///
269 /// This method applies a 2D affine transformation to a `Vec2<T>` using a `Mat2<T>` matrix.
270 /// The matrix multiplication is performed as follows:
271 ///
272 /// ```text
273 /// [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ]
274 /// [ y' ] [ m10 m11 ] [ y ] [ m10 * x + m11 * y ]
275 /// ```
276 ///
277 /// where `Vec2<T>` is represented as `[x, y]` and `Mat2<T>` is represented as:
278 ///
279 /// ```text
280 /// [ m00 m01 ]
281 /// [ m10 m11 ]
282 /// ```
283 ///
284 /// Parameters:
285 ///
286 /// - `transform`: A reference to a `Mat2<T>` matrix representing the 2D transformation to be applied.
287 ///
288 /// Returns:
289 /// - A new `Vec2<T>` that is the result of transforming the original vector by the matrix.
290 ///
291 /// Example:
292 /// ```
293 /// let vec = Vec2::new(1.0, 2.0);
294 /// let mat = Mat2::new(&Vec2::new(1.0, 0.0), &Vec2::new(0.0, 1.0));
295 /// let transformed_vec = vec.transform_mat2(&mat);
296 /// assert_eq!(transformed_vec, Vec2::new(1.0, 2.0));
297 /// ```
298 ///
299 /// This example shows a simple case where the matrix is the identity matrix, and hence
300 /// the vector remains unchanged.
301 #[inline]
302 pub fn transform_mat2(&self, transform: &Mat2<T>) -> Self {
303 let x = transform.0.x * self.x + transform.1.x * self.y;
304 let y = transform.0.y * self.x + transform.1.y * self.y;
305 Self::new(x, y)
306 }
307
308 /// Transforms a 2D vector using a 3x3 matrix.
309 ///
310 /// This method applies a 2D affine transformation to a `Vec2<T>` using a `Mat3<T>` matrix.
311 /// The matrix multiplication is performed as follows:
312 ///
313 /// ```text
314 /// [ x' ] = [ m00 m01 m02 ] [ x ] = [ m00 * x + m01 * y + m02 ]
315 /// [ y' ] [ m10 m11 m12 ] [ y ] [ m10 * x + m11 * y + m12 ]
316 /// [ w' ] [ 0 0 1 ] [ 1 ] [ 1 ] // Homogeneous coordinate
317 /// ```
318 ///
319 /// where `Vec2<T>` is represented as `[x, y]` and `Mat3<T>` is represented as:
320 ///
321 /// ```text
322 /// [ m00 m01 m02 ]
323 /// [ m10 m11 m12 ]
324 /// [ 0 0 1 ]
325 /// ```
326 ///
327 /// Parameters:
328 ///
329 /// - `transform`: A reference to a `Mat3<T>` matrix representing the 2D affine transformation to be applied.
330 ///
331 /// Returns:
332 ///
333 /// - A new `Vec2<T>` that is the result of transforming the original vector by the matrix.
334 ///
335 /// Example:
336 /// ```
337 /// let vec = Vec2::new(1.0, 2.0);
338 /// let mat = Mat3::new(
339 /// Vec3::new(1.0, 0.0, 3.0), // Translation x
340 /// Vec3::new(0.0, 1.0, 4.0), // Translation y
341 /// Vec3::new(0.0, 0.0, 1.0) // Homogeneous coordinate
342 /// );
343 /// let transformed_vec = vec.transform_mat3(&mat);
344 /// assert_eq!(transformed_vec, Vec2::new(4.0, 6.0));
345 /// ```
346 ///
347 /// In this example, the `Mat3` matrix represents a translation, moving the vector `(1.0, 2.0)`
348 /// to `(4.0, 6.0)`.
349 #[inline]
350 pub fn transform_mat3(&self, transform: &Mat3<T>) -> Self {
351 let x = transform.0.x * self.x + transform.1.x * self.y + transform.2.x;
352 let y = transform.0.y * self.x + transform.1.y * self.y + transform.2.y;
353 Self::new(x, y)
354 }
355}
356
357impl<T> Vec2<T>
358where
359 T: NumAssign + Copy + PartialOrd,
360{
361 /// Returns a new `Vec2` containing the component-wise minimum of `self` and `other`.
362 ///
363 /// For each component `x` and `y`, the method compares the corresponding components of
364 /// `self` and `other` and returns the smaller of the two.
365 ///
366 /// # Parameters
367 ///
368 /// - `other`: A reference to another `Vec2` instance to compare with `self`.
369 ///
370 /// # Returns
371 ///
372 /// A new `Vec2` where each component is the minimum value between `self` and `other`.
373 ///
374 /// # Examples
375 ///
376 /// ```
377 /// let vec1 = Vec2::new(3, 7);
378 /// let vec2 = Vec2::new(4, 5);
379 /// let min_vec = vec1.min(&vec2);
380 /// assert_eq!(min_vec, Vec2::new(3, 5));
381 /// ```
382 #[inline]
383 pub fn min(&self, other: &Self) -> Self {
384 Self::new(
385 if self.x < other.x { self.x } else { other.x },
386 if self.y < other.y { self.y } else { other.y }
387 )
388 }
389
390 /// Returns a new `Vec2` containing the component-wise maximum of `self` and `other`.
391 ///
392 /// For each component `x` and `y`, the method compares the corresponding components of
393 /// `self` and `other` and returns the larger of the two.
394 ///
395 /// # Parameters
396 ///
397 /// - `other`: A reference to another `Vec2` instance to compare with `self`.
398 ///
399 /// # Returns
400 ///
401 /// A new `Vec2` where each component is the maximum value between `self` and `other`.
402 ///
403 /// # Examples
404 ///
405 /// ```
406 /// let vec1 = Vec2::new(3, 7);
407 /// let vec2 = Vec2::new(4, 5);
408 /// let max_vec = vec1.max(&vec2);
409 /// assert_eq!(max_vec, Vec2::new(4, 7));
410 /// ```
411 #[inline]
412 pub fn max(&self, other: &Self) -> Self {
413 Self::new(
414 if self.x > other.x { self.x } else { other.x },
415 if self.y > other.y { self.y } else { other.y }
416 )
417 }
418
419 /// Clamps the components of `self` to lie within the inclusive range defined by `min` and `max`.
420 ///
421 /// For each component `x` and `y`, the method compares the corresponding component of `self`
422 /// to the provided `min` and `max` values and ensures it lies within this range. If a component
423 /// of `self` is less than the corresponding component of `min`, it is set to the `min` value.
424 /// If it is greater than the corresponding component of `max`, it is set to the `max` value.
425 ///
426 /// # Parameters
427 ///
428 /// - `min`: A reference to a `Vec2` representing the minimum allowed values for each component.
429 /// - `max`: A reference to a `Vec2` representing the maximum allowed values for each component.
430 ///
431 /// # Returns
432 ///
433 /// A new `Vec2` where each component is clamped to the range `[min, max]`.
434 ///
435 /// # Panics
436 ///
437 /// This method will panic if any component of `min` is greater than the corresponding component
438 /// of `max`, as it is not possible to clamp a value within an invalid range.
439 ///
440 /// # Examples
441 ///
442 /// ```
443 /// let vec = Vec2::new(5, 10);
444 /// let min_vec = Vec2::new(3, 7);
445 /// let max_vec = Vec2::new(6, 8);
446 /// let clamped_vec = vec.clamp(&min_vec, &max_vec);
447 /// assert_eq!(clamped_vec, Vec2::new(5, 8));
448 /// ```
449 #[inline]
450 pub fn clamp(&self, min: &Self, max: &Self) -> Self {
451 Self::new(
452 if self.x < min.x { min.x } else if self.x > max.x { max.x } else { self.x },
453 if self.y < min.y { min.y } else if self.y > max.y { max.y } else { self.y }
454 )
455 }
456}
457
458impl<T> Vec2<T>
459where
460 T: NumAssign + Float,
461{
462 /// Returns the length (magnitude) of the vector.
463 ///
464 /// The length of the vector is calculated as the Euclidean norm, which is the square root of
465 /// the sum of the squares of its components.
466 ///
467 /// # Returns
468 ///
469 /// The length (magnitude) of the vector as a value of type `T`.
470 ///
471 /// # Constraints
472 ///
473 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
474 ///
475 /// # Example
476 ///
477 /// ```
478 /// let vec = Vec2::new(3.0, 4.0);
479 /// assert_eq!(vec.length(), 5.0);
480 /// ```
481 #[inline]
482 pub fn length(&self) -> T {
483 (self.x * self.x + self.y * self.y).sqrt()
484 }
485
486 /// Returns a normalized (unit length) version of the vector.
487 ///
488 /// The normalized vector is a unit vector that points in the same direction as the original vector.
489 /// Normalization is achieved by dividing each component of the vector by its length.
490 /// If the vector has zero length (is a zero vector), `None` is returned to indicate that normalization is not possible.
491 ///
492 /// # Returns
493 ///
494 /// - `Some(Self)`: A new vector with unit length pointing in the same direction as the original vector, if normalization is possible.
495 /// - `None`: If the vector has zero length, indicating that it cannot be normalized.
496 ///
497 /// # Constraints
498 ///
499 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
500 ///
501 /// # Example
502 ///
503 /// ```
504 /// let vec = Vec2::new(3.0, 4.0);
505 /// let normalized = vec.normalize().unwrap();
506 /// assert_eq!(normalized.length(), 1.0);
507 /// ```
508 #[inline]
509 pub fn normalize(&self) -> Option<Self> {
510 let len = self.length();
511 if len.is_zero() {
512 None
513 } else {
514 Some(Self::new(self.x / len, self.y / len))
515 }
516 }
517
518 /// Computes the distance between this vector and another vector.
519 ///
520 /// The distance is calculated as the Euclidean distance between the two vectors, which is the length of the vector
521 /// representing the difference between them.
522 ///
523 /// # Arguments
524 ///
525 /// - `other`: The other vector to which the distance is calculated.
526 ///
527 /// # Returns
528 ///
529 /// The distance between the two vectors as a value of type `T`.
530 ///
531 /// # Constraints
532 ///
533 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
534 ///
535 /// # Example
536 ///
537 /// ```
538 /// let vec1 = Vec2::new(1.0, 2.0);
539 /// let vec2 = Vec2::new(4.0, 6.0);
540 /// assert_eq!(vec1.distance(&vec2), 5.0);
541 /// ```
542 #[inline]
543 pub fn distance(&self, other: &Self) -> T {
544 (
545 (self.x - other.x) * (self.x - other.x) +
546 (self.y - other.y) * (self.y - other.y)
547 )
548 .sqrt()
549 }
550
551 /// Computes the direction from this vector to another vector.
552 ///
553 /// This method calculates a normalized vector that points from `self` to `other`. If `self` and `other` are the same vector,
554 /// resulting in a zero-length vector, `None` is returned.
555 ///
556 /// # Arguments
557 ///
558 /// - `other`: The target vector to which the direction is calculated.
559 ///
560 /// # Returns
561 ///
562 /// An `Option<Self>` where:
563 /// - `Some(Self)` contains the normalized direction vector pointing from `self` to `other` if the vectors are not identical.
564 /// - `None` if `self` and `other` are identical (i.e., the direction vector has zero length).
565 ///
566 /// # Constraints
567 ///
568 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
569 ///
570 /// # Example
571 ///
572 /// ```
573 /// let vec1 = Vec2::new(1.0, 2.0);
574 /// let vec2 = Vec2::new(4.0, 6.0);
575 /// if let Some(direction) = vec1.direction(&vec2) {
576 /// assert_eq!(direction, Vec2::new(0.6, 0.8));
577 /// } else {
578 /// panic!("The vectors are identical, so no direction can be computed.");
579 /// }
580 /// ```
581 #[inline]
582 pub fn direction(&self, other: &Self) -> Option<Self> {
583 let direction = Self::new(
584 other.x - self.x,
585 other.y - self.y
586 );
587 direction.normalize()
588 }
589
590 /// Computes the angle (in radians) between this vector and another vector.
591 ///
592 /// This method calculates the angle between `self` and `other` vectors using the arctangent of the cross product
593 /// and dot product of the vectors. The result is in radians, and the angle is measured counterclockwise.
594 ///
595 /// # Arguments
596 ///
597 /// - `other`: The other vector to which the angle is computed.
598 ///
599 /// # Returns
600 ///
601 /// The angle between the vectors as a value of type `T`.
602 ///
603 /// # Constraints
604 ///
605 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
606 ///
607 /// # Example
608 ///
609 /// ```
610 /// let vec1 = Vec2::new(1.0, 0.0);
611 /// let vec2 = Vec2::new(0.0, 1.0);
612 /// assert_eq!(vec1.angle(&vec2), std::f32::consts::PI / 2.0);
613 /// ```
614 #[inline]
615 pub fn angle(&self, other: &Self) -> T {
616 let dot = self.x * other.x + self.y * other.y;
617 let det = self.x * other.y - self.y * other.x;
618 det.atan2(dot)
619 }
620
621 /// Computes the angle (in radians) of the line defined by two vectors.
622 ///
623 /// This method calculates the angle of the line segment defined by `self` and `end` relative to the positive x-axis.
624 /// The vectors should be normalized for accurate results. The angle is measured from the positive x-axis to the line,
625 /// and the result is in radians. The direction is clockwise from the positive x-axis.
626 ///
627 /// # Arguments
628 ///
629 /// - `end`: The end point of the line segment from `self` to `end`.
630 ///
631 /// # Returns
632 ///
633 /// The angle of the line segment as a value of type `T`.
634 ///
635 /// # Constraints
636 ///
637 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
638 ///
639 /// # Example
640 ///
641 /// ```
642 /// let start = Vec2::new(1.0, 1.0);
643 /// let end = Vec2::new(4.0, 3.0);
644 /// assert_eq!(start.line_angle(&end), (-0.6435011).abs()); // Example result
645 /// ```
646 #[inline]
647 pub fn line_angle(&self, end: &Self) -> T {
648 // Note: The angle is measured clockwise from the positive x-axis.
649 // If vectors are normalized, this is simply -atan2 of the difference.
650 - (end.y - self.y).atan2(end.x - self.x)
651 }
652
653 /// Linearly interpolates between this vector and another vector.
654 ///
655 /// This method performs linear interpolation between `self` and `other` based on the parameter `t`.
656 /// When `t` is `0.0`, the result is `self`. When `t` is `1.0`, the result is `other`. For values of `t`
657 /// between `0.0` and `1.0`, the result is a point between `self` and `other` on the line segment connecting them.
658 ///
659 /// # Arguments
660 ///
661 /// - `other`: The vector to interpolate towards.
662 /// - `t`: The interpolation factor, where `t` ranges from `0.0` to `1.0`.
663 ///
664 /// # Returns
665 ///
666 /// A new vector representing the point that is linearly interpolated between `self` and `other`.
667 ///
668 /// # Constraints
669 ///
670 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
671 ///
672 /// # Example
673 ///
674 /// ```
675 /// let start = Vec2::new(0.0, 0.0);
676 /// let end = Vec2::new(10.0, 10.0);
677 /// let result = start.lerp(&end, 0.5);
678 /// assert_eq!(result, Vec2::new(5.0, 5.0));
679 /// ```
680 #[inline]
681 pub fn lerp(&self, other: &Self, t: T) -> Self {
682 Self::new(
683 self.x + t * (other.x - self.x),
684 self.y + t * (other.y - self.y))
685 }
686
687 /// Computes the reflection of the vector around a given normal vector.
688 ///
689 /// The reflection is calculated using the formula:
690 /// `reflected = self - 2 * (self · normal) * normal`
691 /// where `self · normal` is the dot product between `self` and `normal`.
692 ///
693 /// # Parameters
694 ///
695 /// - `normal`: The normal vector around which to reflect. This vector should be normalized.
696 ///
697 /// # Returns
698 ///
699 /// A new vector representing the reflection of `self` around `normal`.
700 ///
701 /// # Constraints
702 ///
703 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
704 ///
705 /// # Example
706 ///
707 /// ```
708 /// let incident = Vec2::new(1.0, -1.0);
709 /// let normal = Vec2::new(0.0, 1.0).normalize().unwrap(); // Normalized normal vector
710 /// let reflected = incident.reflect(&normal);
711 /// assert_eq!(reflected, Vec2::new(1.0, 1.0)); // Reflection of (1.0, -1.0) around (0.0, 1.0) is (1.0, 1.0)
712 /// ```
713 #[inline]
714 pub fn reflect(&self, normal: &Self) -> Self {
715 let dot = self.x * normal.x + self.y * normal.y;
716 let two = T::from(2.0).unwrap();
717
718 Self::new(
719 self.x - (two * normal.x) * dot,
720 self.y - (two * normal.y) * dot
721 )
722 }
723
724 /// Computes the direction of a refracted ray.
725 ///
726 /// This function calculates the direction of a refracted ray given the direction of the incoming ray,
727 /// the normal vector of the surface, and the ratio of the refractive indices of the two media.
728 ///
729 /// # Parameters
730 ///
731 /// - `normal`: The normalized normal vector of the interface between two optical media.
732 /// - `r`: The ratio of the refractive index of the medium from where the ray comes
733 /// to the refractive index of the medium on the other side of the surface.
734 ///
735 /// # Returns
736 ///
737 /// An `Option<Self>`. Returns `Some(Self)` with the direction of the refracted ray if refraction is possible,
738 /// or `None` if refraction is not possible (e.g., due to total internal reflection).
739 ///
740 /// # Constraints
741 ///
742 /// - `T` must implement the `Float` trait, which provides methods for floating-point arithmetic.
743 ///
744 /// # Notes
745 ///
746 /// - The incoming ray and the normal vector should be normalized.
747 /// - The result will be `None` if total internal reflection occurs (i.e., `d < 0`).
748 #[inline]
749 pub fn refract(&self, normal: &Self, r: T) -> Option<Self> {
750 // Calculate the dot product between the incoming ray and the normal
751 let dot = self.dot(normal);
752
753 // Compute the squared ratio of the refractive indices
754 let r2 = r * r;
755
756 // Compute the discriminant to check for total internal reflection
757 let one = T::one();
758 let zero = T::zero();
759 let d = one - r2 * (one - dot * dot);
760
761 // If d is negative, total internal reflection occurs, so refraction is not possible
762 if d < zero {
763 None
764 } else {
765 // Calculate the square root of the discriminant
766 let sqrt_d = d.sqrt();
767
768 // Calculate the direction of the refracted ray
769 let r_dot = r * dot;
770 let v_x = r * self.x - (r_dot + sqrt_d) * normal.x;
771 let v_y = r * self.y - (r_dot + sqrt_d) * normal.y;
772
773 // Return the refracted ray direction
774 Some(Self::new(v_x, v_y))
775 }
776 }
777
778 /// Rotates the vector by a given angle (in radians) around the origin.
779 ///
780 /// This method applies a 2D rotation to the vector, rotating it by the specified
781 /// angle in a counterclockwise direction around the origin (0, 0).
782 ///
783 /// # Arguments
784 ///
785 /// * `angle` - The angle of rotation in radians. A positive angle rotates the vector
786 /// counterclockwise, while a negative angle rotates it clockwise.
787 ///
788 /// # Returns
789 ///
790 /// A new vector that represents the original vector rotated by the specified angle.
791 ///
792 /// # Examples
793 ///
794 /// ```
795 /// let v = Vec2::new(1.0, 0.0);
796 /// let rotated_v = v.rotate(std::f32::consts::PI / 2.0);
797 /// assert_eq!(rotated_v, Vec2::new(0.0, 1.0));
798 /// ```
799 #[inline]
800 pub fn rotate(&self, angle: T) -> Self {
801 let c = angle.cos();
802 let s = angle.sin();
803 Self::new(
804 self.x * c - self.y * s,
805 self.x * s + self.y * c,
806 )
807 }
808
809 /// Moves the vector towards a target vector by a specified maximum distance.
810 ///
811 /// This method calculates the direction from the vector to a target vector and
812 /// moves the vector along that direction by a specified maximum distance. If the
813 /// target vector is closer than the specified distance, the vector will be moved
814 /// directly to the target position.
815 ///
816 /// # Arguments
817 ///
818 /// * `target` - The target vector to move towards.
819 /// * `max_distance` - The maximum distance to move. If this distance is greater
820 /// than the distance to the target, the vector will move directly
821 /// to the target.
822 ///
823 /// # Returns
824 ///
825 /// A new vector that represents the original vector moved towards the target by
826 /// the specified distance.
827 ///
828 /// # Examples
829 ///
830 /// ```
831 /// let start = Vec2::new(1.0, 1.0);
832 /// let target = Vec2::new(4.0, 5.0);
833 /// let result = start.move_towards(&target, 2.0);
834 /// // result will be a vector closer to the target by 2.0 units.
835 /// ```
836 pub fn move_towards(&self, target: &Self, max_distance: T) -> Self {
837 let dir = *target - *self;
838 let dist_sq = dir.length_squared();
839 if dist_sq.is_zero() || (max_distance * max_distance >= dist_sq) {
840 return *target;
841 }
842 let dist = dist_sq.sqrt();
843 *self + (dir / dist) * max_distance
844 }
845
846 /// Computes the reciprocal (1/x) of each component of the vector.
847 ///
848 /// This method returns a new vector where each component is the reciprocal
849 /// of the corresponding component of the original vector. This is equivalent
850 /// to element-wise division of 1 by the vector components.
851 ///
852 /// # Returns
853 ///
854 /// A new vector where each component is the reciprocal of the corresponding
855 /// component of the original vector.
856 ///
857 /// # Panics
858 ///
859 /// This method will panic if any component of the vector is zero, as the reciprocal
860 /// of zero is undefined and would result in a division by zero error.
861 ///
862 /// # Examples
863 ///
864 /// ```
865 /// let v = Vec2::new(2.0, 4.0);
866 /// let recip_v = v.recip();
867 /// assert_eq!(recip_v, Vec2::new(0.5, 0.25));
868 /// ```
869 #[inline]
870 pub fn recip(&self) -> Self {
871 Self::new(self.x.recip(), self.y.recip())
872 }
873}
874
875impl<T> fmt::Display for Vec2<T>
876where
877 T: fmt::Display,
878{
879 #[inline]
880 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
881 write!(f, "({}, {})", self.x, self.y)
882 }
883}
884
885impl<T> From<(T, T)> for Vec2<T>
886where
887 T: NumAssign + Copy,
888{
889 #[inline]
890 fn from(tuple: (T, T)) -> Self {
891 Vec2::new(tuple.0, tuple.1)
892 }
893}
894
895impl<T> Into<(T, T)> for Vec2<T>
896where
897 T: NumAssign + Copy,
898{
899 #[inline]
900 fn into(self) -> (T, T) {
901 (self.x, self.y)
902 }
903}
904
905impl<T> Index<usize> for Vec2<T> {
906 type Output = T;
907
908 fn index(&self, index: usize) -> &Self::Output {
909 match index {
910 0 => &self.x,
911 1 => &self.y,
912 _ => panic!("Index out of bounds for Vec2"),
913 }
914 }
915}
916
917impl<T> IndexMut<usize> for Vec2<T> {
918 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
919 match index {
920 0 => &mut self.x,
921 1 => &mut self.y,
922 _ => panic!("Index out of bounds for Vec2"),
923 }
924 }
925}
926
927impl<'a, T> IntoIterator for &'a Vec2<T>
928where
929 T: NumAssign + Copy
930{
931 type Item = &'a T;
932 type IntoIter = Iter<'a, T>;
933
934 #[inline]
935 fn into_iter(self) -> Self::IntoIter {
936 let slice: &[T; 3] = unsafe { std::mem::transmute(self) };
937 slice.iter()
938 }
939}
940
941impl<'a, T> IntoIterator for &'a mut Vec2<T>
942where
943 T: NumAssign + Copy
944{
945 type Item = &'a mut T;
946 type IntoIter = IterMut<'a, T>;
947
948 #[inline]
949 fn into_iter(self) -> Self::IntoIter {
950 let slice: &mut [T; 3] = unsafe { std::mem::transmute(self) };
951 slice.iter_mut()
952 }
953}
954
955impl<T> Neg for Vec2<T>
956where
957 T: NumAssign + Copy + Neg<Output = T>,
958{
959 type Output = Self;
960
961 #[inline]
962 fn neg(self) -> Self::Output {
963 Self::new(-self.x, -self.y)
964 }
965}
966
967impl<T> Add for Vec2<T>
968where
969 T: NumAssign + Copy,
970{
971 type Output = Self;
972
973 #[inline]
974 fn add(self, other: Self) -> Self {
975 Self::new(self.x + other.x, self.y + other.y)
976 }
977}
978
979impl<T> Add<T> for Vec2<T>
980where
981 T: NumAssign + Copy,
982{
983 type Output = Self;
984
985 #[inline]
986 fn add(self, scalar: T) -> Self {
987 Self::new(self.x + scalar, self.y + scalar)
988 }
989}
990
991impl<T> Sub for Vec2<T>
992where
993 T: NumAssign + Copy,
994{
995 type Output = Self;
996
997 #[inline]
998 fn sub(self, other: Self) -> Self {
999 Self::new(self.x - other.x, self.y - other.y)
1000 }
1001}
1002
1003impl<T> Sub<T> for Vec2<T>
1004where
1005 T: NumAssign + Copy,
1006{
1007 type Output = Self;
1008
1009 #[inline]
1010 fn sub(self, scalar: T) -> Self {
1011 Self::new(self.x - scalar, self.y - scalar)
1012 }
1013}
1014
1015impl<T> Mul for Vec2<T>
1016where
1017 T: NumAssign + Copy,
1018{
1019 type Output = Self;
1020
1021 #[inline]
1022 fn mul(self, other: Self) -> Self {
1023 Self::new(self.x * other.x, self.y * other.y)
1024 }
1025}
1026
1027impl<T> Mul<T> for Vec2<T>
1028where
1029 T: NumAssign + Copy,
1030{
1031 type Output = Self;
1032
1033 #[inline]
1034 fn mul(self, scalar: T) -> Self {
1035 Self::new(self.x * scalar, self.y * scalar)
1036 }
1037}
1038
1039impl<T> Div for Vec2<T>
1040where
1041 T: NumAssign + Copy,
1042{
1043 type Output = Self;
1044
1045 #[inline]
1046 fn div(self, other: Self) -> Self {
1047 Self::new(self.x / other.x, self.y / other.y)
1048 }
1049}
1050
1051impl<T> Div<T> for Vec2<T>
1052where
1053 T: NumAssign + Copy,
1054{
1055 type Output = Self;
1056
1057 #[inline]
1058 fn div(self, scalar: T) -> Self {
1059 Self::new(self.x / scalar, self.y / scalar)
1060 }
1061}
1062
1063impl<T> AddAssign for Vec2<T>
1064where
1065 T: NumAssign + Copy,
1066{
1067 #[inline]
1068 fn add_assign(&mut self, other: Self) {
1069 self.x += other.x;
1070 self.y += other.y;
1071 }
1072}
1073
1074impl<T> AddAssign<T> for Vec2<T>
1075where
1076 T: NumAssign + Copy,
1077{
1078 #[inline]
1079 fn add_assign(&mut self, scalar: T) {
1080 self.x += scalar;
1081 self.y += scalar;
1082 }
1083}
1084
1085impl<T> SubAssign for Vec2<T>
1086where
1087 T: NumAssign + Copy,
1088{
1089 #[inline]
1090 fn sub_assign(&mut self, other: Self) {
1091 self.x -= other.x;
1092 self.y -= other.y;
1093 }
1094}
1095
1096impl<T> SubAssign<T> for Vec2<T>
1097where
1098 T: NumAssign + Copy,
1099{
1100 #[inline]
1101 fn sub_assign(&mut self, scalar: T) {
1102 self.x -= scalar;
1103 self.y -= scalar;
1104 }
1105}
1106
1107impl<T> MulAssign for Vec2<T>
1108where
1109 T: NumAssign + Copy,
1110{
1111 #[inline]
1112 fn mul_assign(&mut self, other: Self) {
1113 self.x *= other.x;
1114 self.y *= other.y;
1115 }
1116}
1117
1118impl<T> MulAssign<T> for Vec2<T>
1119where
1120 T: NumAssign + Copy,
1121{
1122 #[inline]
1123 fn mul_assign(&mut self, scalar: T) {
1124 self.x *= scalar;
1125 self.y *= scalar;
1126 }
1127}
1128
1129impl<T> DivAssign for Vec2<T>
1130where
1131 T: NumAssign + Copy,
1132{
1133 #[inline]
1134 fn div_assign(&mut self, other: Self) {
1135 self.x /= other.x;
1136 self.y /= other.y;
1137 }
1138}
1139
1140impl<T> DivAssign<T> for Vec2<T>
1141where
1142 T: NumAssign + Copy,
1143{
1144 #[inline]
1145 fn div_assign(&mut self, scalar: T) {
1146 self.x /= scalar;
1147 self.y /= scalar;
1148 }
1149}
1150
1151#[cfg(test)]
1152mod tests {
1153 use super::*;
1154
1155 #[test]
1156 fn test_new() {
1157 let vec = Vec2::new(3.0, 4.0);
1158 assert_eq!(vec.x, 3.0);
1159 assert_eq!(vec.y, 4.0);
1160 }
1161
1162 #[test]
1163 fn test_zero() {
1164 let vec = Vec2::<f64>::zero();
1165 assert_eq!(vec.x, 0.0);
1166 assert_eq!(vec.y, 0.0);
1167 }
1168
1169 #[test]
1170 fn test_one() {
1171 let vec = Vec2::<f64>::one();
1172 assert_eq!(vec.x, 1.0);
1173 assert_eq!(vec.y, 1.0);
1174 }
1175
1176 #[test]
1177 fn test_negation() {
1178 let vec = Vec2::new(3.0, -4.0);
1179 let neg_vec = -vec;
1180 assert_eq!(neg_vec.x, -3.0);
1181 assert_eq!(neg_vec.y, 4.0);
1182 }
1183
1184 #[test]
1185 fn test_add() {
1186 let vec1 = Vec2::new(1.0, 2.0);
1187 let vec2 = Vec2::new(3.0, 4.0);
1188 let result = vec1 + vec2;
1189 assert_eq!(result, Vec2::new(4.0, 6.0));
1190 }
1191
1192 #[test]
1193 fn test_subtract() {
1194 let vec1 = Vec2::new(5.0, 7.0);
1195 let vec2 = Vec2::new(2.0, 3.0);
1196 let result = vec1 - vec2;
1197 assert_eq!(result, Vec2::new(3.0, 4.0));
1198 }
1199
1200 #[test]
1201 fn test_multiply() {
1202 let vec = Vec2::new(2.0, 3.0);
1203 let scalar = 2.0;
1204 let result = vec * scalar;
1205 assert_eq!(result, Vec2::new(4.0, 6.0));
1206 }
1207
1208 #[test]
1209 fn test_divide() {
1210 let vec = Vec2::new(8.0, 6.0);
1211 let scalar = 2.0;
1212 let result = vec / scalar;
1213 assert_eq!(result, Vec2::new(4.0, 3.0));
1214 }
1215
1216 #[test]
1217 fn test_length() {
1218 let vec = Vec2::new(3.0, 4.0);
1219 let length = vec.length();
1220 assert_eq!(length, 5.0);
1221 }
1222
1223 #[test]
1224 fn test_normalize() {
1225 let vec = Vec2::new(3.0, 4.0);
1226 let normalized_vec = vec.normalize().unwrap();
1227 assert_eq!(normalized_vec.x, 3.0 / 5.0);
1228 assert_eq!(normalized_vec.y, 4.0 / 5.0);
1229 }
1230
1231 #[test]
1232 fn test_dot_product() {
1233 let vec1 = Vec2::new(1.0, 2.0);
1234 let vec2 = Vec2::new(3.0, 4.0);
1235 let dot_product = vec1.dot(&vec2);
1236 assert_eq!(dot_product, 11.0);
1237 }
1238
1239 #[test]
1240 fn test_distance() {
1241 let vec1 = Vec2::new(1.0, 1.0);
1242 let vec2 = Vec2::new(4.0, 5.0);
1243 let distance = vec1.distance(&vec2);
1244 assert_eq!(distance, 5.0);
1245 }
1246
1247 #[test]
1248 fn test_distance_squared() {
1249 let vec1 = Vec2::new(1.0, 1.0);
1250 let vec2 = Vec2::new(4.0, 5.0);
1251 let distance_squared = vec1.distance_squared(&vec2);
1252 assert_eq!(distance_squared, 25.0);
1253 }
1254
1255 #[test]
1256 fn test_lerp() {
1257 let vec1 = Vec2::new(0.0, 0.0);
1258 let vec2 = Vec2::new(10.0, 10.0);
1259 let result = vec1.lerp(&vec2, 0.5);
1260 assert_eq!(result, Vec2::new(5.0, 5.0));
1261 }
1262}