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}