Skip to main content

primitives/foundation/
vector2d.rs

1use core::cmp::{Eq, PartialEq};
2use core::fmt;
3use core::hash::Hash;
4// use core::iter::Sum;
5use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
6
7
8use num_traits::{Float, NumCast, Signed};
9
10/// A 2d Vector tagged with a unit.
11#[repr(C)]
12pub struct Vector2D<T> {
13    /// The `x` (traditionally, horizontal) coordinate.
14    pub x: T,
15    /// The `y` (traditionally, vertical) coordinate.
16    pub y: T,
17}
18
19// mint_vec!(Vector2D[x, y] = Vector2);
20
21impl<T: Copy> Copy for Vector2D<T> {}
22
23impl<T: Clone> Clone for Vector2D<T> {
24    fn clone(&self) -> Self {
25        Vector2D {
26            x: self.x.clone(),
27            y: self.y.clone(),
28        }
29    }
30}
31
32#[cfg(feature = "serde")]
33impl<'de, T> serde::Deserialize<'de> for Vector2D<T>
34where
35    T: serde::Deserialize<'de>,
36{
37    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
38    where
39        D: serde::Deserializer<'de>,
40    {
41        let (x, y) = serde::Deserialize::deserialize(deserializer)?;
42        Ok(Vector2D {
43            x,
44            y,
45        })
46    }
47}
48
49#[cfg(feature = "serde")]
50impl<T> serde::Serialize for Vector2D<T>
51where
52    T: serde::Serialize,
53{
54    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55    where
56        S: serde::Serializer,
57    {
58        (&self.x, &self.y).serialize(serializer)
59    }
60}
61
62#[cfg(feature = "arbitrary")]
63impl<'a, T> arbitrary::Arbitrary<'a> for Vector2D<T>
64where
65    T: arbitrary::Arbitrary<'a>,
66{
67    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
68    {
69        let (x, y) = arbitrary::Arbitrary::arbitrary(u)?;
70        Ok(Vector2D {
71            x,
72            y,
73        })
74    }
75}
76
77impl<T: Eq> Eq for Vector2D<T> {}
78
79impl<T: PartialEq> PartialEq for Vector2D<T> {
80    fn eq(&self, other: &Self) -> bool {
81        self.x == other.x && self.y == other.y
82    }
83}
84
85impl<T: Hash> Hash for Vector2D<T> {
86    fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
87        self.x.hash(h);
88        self.y.hash(h);
89    }
90}
91
92// impl<T: Zero> Zero for Vector2D<T> {
93//     /// Constructor, setting all components to zero.
94//     #[inline]
95//     fn zero() -> Self {
96//         Vector2D::new(Zero::zero(), Zero::zero())
97//     }
98// }
99
100impl<T: fmt::Debug> fmt::Debug for Vector2D<T> {
101    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102        f.debug_tuple("").field(&self.x).field(&self.y).finish()
103    }
104}
105
106impl<T: Default> Default for Vector2D<T> {
107    fn default() -> Self {
108        Vector2D::new(Default::default(), Default::default())
109    }
110}
111
112impl<T> Vector2D<T> {
113    // /// Constructor, setting all components to zero.
114    // #[inline]
115    // pub fn zero() -> Self
116    // where
117    //     T: Zero,
118    // {
119    //     Vector2D::new(Zero::zero(), Zero::zero())
120    // }
121
122    // /// Constructor, setting all components to one.
123    // #[inline]
124    // pub fn one() -> Self
125    // where
126    //     T: One,
127    // {
128    //     Vector2D::new(One::one(), One::one())
129    // }
130
131    /// Constructor taking scalar values directly.
132    #[inline]
133    pub const fn new(x: T, y: T) -> Self {
134        Vector2D {
135            x,
136            y,
137        }
138    }
139
140    /// Constructor setting all components to the same value.
141    #[inline]
142    pub fn splat(v: T) -> Self
143    where
144        T: Clone,
145    {
146        Vector2D {
147            x: v.clone(),
148            y: v,
149        }
150    }
151
152    // /// Constructor taking angle and length
153    // pub fn from_angle_and_length(angle: Angle<T>, length: T) -> Self
154    // where
155    //     T: Trig + Mul<Output = T> + Copy,
156    // {
157    //     Vector2D::new(length * angle.radians.cos(), length * angle.radians.sin())
158    // }
159
160    // /// Constructor taking properly  Lengths instead of scalar values.
161    // #[inline]
162    // pub fn from_lengths(x: Length<T>, y: Length<T>) -> Self {
163    //     Vector2D::new(x.0, y.0)
164    // }
165
166    // /// Tag a unit-less value with units.
167    // #[inline]
168    // pub fn from_untyped(p: Vector2D<T>) -> Self {
169    //     Vector2D::new(p.x, p.y)
170    // }
171
172    /// Computes the vector with absolute values of each component.
173    ///
174    /// # Example
175    ///
176    /// ```rust
177    /// # use std::{i32, f32};
178    /// # use primitives::foundation::Vector2D;
179    /// enum U {}
180    ///
181    /// assert_eq!(Vector2D::new(-1, 2).abs(), Vector2D::new(1, 2));
182    ///
183    /// let vec = Vector2D::new(f32::NAN, -f32::MAX).abs();
184    /// assert!(vec.x.is_nan());
185    /// assert_eq!(vec.y, f32::MAX);
186    /// ```
187    ///
188    /// # Panics
189    ///
190    /// The behavior for each component follows the scalar type's implementation of
191    /// `num_traits::Signed::abs`.
192    pub fn abs(self) -> Self
193    where
194        T: Signed,
195    {
196        Vector2D::new(self.x.abs(), self.y.abs())
197    }
198
199    /// Dot product.
200    #[inline]
201    pub fn dot(self, other: Self) -> T
202    where
203        T: Add<Output = T> + Mul<Output = T>,
204    {
205        self.x * other.x + self.y * other.y
206    }
207
208    /// Returns the norm of the cross product [self.x, self.y, 0] x [other.x, other.y, 0].
209    #[inline]
210    pub fn cross(self, other: Self) -> T
211    where
212        T: Sub<Output = T> + Mul<Output = T>,
213    {
214        self.x * other.y - self.y * other.x
215    }
216
217    /// Returns the component-wise multiplication of the two vectors.
218    #[inline]
219    pub fn component_mul(self, other: Self) -> Self
220    where
221        T: Mul<Output = T>,
222    {
223        Vector2D::new(self.x * other.x, self.y * other.y)
224    }
225
226    /// Returns the component-wise division of the two vectors.
227    #[inline]
228    pub fn component_div(self, other: Self) -> Self
229    where
230        T: Div<Output = T>,
231    {
232        Vector2D::new(self.x / other.x, self.y / other.y)
233    }
234}
235
236impl<T: Copy> Vector2D<T> {
237    // /// Create a 3d vector from this one, using the specified z value.
238    // #[inline]
239    // pub fn extend(self, z: T) -> Vector3D<T> {
240    //     vec3(self.x, self.y, z)
241    // }
242
243    // /// Cast this vector into a point.
244    // ///
245    // /// Equivalent to adding this vector to the origin.
246    // #[inline]
247    // pub fn to_point(self) -> Point2D<T> {
248    //     Point2D {
249    //         x: self.x,
250    //         y: self.y,
251    //     }
252    // }
253
254    /// Swap x and y.
255    #[inline]
256    pub fn yx(self) -> Self {
257        Vector2D::new(self.y, self.x)
258    }
259
260    // /// Cast this vector into a size.
261    // #[inline]
262    // pub fn to_size(self) -> Size2D<T> {
263    //     size2(self.x, self.y)
264    // }
265
266    /// Drop the units, preserving only the numeric value.
267    #[inline]
268    pub fn to_untyped(self) -> Vector2D<T> {
269        Vector2D::new(self.x, self.y)
270    }
271
272    // /// Cast the unit.
273    // #[inline]
274    // pub fn cast_unit<V>(self) -> Vector2D<T, V> {
275    //     Vector2D::new(self.x, self.y)
276    // }
277
278    /// Cast into an array with x and y.
279    #[inline]
280    pub fn to_array(self) -> [T; 2] {
281        [self.x, self.y]
282    }
283
284    /// Cast into a tuple with x and y.
285    #[inline]
286    pub fn to_tuple(self) -> (T, T) {
287        (self.x, self.y)
288    }
289
290    // /// Convert into a 3d vector with `z` coordinate equals to `T::zero()`.
291    // #[inline]
292    // pub fn to_3d(self) -> Vector3D<T>
293    // where
294    //     T: Zero,
295    // {
296    //     vec3(self.x, self.y, Zero::zero())
297    // }
298
299    // /// Rounds each component to the nearest integer value.
300    // ///
301    // /// This behavior is preserved for negative values (unlike the basic cast).
302    // ///
303    // /// ```rust
304    // /// # use euclid::vec2;
305    // /// enum Mm {}
306    // ///
307    // /// assert_eq!(vec2::<_, Mm>(-0.1, -0.8).round(), vec2::<_, Mm>(0.0, -1.0))
308    // /// ```
309    // #[inline]
310    // #[must_use]
311    // pub fn round(self) -> Self
312    // where
313    //     T: Round,
314    // {
315    //     Vector2D::new(self.x.round(), self.y.round())
316    // }
317
318    // /// Rounds each component to the smallest integer equal or greater than the original value.
319    // ///
320    // /// This behavior is preserved for negative values (unlike the basic cast).
321    // ///
322    // /// ```rust
323    // /// # use euclid::vec2;
324    // /// enum Mm {}
325    // ///
326    // /// assert_eq!(vec2::<_, Mm>(-0.1, -0.8).ceil(), vec2::<_, Mm>(0.0, 0.0))
327    // /// ```
328    // #[inline]
329    // #[must_use]
330    // pub fn ceil(self) -> Self
331    // where
332    //     T: Ceil,
333    // {
334    //     Vector2D::new(self.x.ceil(), self.y.ceil())
335    // }
336
337    // /// Rounds each component to the biggest integer equal or lower than the original value.
338    // ///
339    // /// This behavior is preserved for negative values (unlike the basic cast).
340    // ///
341    // /// ```rust
342    // /// # use euclid::vec2;
343    // /// enum Mm {}
344    // ///
345    // /// assert_eq!(vec2::<_, Mm>(-0.1, -0.8).floor(), vec2::<_, Mm>(-1.0, -1.0))
346    // /// ```
347    // #[inline]
348    // #[must_use]
349    // pub fn floor(self) -> Self
350    // where
351    //     T: Floor,
352    // {
353    //     Vector2D::new(self.x.floor(), self.y.floor())
354    // }
355
356    // /// Returns the signed angle between this vector and the x axis.
357    // /// Positive values counted counterclockwise, where 0 is `+x` axis, `PI/2`
358    // /// is `+y` axis.
359    // ///
360    // /// The returned angle is between -PI and PI.
361    // pub fn angle_from_x_axis(self) -> Angle<T>
362    // where
363    //     T: Trig,
364    // {
365    //     Angle::radians(Trig::fast_atan2(self.y, self.x))
366    // }
367
368    // /// Creates translation by this vector in vector units.
369    // #[inline]
370    // pub fn to_transform(self) -> Transform2D<T>
371    // where
372    //     T: Zero + One,
373    // {
374    //     Transform2D::translation(self.x, self.y)
375    // }
376}
377
378impl<T> Vector2D<T>
379where
380    T: Copy + Mul<T, Output = T> + Add<T, Output = T>,
381{
382    /// Returns the vector's length squared.
383    #[inline]
384    pub fn square_length(self) -> T {
385        self.x * self.x + self.y * self.y
386    }
387
388    /// Returns this vector projected onto another one.
389    ///
390    /// Projecting onto a nil vector will cause a division by zero.
391    #[inline]
392    pub fn project_onto_vector(self, onto: Self) -> Self
393    where
394        T: Sub<T, Output = T> + Div<T, Output = T>,
395    {
396        onto * (self.dot(onto) / onto.square_length())
397    }
398
399    // /// Returns the signed angle between this vector and another vector.
400    // ///
401    // /// The returned angle is between -PI and PI.
402    // pub fn angle_to(self, other: Self) -> Angle<T>
403    // where
404    //     T: Sub<Output = T> + Trig,
405    // {
406    //     Angle::radians(Trig::fast_atan2(self.cross(other), self.dot(other)))
407    // }
408}
409
410impl<T: Float> Vector2D<T> {
411    /// Returns the vector length.
412    #[inline]
413    pub fn length(self) -> T {
414        self.square_length().sqrt()
415    }
416
417    /// Returns the vector with length of one unit.
418    #[inline]
419    #[must_use]
420    pub fn normalize(self) -> Self {
421        self / self.length()
422    }
423
424    /// Returns the vector with length of one unit.
425    ///
426    /// Unlike [`Vector2D::normalize`](#method.normalize), this returns None in the case that the
427    /// length of the vector is zero.
428    #[inline]
429    #[must_use]
430    pub fn try_normalize(self) -> Option<Self> {
431        let len = self.length();
432        if len == T::zero() {
433            None
434        } else {
435            Some(self / len)
436        }
437    }
438
439    /// Return the normalized vector even if the length is larger than the max value of Float.
440    #[inline]
441    #[must_use]
442    pub fn robust_normalize(self) -> Self {
443        let length = self.length();
444        if length.is_infinite() {
445            let scaled = self / T::max_value();
446            scaled / scaled.length()
447        } else {
448            self / length
449        }
450    }
451
452    /// Return this vector capped to a maximum length.
453    #[inline]
454    pub fn with_max_length(self, max_length: T) -> Self {
455        let square_length = self.square_length();
456        if square_length > max_length * max_length {
457            return self * (max_length / square_length.sqrt());
458        }
459
460        self
461    }
462
463    /// Return this vector with a minimum length applied.
464    #[inline]
465    pub fn with_min_length(self, min_length: T) -> Self {
466        let square_length = self.square_length();
467        if square_length < min_length * min_length {
468            return self * (min_length / square_length.sqrt());
469        }
470
471        self
472    }
473
474    /// Return this vector with minimum and maximum lengths applied.
475    #[inline]
476    pub fn clamp_length(self, min: T, max: T) -> Self {
477        debug_assert!(min <= max);
478        self.with_min_length(min).with_max_length(max)
479    }
480
481    /// Returns true if all members are finite.
482    #[inline]
483    pub fn is_finite(self) -> bool {
484        self.x.is_finite() && self.y.is_finite()
485    }
486}
487
488// impl<T> Vector2D<T>
489// where
490//     T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
491// {
492//     /// Linearly interpolate each component between this vector and another vector.
493//     ///
494//     /// # Example
495//     ///
496//     /// ```rust
497//     /// use euclid::vec2;
498//     /// use euclid::default::Vector2D;
499//     ///
500//     /// let from: Vector2D<_> = Vector2D::new(0.0, 10.0);
501//     /// let to:  Vector2D<_> = Vector2D::new(8.0, -4.0);
502//     ///
503//     /// assert_eq!(from.lerp(to, -1.0), Vector2D::new(-8.0,  24.0));
504//     /// assert_eq!(from.lerp(to,  0.0), Vector2D::new( 0.0,  10.0));
505//     /// assert_eq!(from.lerp(to,  0.5), Vector2D::new( 4.0,   3.0));
506//     /// assert_eq!(from.lerp(to,  1.0), Vector2D::new( 8.0,  -4.0));
507//     /// assert_eq!(from.lerp(to,  2.0), Vector2D::new(16.0, -18.0));
508//     /// ```
509//     #[inline]
510//     pub fn lerp(self, other: Self, t: T) -> Self {
511//         let one_t = T::one() - t;
512//         self * one_t + other * t
513//     }
514
515//     /// Returns a reflection vector using an incident ray and a surface normal.
516//     #[inline]
517//     pub fn reflect(self, normal: Self) -> Self {
518//         let two = T::one() + T::one();
519//         self - normal * two * self.dot(normal)
520//     }
521// }
522
523// impl<T: PartialOrd> Vector2D<T> {
524//     /// Returns the vector each component of which are minimum of this vector and another.
525//     #[inline]
526//     pub fn min(self, other: Self) -> Self {
527//         Vector2D::new(min(self.x, other.x), min(self.y, other.y))
528//     }
529
530//     /// Returns the vector each component of which are maximum of this vector and another.
531//     #[inline]
532//     pub fn max(self, other: Self) -> Self {
533//         Vector2D::new(max(self.x, other.x), max(self.y, other.y))
534//     }
535
536//     /// Returns the vector each component of which is clamped by corresponding
537//     /// components of `start` and `end`.
538//     ///
539//     /// Shortcut for `self.max(start).min(end)`.
540//     #[inline]
541//     pub fn clamp(self, start: Self, end: Self) -> Self
542//     where
543//         T: Copy,
544//     {
545//         self.max(start).min(end)
546//     }
547
548//     /// Returns vector with results of "greater than" operation on each component.
549//     #[inline]
550//     pub fn greater_than(self, other: Self) -> BoolVector2D {
551//         BoolVector2D {
552//             x: self.x > other.x,
553//             y: self.y > other.y,
554//         }
555//     }
556
557//     /// Returns vector with results of "lower than" operation on each component.
558//     #[inline]
559//     pub fn lower_than(self, other: Self) -> BoolVector2D {
560//         BoolVector2D {
561//             x: self.x < other.x,
562//             y: self.y < other.y,
563//         }
564//     }
565// }
566
567// impl<T: PartialEq> Vector2D<T> {
568//     /// Returns vector with results of "equal" operation on each component.
569//     #[inline]
570//     pub fn equal(self, other: Self) -> BoolVector2D {
571//         BoolVector2D {
572//             x: self.x == other.x,
573//             y: self.y == other.y,
574//         }
575//     }
576
577//     /// Returns vector with results of "not equal" operation on each component.
578//     #[inline]
579//     pub fn not_equal(self, other: Self) -> BoolVector2D {
580//         BoolVector2D {
581//             x: self.x != other.x,
582//             y: self.y != other.y,
583//         }
584//     }
585// }
586
587impl<T: NumCast + Copy> Vector2D<T> {
588    /// Cast from one numeric representation to another, preserving the units.
589    ///
590    /// When casting from floating vector to integer coordinates, the decimals are truncated
591    /// as one would expect from a simple cast, but this behavior does not always make sense
592    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
593    #[inline]
594    pub fn cast<NewT: NumCast>(self) -> Vector2D<NewT> {
595        self.try_cast().unwrap()
596    }
597
598    /// Fallible cast from one numeric representation to another, preserving the units.
599    ///
600    /// When casting from floating vector to integer coordinates, the decimals are truncated
601    /// as one would expect from a simple cast, but this behavior does not always make sense
602    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
603    pub fn try_cast<NewT: NumCast>(self) -> Option<Vector2D<NewT>> {
604        match (NumCast::from(self.x), NumCast::from(self.y)) {
605            (Some(x), Some(y)) => Some(Vector2D::new(x, y)),
606            _ => None,
607        }
608    }
609
610    // Convenience functions for common casts.
611
612    /// Cast into an `f32` vector.
613    #[inline]
614    pub fn to_f32(self) -> Vector2D<f32> {
615        self.cast()
616    }
617
618    /// Cast into an `f64` vector.
619    #[inline]
620    pub fn to_f64(self) -> Vector2D<f64> {
621        self.cast()
622    }
623
624    /// Cast into an `usize` vector, truncating decimals if any.
625    ///
626    /// When casting from floating vector vectors, it is worth considering whether
627    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
628    /// the desired conversion behavior.
629    #[inline]
630    pub fn to_usize(self) -> Vector2D<usize> {
631        self.cast()
632    }
633
634    /// Cast into an `u32` vector, truncating decimals if any.
635    ///
636    /// When casting from floating vector vectors, it is worth considering whether
637    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
638    /// the desired conversion behavior.
639    #[inline]
640    pub fn to_u32(self) -> Vector2D<u32> {
641        self.cast()
642    }
643
644    /// Cast into an i32 vector, truncating decimals if any.
645    ///
646    /// When casting from floating vector vectors, it is worth considering whether
647    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
648    /// the desired conversion behavior.
649    #[inline]
650    pub fn to_i32(self) -> Vector2D<i32> {
651        self.cast()
652    }
653
654    /// Cast into an i64 vector, truncating decimals if any.
655    ///
656    /// When casting from floating vector vectors, it is worth considering whether
657    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
658    /// the desired conversion behavior.
659    #[inline]
660    pub fn to_i64(self) -> Vector2D<i64> {
661        self.cast()
662    }
663}
664
665impl<T: Neg> Neg for Vector2D<T> {
666    type Output = Vector2D<T::Output>;
667
668    #[inline]
669    fn neg(self) -> Self::Output {
670        Vector2D::new(-self.x, -self.y)
671    }
672}
673
674impl<T: Add> Add for Vector2D<T> {
675    type Output = Vector2D<T::Output>;
676
677    #[inline]
678    fn add(self, other: Self) -> Self::Output {
679        Vector2D::new(self.x + other.x, self.y + other.y)
680    }
681}
682
683impl<T: Add + Copy> Add<&Self> for Vector2D<T> {
684    type Output = Vector2D<T::Output>;
685
686    #[inline]
687    fn add(self, other: &Self) -> Self::Output {
688        Vector2D::new(self.x + other.x, self.y + other.y)
689    }
690}
691
692// impl<T: Add<Output = T> + Zero> Sum for Vector2D<T> {
693//     fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
694//         iter.fold(Self::zero(), Add::add)
695//     }
696// }
697
698// impl<'a, T: 'a + Add<Output = T> + Copy + Zero: 'a> Sum<&'a Self> for Vector2D<T> {
699//     fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
700//         iter.fold(Self::zero(), Add::add)
701//     }
702// }
703
704impl<T: Copy + Add<T, Output = T>> AddAssign for Vector2D<T> {
705    #[inline]
706    fn add_assign(&mut self, other: Self) {
707        *self = *self + other
708    }
709}
710
711impl<T: Sub> Sub for Vector2D<T> {
712    type Output = Vector2D<T::Output>;
713
714    #[inline]
715    fn sub(self, other: Self) -> Self::Output {
716        Vector2D::new(self.x - other.x, self.y - other.y)
717    }
718}
719
720impl<T: Copy + Sub<T, Output = T>> SubAssign<Vector2D<T>> for Vector2D<T> {
721    #[inline]
722    fn sub_assign(&mut self, other: Self) {
723        *self = *self - other
724    }
725}
726
727impl<T: Copy + Mul> Mul<T> for Vector2D<T> {
728    type Output = Vector2D<T::Output>;
729
730    #[inline]
731    fn mul(self, scale: T) -> Self::Output {
732        Vector2D::new(self.x * scale, self.y * scale)
733    }
734}
735
736impl<T: Copy + Mul<T, Output = T>> MulAssign<T> for Vector2D<T> {
737    #[inline]
738    fn mul_assign(&mut self, scale: T) {
739        *self = *self * scale
740    }
741}
742
743// impl<T: Copy + Mul> Mul<Scale<T>> for Vector2D<T> {
744//     type Output = Vector2D<T::Output>;
745
746//     #[inline]
747//     fn mul(self, scale: Scale<T>) -> Self::Output {
748//         Vector2D::new(self.x * scale.0, self.y * scale.0)
749//     }
750// }
751
752// impl<T: Copy + MulAssign> MulAssign<Scale<T>> for Vector2D<T> {
753//     #[inline]
754//     fn mul_assign(&mut self, scale: Scale<T>) {
755//         self.x *= scale.0;
756//         self.y *= scale.0;
757//     }
758// }
759
760impl<T: Copy + Div> Div<T> for Vector2D<T> {
761    type Output = Vector2D<T::Output>;
762
763    #[inline]
764    fn div(self, scale: T) -> Self::Output {
765        Vector2D::new(self.x / scale, self.y / scale)
766    }
767}
768
769impl<T: Copy + Div<T, Output = T>> DivAssign<T> for Vector2D<T> {
770    #[inline]
771    fn div_assign(&mut self, scale: T) {
772        *self = *self / scale
773    }
774}
775
776// impl<T: Copy + Div> Div<Scale<T>> for Vector2D<T> {
777//     type Output = Vector2D<T::Output>;
778
779//     #[inline]
780//     fn div(self, scale: Scale<T>) -> Self::Output {
781//         Vector2D::new(self.x / scale.0, self.y / scale.0)
782//     }
783// }
784
785// impl<T: Copy + DivAssign> DivAssign<Scale<T>> for Vector2D<T> {
786//     #[inline]
787//     fn div_assign(&mut self, scale: Scale<T>) {
788//         self.x /= scale.0;
789//         self.y /= scale.0;
790//     }
791// }
792
793// impl<T: Round> Round for Vector2D<T> {
794//     /// See [`Vector2D::round()`](#method.round)
795//     #[inline]
796//     fn round(self) -> Self {
797//         self.round()
798//     }
799// }
800
801// impl<T: Ceil> Ceil for Vector2D<T> {
802//     /// See [`Vector2D::ceil()`](#method.ceil)
803//     #[inline]
804//     fn ceil(self) -> Self {
805//         self.ceil()
806//     }
807// }
808
809// impl<T: Floor> Floor for Vector2D<T> {
810//     /// See [`Vector2D::floor()`](#method.floor)
811//     #[inline]
812//     fn floor(self) -> Self {
813//         self.floor()
814//     }
815// }
816
817// impl<T: ApproxEq<T>> ApproxEq<Vector2D<T>> for Vector2D<T> {
818//     #[inline]
819//     fn approx_epsilon() -> Self {
820//         Vector2D::new(T::approx_epsilon(), T::approx_epsilon())
821//     }
822
823//     #[inline]
824//     fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
825//         self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
826//     }
827// }
828
829impl<T> Into<[T; 2]> for Vector2D<T> {
830    fn into(self) -> [T; 2] {
831        [self.x, self.y]
832    }
833}
834
835impl<T> From<[T; 2]> for Vector2D<T> {
836    fn from([x, y]: [T; 2]) -> Self {
837        Vector2D::new(x, y)
838    }
839}
840
841impl<T> Into<(T, T)> for Vector2D<T> {
842    fn into(self) -> (T, T) {
843        (self.x, self.y)
844    }
845}
846
847impl<T> From<(T, T)> for Vector2D<T> {
848    fn from(tuple: (T, T)) -> Self {
849        Vector2D::new(tuple.0, tuple.1)
850    }
851}
852
853// impl<T> From<Size2D<T>> for Vector2D<T> {
854//     fn from(size: Size2D<T>) -> Self {
855//         Vector2D::new(size.width, size.height)
856//     }
857// }
858
859#[cfg(test)]
860mod vector2d {
861    use crate::foundation::Vector2D;
862    // use crate::scale::Scale;
863    // use crate::{default};
864
865    #[cfg(feature = "mint")]
866    use mint;
867
868    type Vec2 = Vector2D<f32>;
869
870    #[test]
871    pub fn test_scalar_mul() {
872        let p1: Vec2 = Vector2D::new(3.0, 5.0);
873
874        let result = p1 * 5.0;
875
876        assert_eq!(result, Vec2::new(15.0, 25.0));
877    }
878
879    #[test]
880    pub fn test_dot() {
881        let p1: Vec2 = Vector2D::new(2.0, 7.0);
882        let p2: Vec2 = Vector2D::new(13.0, 11.0);
883        assert_eq!(p1.dot(p2), 103.0);
884    }
885
886    #[test]
887    pub fn test_cross() {
888        let p1: Vec2 = Vector2D::new(4.0, 7.0);
889        let p2: Vec2 = Vector2D::new(13.0, 8.0);
890        let r = p1.cross(p2);
891        assert_eq!(r, -59.0);
892    }
893
894    // #[test]
895    // pub fn test_normalize() {
896    //     use std::f32;
897
898    //     let p0: Vec2 = Vec2::zero();
899    //     let p1: Vec2 = Vector2D::new(4.0, 0.0);
900    //     let p2: Vec2 = Vector2D::new(3.0, -4.0);
901    //     assert!(p0.normalize().x.is_nan() && p0.normalize().y.is_nan());
902    //     assert_eq!(p1.normalize(), Vector2D::new(1.0, 0.0));
903    //     assert_eq!(p2.normalize(), Vector2D::new(0.6, -0.8));
904
905    //     let p3: Vec2 = Vector2D::new(::std::f32::MAX, ::std::f32::MAX);
906    //     assert_ne!(
907    //         p3.normalize(),
908    //         Vector2D::new(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt())
909    //     );
910    //     assert_eq!(
911    //         p3.robust_normalize(),
912    //         Vector2D::new(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt())
913    //     );
914
915    //     let p4: Vec2 = Vec2::zero();
916    //     assert!(p4.try_normalize().is_none());
917    //     let p5: Vec2 = Vec2::new(f32::MIN_POSITIVE, f32::MIN_POSITIVE);
918    //     assert!(p5.try_normalize().is_none());
919
920    //     let p6: Vec2 = Vector2D::new(4.0, 0.0);
921    //     let p7: Vec2 = Vector2D::new(3.0, -4.0);
922    //     assert_eq!(p6.try_normalize().unwrap(), Vector2D::new(1.0, 0.0));
923    //     assert_eq!(p7.try_normalize().unwrap(), Vector2D::new(0.6, -0.8));
924    // }
925
926    // #[test]
927    // pub fn test_min() {
928    //     let p1: Vec2 = Vector2D::new(1.0, 3.0);
929    //     let p2: Vec2 = Vector2D::new(2.0, 2.0);
930
931    //     let result = p1.min(p2);
932
933    //     assert_eq!(result, Vector2D::new(1.0, 2.0));
934    // }
935
936    // #[test]
937    // pub fn test_max() {
938    //     let p1: Vec2 = Vector2D::new(1.0, 3.0);
939    //     let p2: Vec2 = Vector2D::new(2.0, 2.0);
940
941    //     let result = p1.max(p2);
942
943    //     assert_eq!(result, Vector2D::new(2.0, 3.0));
944    // }
945
946    // #[test]
947    // pub fn test_angle_from_x_axis() {
948    //     // use crate::approxeq::ApproxEq;
949    //     use core::f32::consts::FRAC_PI_2;
950
951    //     let right: Vec2 = Vector2D::new(10.0, 0.0);
952    //     let down: Vec2 = Vector2D::new(0.0, 4.0);
953    //     let up: Vec2 = Vector2D::new(0.0, -1.0);
954
955    //     assert!(right.angle_from_x_axis().get().approx_eq(&0.0));
956    //     assert!(down.angle_from_x_axis().get().approx_eq(&FRAC_PI_2));
957    //     assert!(up.angle_from_x_axis().get().approx_eq(&-FRAC_PI_2));
958    // }
959
960    // #[test]
961    // pub fn test_angle_to() {
962    //     // use crate::approxeq::ApproxEq;
963    //     use core::f32::consts::FRAC_PI_2;
964
965    //     let right: Vec2 = Vector2D::new(10.0, 0.0);
966    //     let right2: Vec2 = Vector2D::new(1.0, 0.0);
967    //     let up: Vec2 = Vector2D::new(0.0, -1.0);
968    //     let up_left: Vec2 = Vector2D::new(-1.0, -1.0);
969
970    //     assert!(right.angle_to(right2).get().approx_eq(&0.0));
971    //     assert!(right.angle_to(up).get().approx_eq(&-FRAC_PI_2));
972    //     assert!(up.angle_to(right).get().approx_eq(&FRAC_PI_2));
973    //     assert!(up_left
974    //         .angle_to(up)
975    //         .get()
976    //         .approx_eq_eps(&(0.5 * FRAC_PI_2), &0.0005));
977    // }
978
979    // #[test]
980    // pub fn test_with_max_length() {
981    //     // use crate::approxeq::ApproxEq;
982
983    //     let v1: Vec2 = Vector2D::new(0.5, 0.5);
984    //     let v2: Vec2 = Vector2D::new(1.0, 0.0);
985    //     let v3: Vec2 = Vector2D::new(0.1, 0.2);
986    //     let v4: Vec2 = Vector2D::new(2.0, -2.0);
987    //     let v5: Vec2 = Vector2D::new(1.0, 2.0);
988    //     let v6: Vec2 = Vector2D::new(-1.0, 3.0);
989
990    //     assert_eq!(v1.with_max_length(1.0), v1);
991    //     assert_eq!(v2.with_max_length(1.0), v2);
992    //     assert_eq!(v3.with_max_length(1.0), v3);
993    //     assert_eq!(v4.with_max_length(10.0), v4);
994    //     assert_eq!(v5.with_max_length(10.0), v5);
995    //     assert_eq!(v6.with_max_length(10.0), v6);
996
997    //     let v4_clamped = v4.with_max_length(1.0);
998    //     assert!(v4_clamped.length().approx_eq(&1.0));
999    //     assert!(v4_clamped.normalize().approx_eq(&v4.normalize()));
1000
1001    //     let v5_clamped = v5.with_max_length(1.5);
1002    //     assert!(v5_clamped.length().approx_eq(&1.5));
1003    //     assert!(v5_clamped.normalize().approx_eq(&v5.normalize()));
1004
1005    //     let v6_clamped = v6.with_max_length(2.5);
1006    //     assert!(v6_clamped.length().approx_eq(&2.5));
1007    //     assert!(v6_clamped.normalize().approx_eq(&v6.normalize()));
1008    // }
1009
1010    // #[test]
1011    // pub fn test_project_onto_vector() {
1012    //     // use crate::approxeq::ApproxEq;
1013
1014    //     let v1: Vec2 = Vector2D::new(1.0, 2.0);
1015    //     let x: Vec2 = Vector2D::new(1.0, 0.0);
1016    //     let y: Vec2 = Vector2D::new(0.0, 1.0);
1017
1018    //     assert!(v1.project_onto_vector(x).approx_eq(&Vector2D::new(1.0, 0.0)));
1019    //     assert!(v1.project_onto_vector(y).approx_eq(&Vector2D::new(0.0, 2.0)));
1020    //     assert!(v1.project_onto_vector(-x).approx_eq(&Vector2D::new(1.0, 0.0)));
1021    //     assert!(v1.project_onto_vector(x * 10.0).approx_eq(&Vector2D::new(1.0, 0.0)));
1022    //     assert!(v1.project_onto_vector(v1 * 2.0).approx_eq(&v1));
1023    //     assert!(v1.project_onto_vector(-v1).approx_eq(&v1));
1024    // }
1025
1026    #[cfg(feature = "mint")]
1027    #[test]
1028    pub fn test_mint() {
1029        let v1 = Vec2::new(1.0, 3.0);
1030        let vm: mint::Vector2<_> = v1.into();
1031        let v2 = Vec2::from(vm);
1032
1033        assert_eq!(v1, v2);
1034    }
1035
1036    // pub enum Mm {}
1037    // pub enum Cm {}
1038
1039    // pub type Vector2DMm<T> = super::Vector2D<T, Mm>;
1040    // pub type Vector2DCm<T> = super::Vector2D<T, Cm>;
1041
1042    // #[test]
1043    // pub fn test_add() {
1044    //     let p1 = Vector2DMm::new(1.0, 2.0);
1045    //     let p2 = Vector2DMm::new(3.0, 4.0);
1046
1047    //     assert_eq!(p1 + p2, Vector2D::new(4.0, 6.0));
1048    //     assert_eq!(p1 + &p2, Vector2D::new(4.0, 6.0));
1049    // }
1050
1051    // #[test]
1052    // pub fn test_sum() {
1053    //     let vecs = [
1054    //         Vector2DMm::new(1.0, 2.0),
1055    //         Vector2DMm::new(3.0, 4.0),
1056    //         Vector2DMm::new(5.0, 6.0)
1057    //     ];
1058    //     let sum = Vector2DMm::new(9.0, 12.0);
1059    //     assert_eq!(vecs.iter().sum::<Vector2DMm<_>>(), sum);
1060    //     assert_eq!(vecs.into_iter().sum::<Vector2DMm<_>>(), sum);
1061    // }
1062
1063    // #[test]
1064    // pub fn test_add_assign() {
1065    //     let mut p1 = Vector2DMm::new(1.0, 2.0);
1066    //     p1 += Vector2D::new(3.0, 4.0);
1067
1068    //     assert_eq!(p1, Vector2D::new(4.0, 6.0));
1069    // }
1070
1071    // #[test]
1072    // pub fn test_tpyed_scalar_mul() {
1073    //     let p1 = Vector2DMm::new(1.0, 2.0);
1074    //     let cm_per_mm = Scale::<f32, Mm, Cm>::new(0.1);
1075
1076    //     let result: Vector2DCm<f32> = p1 * cm_per_mm;
1077
1078    //     assert_eq!(result, Vector2D::new(0.1, 0.2));
1079    // }
1080
1081    #[test]
1082    pub fn test_swizzling() {
1083        let p: Vector2D<i32> = Vector2D::new(1, 2);
1084        assert_eq!(p.yx(), Vector2D::new(2, 1));
1085    }
1086
1087    // #[test]
1088    // pub fn test_reflect() {
1089    //     // use crate::approxeq::ApproxEq;
1090    //     let a: Vec2 = Vector2D::new(1.0, 3.0);
1091    //     let n1: Vec2 = Vector2D::new(0.0, -1.0);
1092    //     let n2: Vec2 = Vector2D::new(1.0, -1.0).normalize();
1093
1094    //     assert!(a.reflect(n1).approx_eq(&Vector2D::new(1.0, -3.0)));
1095    //     assert!(a.reflect(n2).approx_eq(&Vector2D::new(3.0, 1.0)));
1096    // }
1097}