Skip to main content

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}