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