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}