Skip to main content

euclid/
point.rs

1// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use super::UnknownUnit;
11use crate::approxord::{max, min};
12use crate::length::Length;
13use crate::num::*;
14use crate::scale::Scale;
15use crate::size::{Size2D, Size3D};
16use crate::vector::{vec2, vec3, Vector2D, Vector3D};
17use core::cmp::{Eq, PartialEq};
18use core::fmt;
19use core::hash::Hash;
20use core::marker::PhantomData;
21use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
22#[cfg(feature = "malloc_size_of")]
23use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
24#[cfg(feature = "mint")]
25use mint;
26use num_traits::{Euclid, NumCast};
27
28#[cfg(feature = "serde")]
29use serde;
30
31#[cfg(feature = "bytemuck")]
32use bytemuck::{Pod, Zeroable};
33
34/// A 2d Point tagged with a unit.
35#[repr(C)]
36pub struct Point2D<T, U> {
37    pub x: T,
38    pub y: T,
39    #[doc(hidden)]
40    pub _unit: PhantomData<U>,
41}
42
43impl<T: Copy, U> Copy for Point2D<T, U> {}
44
45impl<T: Clone, U> Clone for Point2D<T, U> {
46    fn clone(&self) -> Self {
47        Point2D {
48            x: self.x.clone(),
49            y: self.y.clone(),
50            _unit: PhantomData,
51        }
52    }
53}
54
55#[cfg(feature = "serde")]
56impl<'de, T, U> serde::Deserialize<'de> for Point2D<T, U>
57where
58    T: serde::Deserialize<'de>,
59{
60    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
61    where
62        D: serde::Deserializer<'de>,
63    {
64        let (x, y) = serde::Deserialize::deserialize(deserializer)?;
65        Ok(Point2D {
66            x,
67            y,
68            _unit: PhantomData,
69        })
70    }
71}
72
73#[cfg(feature = "serde")]
74impl<T, U> serde::Serialize for Point2D<T, U>
75where
76    T: serde::Serialize,
77{
78    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
79    where
80        S: serde::Serializer,
81    {
82        (&self.x, &self.y).serialize(serializer)
83    }
84}
85
86#[cfg(feature = "arbitrary")]
87impl<'a, T, U> arbitrary::Arbitrary<'a> for Point2D<T, U>
88where
89    T: arbitrary::Arbitrary<'a>,
90{
91    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
92        let (x, y) = arbitrary::Arbitrary::arbitrary(u)?;
93        Ok(Point2D {
94            x,
95            y,
96            _unit: PhantomData,
97        })
98    }
99}
100
101#[cfg(feature = "bytemuck")]
102unsafe impl<T: Zeroable, U> Zeroable for Point2D<T, U> {}
103
104#[cfg(feature = "bytemuck")]
105unsafe impl<T: Pod, U: 'static> Pod for Point2D<T, U> {}
106
107#[cfg(feature = "malloc_size_of")]
108impl<T: MallocSizeOf, U> MallocSizeOf for Point2D<T, U> {
109    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
110        self.x.size_of(ops) + self.y.size_of(ops)
111    }
112}
113
114impl<T, U> Eq for Point2D<T, U> where T: Eq {}
115
116impl<T, U> PartialEq for Point2D<T, U>
117where
118    T: PartialEq,
119{
120    fn eq(&self, other: &Self) -> bool {
121        self.x == other.x && self.y == other.y
122    }
123}
124
125impl<T, U> Hash for Point2D<T, U>
126where
127    T: Hash,
128{
129    fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
130        self.x.hash(h);
131        self.y.hash(h);
132    }
133}
134
135mint_vec!(Point2D[x, y] = Point2);
136
137impl<T: fmt::Debug, U> fmt::Debug for Point2D<T, U> {
138    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
139        f.debug_tuple("").field(&self.x).field(&self.y).finish()
140    }
141}
142
143impl<T: Default, U> Default for Point2D<T, U> {
144    fn default() -> Self {
145        Point2D::new(Default::default(), Default::default())
146    }
147}
148
149impl<T, U> Point2D<T, U> {
150    /// Constructor, setting all components to zero.
151    #[inline]
152    pub fn origin() -> Self
153    where
154        T: Zero,
155    {
156        point2(Zero::zero(), Zero::zero())
157    }
158
159    /// The same as [`Point2D::origin`].
160    #[inline]
161    pub fn zero() -> Self
162    where
163        T: Zero,
164    {
165        Self::origin()
166    }
167
168    /// Constructor taking scalar values directly.
169    #[inline]
170    pub const fn new(x: T, y: T) -> Self {
171        Point2D {
172            x,
173            y,
174            _unit: PhantomData,
175        }
176    }
177
178    /// Constructor taking properly Lengths instead of scalar values.
179    #[inline]
180    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>) -> Self {
181        point2(x.0, y.0)
182    }
183
184    /// Constructor setting all components to the same value.
185    #[inline]
186    pub fn splat(v: T) -> Self
187    where
188        T: Clone,
189    {
190        Point2D {
191            x: v.clone(),
192            y: v,
193            _unit: PhantomData,
194        }
195    }
196
197    /// Tag a unitless value with units.
198    #[inline]
199    pub fn from_untyped(p: Point2D<T, UnknownUnit>) -> Self {
200        point2(p.x, p.y)
201    }
202
203    /// Apply the function `f` to each component of this point.
204    ///
205    /// # Example
206    ///
207    /// This may be used to perform unusual arithmetic which is not already offered as methods.
208    ///
209    /// ```
210    /// use euclid::default::Point2D;
211    ///
212    /// let p = Point2D::<u32>::new(5, 15);
213    /// assert_eq!(p.map(|coord| coord.saturating_sub(10)), Point2D::new(0, 5));
214    /// ```
215    #[inline]
216    pub fn map<V, F: FnMut(T) -> V>(self, mut f: F) -> Point2D<V, U> {
217        point2(f(self.x), f(self.y))
218    }
219
220    /// Apply the function `f` to each pair of components of this point and `rhs`.
221    ///
222    /// # Example
223    ///
224    /// This may be used to perform unusual arithmetic which is not already offered as methods.
225    ///
226    /// ```
227    /// use euclid::{default::{Point2D, Vector2D}, point2};
228    ///
229    /// let a: Point2D<u32> = point2(50, 200);
230    /// let b: Point2D<u32> = point2(100, 100);
231    /// assert_eq!(a.zip(b, u32::saturating_sub), Vector2D::new(0, 100));
232    /// ```
233    #[inline]
234    pub fn zip<V, F: FnMut(T, T) -> V>(self, rhs: Self, mut f: F) -> Vector2D<V, U> {
235        vec2(f(self.x, rhs.x), f(self.y, rhs.y))
236    }
237}
238
239impl<T: Copy, U> Point2D<T, U> {
240    /// Create a 3d point from this one, using the specified z value.
241    #[inline]
242    pub fn extend(self, z: T) -> Point3D<T, U> {
243        point3(self.x, self.y, z)
244    }
245
246    /// Cast this point into a vector.
247    ///
248    /// Equivalent to subtracting the origin from this point.
249    #[inline]
250    pub fn to_vector(self) -> Vector2D<T, U> {
251        Vector2D {
252            x: self.x,
253            y: self.y,
254            _unit: PhantomData,
255        }
256    }
257
258    /// Swap x and y.
259    ///
260    /// # Example
261    ///
262    /// ```rust
263    /// # use euclid::{Point2D, point2};
264    /// enum Mm {}
265    ///
266    /// let point: Point2D<_, Mm> = point2(1, -8);
267    ///
268    /// assert_eq!(point.yx(), point2(-8, 1));
269    /// ```
270    #[inline]
271    pub fn yx(self) -> Self {
272        point2(self.y, self.x)
273    }
274
275    /// Drop the units, preserving only the numeric value.
276    ///
277    /// # Example
278    ///
279    /// ```rust
280    /// # use euclid::{Point2D, point2};
281    /// enum Mm {}
282    ///
283    /// let point: Point2D<_, Mm> = point2(1, -8);
284    ///
285    /// assert_eq!(point.x, point.to_untyped().x);
286    /// assert_eq!(point.y, point.to_untyped().y);
287    /// ```
288    #[inline]
289    pub fn to_untyped(self) -> Point2D<T, UnknownUnit> {
290        point2(self.x, self.y)
291    }
292
293    /// Cast the unit, preserving the numeric value.
294    ///
295    /// # Example
296    ///
297    /// ```rust
298    /// # use euclid::{Point2D, point2};
299    /// enum Mm {}
300    /// enum Cm {}
301    ///
302    /// let point: Point2D<_, Mm> = point2(1, -8);
303    ///
304    /// assert_eq!(point.x, point.cast_unit::<Cm>().x);
305    /// assert_eq!(point.y, point.cast_unit::<Cm>().y);
306    /// ```
307    #[inline]
308    pub fn cast_unit<V>(self) -> Point2D<T, V> {
309        point2(self.x, self.y)
310    }
311
312    /// Cast into an array with x and y.
313    ///
314    /// # Example
315    ///
316    /// ```rust
317    /// # use euclid::{Point2D, point2};
318    /// enum Mm {}
319    ///
320    /// let point: Point2D<_, Mm> = point2(1, -8);
321    ///
322    /// assert_eq!(point.to_array(), [1, -8]);
323    /// ```
324    #[inline]
325    pub fn to_array(self) -> [T; 2] {
326        [self.x, self.y]
327    }
328
329    /// Cast into a tuple with x and y.
330    ///
331    /// # Example
332    ///
333    /// ```rust
334    /// # use euclid::{Point2D, point2};
335    /// enum Mm {}
336    ///
337    /// let point: Point2D<_, Mm> = point2(1, -8);
338    ///
339    /// assert_eq!(point.to_tuple(), (1, -8));
340    /// ```
341    #[inline]
342    pub fn to_tuple(self) -> (T, T) {
343        (self.x, self.y)
344    }
345
346    /// Convert into a 3d point with z-coordinate equals to zero.
347    #[inline]
348    pub fn to_3d(self) -> Point3D<T, U>
349    where
350        T: Zero,
351    {
352        point3(self.x, self.y, Zero::zero())
353    }
354
355    /// Rounds each component to the nearest integer value.
356    ///
357    /// This behavior is preserved for negative values (unlike the basic cast).
358    ///
359    /// ```rust
360    /// # use euclid::point2;
361    /// enum Mm {}
362    ///
363    /// assert_eq!(point2::<_, Mm>(-0.1, -0.8).round(), point2::<_, Mm>(0.0, -1.0))
364    /// ```
365    #[inline]
366    #[must_use]
367    pub fn round(self) -> Self
368    where
369        T: Round,
370    {
371        point2(self.x.round(), self.y.round())
372    }
373
374    /// Rounds each component to the smallest integer equal or greater than the original value.
375    ///
376    /// This behavior is preserved for negative values (unlike the basic cast).
377    ///
378    /// ```rust
379    /// # use euclid::point2;
380    /// enum Mm {}
381    ///
382    /// assert_eq!(point2::<_, Mm>(-0.1, -0.8).ceil(), point2::<_, Mm>(0.0, 0.0))
383    /// ```
384    #[inline]
385    #[must_use]
386    pub fn ceil(self) -> Self
387    where
388        T: Ceil,
389    {
390        point2(self.x.ceil(), self.y.ceil())
391    }
392
393    /// Rounds each component to the biggest integer equal or lower than the original value.
394    ///
395    /// This behavior is preserved for negative values (unlike the basic cast).
396    ///
397    /// ```rust
398    /// # use euclid::point2;
399    /// enum Mm {}
400    ///
401    /// assert_eq!(point2::<_, Mm>(-0.1, -0.8).floor(), point2::<_, Mm>(-1.0, -1.0))
402    /// ```
403    #[inline]
404    #[must_use]
405    pub fn floor(self) -> Self
406    where
407        T: Floor,
408    {
409        point2(self.x.floor(), self.y.floor())
410    }
411
412    /// Linearly interpolate between this point and another point.
413    ///
414    /// # Example
415    ///
416    /// ```rust
417    /// use euclid::point2;
418    /// use euclid::default::Point2D;
419    ///
420    /// let from: Point2D<_> = point2(0.0, 10.0);
421    /// let to:  Point2D<_> = point2(8.0, -4.0);
422    ///
423    /// assert_eq!(from.lerp(to, -1.0), point2(-8.0,  24.0));
424    /// assert_eq!(from.lerp(to,  0.0), point2( 0.0,  10.0));
425    /// assert_eq!(from.lerp(to,  0.5), point2( 4.0,   3.0));
426    /// assert_eq!(from.lerp(to,  1.0), point2( 8.0,  -4.0));
427    /// assert_eq!(from.lerp(to,  2.0), point2(16.0, -18.0));
428    /// ```
429    #[inline]
430    pub fn lerp(self, other: Self, t: T) -> Self
431    where
432        T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
433    {
434        let one_t = T::one() - t;
435        point2(one_t * self.x + t * other.x, one_t * self.y + t * other.y)
436    }
437}
438
439impl<T: PartialOrd, U> Point2D<T, U> {
440    #[inline]
441    pub fn min(self, other: Self) -> Self {
442        point2(min(self.x, other.x), min(self.y, other.y))
443    }
444
445    #[inline]
446    pub fn max(self, other: Self) -> Self {
447        point2(max(self.x, other.x), max(self.y, other.y))
448    }
449
450    /// Returns the point each component of which clamped by corresponding
451    /// components of `start` and `end`.
452    ///
453    /// Shortcut for `self.max(start).min(end)`.
454    #[inline]
455    pub fn clamp(self, start: Self, end: Self) -> Self
456    where
457        T: Copy,
458    {
459        self.max(start).min(end)
460    }
461}
462
463impl<T: NumCast + Copy, U> Point2D<T, U> {
464    /// Cast from one numeric representation to another, preserving the units.
465    ///
466    /// When casting from floating point to integer coordinates, the decimals are truncated
467    /// as one would expect from a simple cast, but this behavior does not always make sense
468    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
469    #[inline]
470    pub fn cast<NewT: NumCast>(self) -> Point2D<NewT, U> {
471        self.try_cast().unwrap()
472    }
473
474    /// Fallible cast from one numeric representation to another, preserving the units.
475    ///
476    /// When casting from floating point to integer coordinates, the decimals are truncated
477    /// as one would expect from a simple cast, but this behavior does not always make sense
478    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
479    pub fn try_cast<NewT: NumCast>(self) -> Option<Point2D<NewT, U>> {
480        match (NumCast::from(self.x), NumCast::from(self.y)) {
481            (Some(x), Some(y)) => Some(point2(x, y)),
482            _ => None,
483        }
484    }
485
486    // Convenience functions for common casts
487
488    /// Cast into an `f32` point.
489    #[inline]
490    pub fn to_f32(self) -> Point2D<f32, U> {
491        self.cast()
492    }
493
494    /// Cast into an `f64` point.
495    #[inline]
496    pub fn to_f64(self) -> Point2D<f64, U> {
497        self.cast()
498    }
499
500    /// Cast into an `usize` point, truncating decimals if any.
501    ///
502    /// When casting from floating point points, it is worth considering whether
503    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
504    /// the desired conversion behavior.
505    #[inline]
506    pub fn to_usize(self) -> Point2D<usize, U> {
507        self.cast()
508    }
509
510    /// Cast into an `u32` point, truncating decimals if any.
511    ///
512    /// When casting from floating point points, it is worth considering whether
513    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
514    /// the desired conversion behavior.
515    #[inline]
516    pub fn to_u32(self) -> Point2D<u32, U> {
517        self.cast()
518    }
519
520    /// Cast into an `i32` point, truncating decimals if any.
521    ///
522    /// When casting from floating point points, it is worth considering whether
523    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
524    /// the desired conversion behavior.
525    #[inline]
526    pub fn to_i32(self) -> Point2D<i32, U> {
527        self.cast()
528    }
529
530    /// Cast into an `i64` point, truncating decimals if any.
531    ///
532    /// When casting from floating point points, it is worth considering whether
533    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
534    /// the desired conversion behavior.
535    #[inline]
536    pub fn to_i64(self) -> Point2D<i64, U> {
537        self.cast()
538    }
539}
540
541#[cfg(any(feature = "std", feature = "libm"))]
542mod point2d_float {
543    use super::Point2D;
544    use crate::{approxeq::ApproxEq, point2};
545    use core::ops::Sub;
546    use num_traits::{real::Real, Float};
547
548    impl<T: Float, U> Point2D<T, U> {
549        /// Returns `true` if all members are finite.
550        #[inline]
551        pub fn is_finite(self) -> bool {
552            self.x.is_finite() && self.y.is_finite()
553        }
554    }
555
556    impl<T: Real + Sub<T, Output = T>, U> Point2D<T, U> {
557        #[inline]
558        pub fn distance_to(self, other: Self) -> T {
559            (self - other).length()
560        }
561    }
562
563    impl<T: ApproxEq<T>, U> ApproxEq<Point2D<T, U>> for Point2D<T, U> {
564        #[inline]
565        fn approx_epsilon() -> Self {
566            point2(T::approx_epsilon(), T::approx_epsilon())
567        }
568
569        #[inline]
570        fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
571            self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
572        }
573    }
574}
575
576impl<T: Copy + Add<T, Output = T>, U> Point2D<T, U> {
577    #[inline]
578    pub fn add_size(self, other: &Size2D<T, U>) -> Self {
579        point2(self.x + other.width, self.y + other.height)
580    }
581}
582
583impl<T: Neg, U> Neg for Point2D<T, U> {
584    type Output = Point2D<T::Output, U>;
585
586    #[inline]
587    fn neg(self) -> Self::Output {
588        point2(-self.x, -self.y)
589    }
590}
591
592impl<T: Add, U> Add<Size2D<T, U>> for Point2D<T, U> {
593    type Output = Point2D<T::Output, U>;
594
595    #[inline]
596    fn add(self, other: Size2D<T, U>) -> Self::Output {
597        point2(self.x + other.width, self.y + other.height)
598    }
599}
600
601impl<T: AddAssign, U> AddAssign<Size2D<T, U>> for Point2D<T, U> {
602    #[inline]
603    fn add_assign(&mut self, other: Size2D<T, U>) {
604        self.x += other.width;
605        self.y += other.height;
606    }
607}
608
609impl<T: Add, U> Add<Vector2D<T, U>> for Point2D<T, U> {
610    type Output = Point2D<T::Output, U>;
611
612    #[inline]
613    fn add(self, other: Vector2D<T, U>) -> Self::Output {
614        point2(self.x + other.x, self.y + other.y)
615    }
616}
617
618impl<T: Copy + Add<T, Output = T>, U> AddAssign<Vector2D<T, U>> for Point2D<T, U> {
619    #[inline]
620    fn add_assign(&mut self, other: Vector2D<T, U>) {
621        *self = *self + other;
622    }
623}
624
625impl<T: Sub, U> Sub for Point2D<T, U> {
626    type Output = Vector2D<T::Output, U>;
627
628    #[inline]
629    fn sub(self, other: Self) -> Self::Output {
630        vec2(self.x - other.x, self.y - other.y)
631    }
632}
633
634impl<T: Sub, U> Sub<Size2D<T, U>> for Point2D<T, U> {
635    type Output = Point2D<T::Output, U>;
636
637    #[inline]
638    fn sub(self, other: Size2D<T, U>) -> Self::Output {
639        point2(self.x - other.width, self.y - other.height)
640    }
641}
642
643impl<T: SubAssign, U> SubAssign<Size2D<T, U>> for Point2D<T, U> {
644    #[inline]
645    fn sub_assign(&mut self, other: Size2D<T, U>) {
646        self.x -= other.width;
647        self.y -= other.height;
648    }
649}
650
651impl<T: Sub, U> Sub<Vector2D<T, U>> for Point2D<T, U> {
652    type Output = Point2D<T::Output, U>;
653
654    #[inline]
655    fn sub(self, other: Vector2D<T, U>) -> Self::Output {
656        point2(self.x - other.x, self.y - other.y)
657    }
658}
659
660impl<T: Copy + Sub<T, Output = T>, U> SubAssign<Vector2D<T, U>> for Point2D<T, U> {
661    #[inline]
662    fn sub_assign(&mut self, other: Vector2D<T, U>) {
663        *self = *self - other;
664    }
665}
666
667impl<T: Copy + Mul, U> Mul<T> for Point2D<T, U> {
668    type Output = Point2D<T::Output, U>;
669
670    #[inline]
671    fn mul(self, scale: T) -> Self::Output {
672        point2(self.x * scale, self.y * scale)
673    }
674}
675
676impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for Point2D<T, U> {
677    #[inline]
678    fn mul_assign(&mut self, scale: T) {
679        *self = *self * scale;
680    }
681}
682
683impl<T: Copy + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Point2D<T, U1> {
684    type Output = Point2D<T::Output, U2>;
685
686    #[inline]
687    fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
688        point2(self.x * scale.0, self.y * scale.0)
689    }
690}
691
692impl<T: Copy + MulAssign, U> MulAssign<Scale<T, U, U>> for Point2D<T, U> {
693    #[inline]
694    fn mul_assign(&mut self, scale: Scale<T, U, U>) {
695        self.x *= scale.0;
696        self.y *= scale.0;
697    }
698}
699
700impl<T: Copy + Div, U> Div<T> for Point2D<T, U> {
701    type Output = Point2D<T::Output, U>;
702
703    #[inline]
704    fn div(self, scale: T) -> Self::Output {
705        point2(self.x / scale, self.y / scale)
706    }
707}
708
709impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for Point2D<T, U> {
710    #[inline]
711    fn div_assign(&mut self, scale: T) {
712        *self = *self / scale;
713    }
714}
715
716impl<T: Copy + Div, U1, U2> Div<Scale<T, U1, U2>> for Point2D<T, U2> {
717    type Output = Point2D<T::Output, U1>;
718
719    #[inline]
720    fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
721        point2(self.x / scale.0, self.y / scale.0)
722    }
723}
724
725impl<T: Copy + DivAssign, U> DivAssign<Scale<T, U, U>> for Point2D<T, U> {
726    #[inline]
727    fn div_assign(&mut self, scale: Scale<T, U, U>) {
728        self.x /= scale.0;
729        self.y /= scale.0;
730    }
731}
732
733impl<T: Zero, U> Zero for Point2D<T, U> {
734    #[inline]
735    fn zero() -> Self {
736        Self::origin()
737    }
738}
739
740impl<T: Round, U> Round for Point2D<T, U> {
741    /// See [`Point2D::round`].
742    #[inline]
743    fn round(self) -> Self {
744        self.round()
745    }
746}
747
748impl<T: Ceil, U> Ceil for Point2D<T, U> {
749    /// See [`Point2D::ceil`].
750    #[inline]
751    fn ceil(self) -> Self {
752        self.ceil()
753    }
754}
755
756impl<T: Floor, U> Floor for Point2D<T, U> {
757    /// See [`Point2D::floor`].
758    #[inline]
759    fn floor(self) -> Self {
760        self.floor()
761    }
762}
763
764impl<T: Euclid, U> Point2D<T, U> {
765    /// Calculates the least nonnegative remainder of `self (mod other)`.
766    ///
767    /// # Example
768    ///
769    /// ```rust
770    /// use euclid::point2;
771    /// use euclid::default::{Point2D, Size2D};
772    ///
773    /// let p = Point2D::new(7.0, -7.0);
774    /// let s = Size2D::new(4.0, -4.0);
775    ///
776    /// assert_eq!(p.rem_euclid(&s), point2(3.0, 1.0));
777    /// assert_eq!((-p).rem_euclid(&s), point2(1.0, 3.0));
778    /// assert_eq!(p.rem_euclid(&-s), point2(3.0, 1.0));
779    /// ```
780    #[inline]
781    pub fn rem_euclid(&self, other: &Size2D<T, U>) -> Self {
782        point2(
783            self.x.rem_euclid(&other.width),
784            self.y.rem_euclid(&other.height),
785        )
786    }
787
788    /// Calculates Euclidean division, the matching method for `rem_euclid`.
789    ///
790    /// # Example
791    ///
792    /// ```rust
793    /// use euclid::point2;
794    /// use euclid::default::{Point2D, Size2D};
795    ///
796    /// let p = Point2D::new(7.0, -7.0);
797    /// let s = Size2D::new(4.0, -4.0);
798    ///
799    /// assert_eq!(p.div_euclid(&s), point2(1.0, 2.0));
800    /// assert_eq!((-p).div_euclid(&s), point2(-2.0, -1.0));
801    /// assert_eq!(p.div_euclid(&-s), point2(-1.0, -2.0));
802    /// ```
803    #[inline]
804    pub fn div_euclid(&self, other: &Size2D<T, U>) -> Self {
805        point2(
806            self.x.div_euclid(&other.width),
807            self.y.div_euclid(&other.height),
808        )
809    }
810}
811
812impl<T, U> From<Point2D<T, U>> for [T; 2] {
813    fn from(p: Point2D<T, U>) -> Self {
814        [p.x, p.y]
815    }
816}
817
818impl<T, U> From<[T; 2]> for Point2D<T, U> {
819    fn from([x, y]: [T; 2]) -> Self {
820        point2(x, y)
821    }
822}
823
824impl<T, U> From<Point2D<T, U>> for (T, T) {
825    fn from(p: Point2D<T, U>) -> Self {
826        (p.x, p.y)
827    }
828}
829
830impl<T, U> From<(T, T)> for Point2D<T, U> {
831    fn from(tuple: (T, T)) -> Self {
832        point2(tuple.0, tuple.1)
833    }
834}
835
836/// A 3d Point tagged with a unit.
837#[repr(C)]
838pub struct Point3D<T, U> {
839    pub x: T,
840    pub y: T,
841    pub z: T,
842    #[doc(hidden)]
843    pub _unit: PhantomData<U>,
844}
845
846mint_vec!(Point3D[x, y, z] = Point3);
847
848impl<T: Copy, U> Copy for Point3D<T, U> {}
849
850impl<T: Clone, U> Clone for Point3D<T, U> {
851    fn clone(&self) -> Self {
852        Point3D {
853            x: self.x.clone(),
854            y: self.y.clone(),
855            z: self.z.clone(),
856            _unit: PhantomData,
857        }
858    }
859}
860
861#[cfg(feature = "serde")]
862impl<'de, T, U> serde::Deserialize<'de> for Point3D<T, U>
863where
864    T: serde::Deserialize<'de>,
865{
866    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
867    where
868        D: serde::Deserializer<'de>,
869    {
870        let (x, y, z) = serde::Deserialize::deserialize(deserializer)?;
871        Ok(Point3D {
872            x,
873            y,
874            z,
875            _unit: PhantomData,
876        })
877    }
878}
879
880#[cfg(feature = "serde")]
881impl<T, U> serde::Serialize for Point3D<T, U>
882where
883    T: serde::Serialize,
884{
885    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
886    where
887        S: serde::Serializer,
888    {
889        (&self.x, &self.y, &self.z).serialize(serializer)
890    }
891}
892
893#[cfg(feature = "arbitrary")]
894impl<'a, T, U> arbitrary::Arbitrary<'a> for Point3D<T, U>
895where
896    T: arbitrary::Arbitrary<'a>,
897{
898    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
899        let (x, y, z) = arbitrary::Arbitrary::arbitrary(u)?;
900        Ok(Point3D {
901            x,
902            y,
903            z,
904            _unit: PhantomData,
905        })
906    }
907}
908
909#[cfg(feature = "bytemuck")]
910unsafe impl<T: Zeroable, U> Zeroable for Point3D<T, U> {}
911
912#[cfg(feature = "bytemuck")]
913unsafe impl<T: Pod, U: 'static> Pod for Point3D<T, U> {}
914
915#[cfg(feature = "malloc_size_of")]
916impl<T: MallocSizeOf, U> MallocSizeOf for Point3D<T, U> {
917    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
918        self.x.size_of(ops) + self.y.size_of(ops) + self.z.size_of(ops)
919    }
920}
921
922impl<T, U> Eq for Point3D<T, U> where T: Eq {}
923
924impl<T, U> PartialEq for Point3D<T, U>
925where
926    T: PartialEq,
927{
928    fn eq(&self, other: &Self) -> bool {
929        self.x == other.x && self.y == other.y && self.z == other.z
930    }
931}
932
933impl<T, U> Hash for Point3D<T, U>
934where
935    T: Hash,
936{
937    fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
938        self.x.hash(h);
939        self.y.hash(h);
940        self.z.hash(h);
941    }
942}
943
944impl<T: fmt::Debug, U> fmt::Debug for Point3D<T, U> {
945    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
946        f.debug_tuple("")
947            .field(&self.x)
948            .field(&self.y)
949            .field(&self.z)
950            .finish()
951    }
952}
953
954impl<T: Default, U> Default for Point3D<T, U> {
955    fn default() -> Self {
956        Point3D::new(Default::default(), Default::default(), Default::default())
957    }
958}
959
960impl<T, U> Point3D<T, U> {
961    /// Constructor, setting all components to zero.
962    #[inline]
963    pub fn origin() -> Self
964    where
965        T: Zero,
966    {
967        point3(Zero::zero(), Zero::zero(), Zero::zero())
968    }
969
970    /// The same as [`Point3D::origin`].
971    #[inline]
972    pub fn zero() -> Self
973    where
974        T: Zero,
975    {
976        Self::origin()
977    }
978
979    /// Constructor taking scalar values directly.
980    #[inline]
981    pub const fn new(x: T, y: T, z: T) -> Self {
982        Point3D {
983            x,
984            y,
985            z,
986            _unit: PhantomData,
987        }
988    }
989
990    /// Constructor taking properly Lengths instead of scalar values.
991    #[inline]
992    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>, z: Length<T, U>) -> Self {
993        point3(x.0, y.0, z.0)
994    }
995
996    /// Constructor setting all components to the same value.
997    #[inline]
998    pub fn splat(v: T) -> Self
999    where
1000        T: Clone,
1001    {
1002        Point3D {
1003            x: v.clone(),
1004            y: v.clone(),
1005            z: v,
1006            _unit: PhantomData,
1007        }
1008    }
1009
1010    /// Tag a unitless value with units.
1011    #[inline]
1012    pub fn from_untyped(p: Point3D<T, UnknownUnit>) -> Self {
1013        point3(p.x, p.y, p.z)
1014    }
1015
1016    /// Apply the function `f` to each component of this point.
1017    ///
1018    /// # Example
1019    ///
1020    /// This may be used to perform unusual arithmetic which is not already offered as methods.
1021    ///
1022    /// ```
1023    /// use euclid::default::Point3D;
1024    ///
1025    /// let p = Point3D::<u32>::new(5, 11, 15);
1026    /// assert_eq!(p.map(|coord| coord.saturating_sub(10)), Point3D::new(0, 1, 5));
1027    /// ```
1028    #[inline]
1029    pub fn map<V, F: FnMut(T) -> V>(self, mut f: F) -> Point3D<V, U> {
1030        point3(f(self.x), f(self.y), f(self.z))
1031    }
1032
1033    /// Apply the function `f` to each pair of components of this point and `rhs`.
1034    ///
1035    /// # Example
1036    ///
1037    /// This may be used to perform unusual arithmetic which is not already offered as methods.
1038    ///
1039    /// ```
1040    /// use euclid::{default::{Point3D, Vector3D}, point2};
1041    ///
1042    /// let a: Point3D<u32> = Point3D::new(50, 200, 400);
1043    /// let b: Point3D<u32> = Point3D::new(100, 100, 150);
1044    /// assert_eq!(a.zip(b, u32::saturating_sub), Vector3D::new(0, 100, 250));
1045    /// ```
1046    #[inline]
1047    pub fn zip<V, F: FnMut(T, T) -> V>(self, rhs: Self, mut f: F) -> Vector3D<V, U> {
1048        vec3(f(self.x, rhs.x), f(self.y, rhs.y), f(self.z, rhs.z))
1049    }
1050}
1051
1052impl<T: Copy, U> Point3D<T, U> {
1053    /// Cast this point into a vector.
1054    ///
1055    /// Equivalent to subtracting the origin to this point.
1056    #[inline]
1057    pub fn to_vector(self) -> Vector3D<T, U> {
1058        Vector3D {
1059            x: self.x,
1060            y: self.y,
1061            z: self.z,
1062            _unit: PhantomData,
1063        }
1064    }
1065
1066    /// Returns a 2d point using this point's x and y coordinates
1067    #[inline]
1068    pub fn xy(self) -> Point2D<T, U> {
1069        point2(self.x, self.y)
1070    }
1071
1072    /// Returns a 2d point using this point's x and z coordinates
1073    #[inline]
1074    pub fn xz(self) -> Point2D<T, U> {
1075        point2(self.x, self.z)
1076    }
1077
1078    /// Returns a 2d point using this point's x and z coordinates
1079    #[inline]
1080    pub fn yz(self) -> Point2D<T, U> {
1081        point2(self.y, self.z)
1082    }
1083
1084    /// Cast into an array with x, y and z.
1085    ///
1086    /// # Example
1087    ///
1088    /// ```rust
1089    /// # use euclid::{Point3D, point3};
1090    /// enum Mm {}
1091    ///
1092    /// let point: Point3D<_, Mm> = point3(1, -8, 0);
1093    ///
1094    /// assert_eq!(point.to_array(), [1, -8, 0]);
1095    /// ```
1096    #[inline]
1097    pub fn to_array(self) -> [T; 3] {
1098        [self.x, self.y, self.z]
1099    }
1100
1101    #[inline]
1102    pub fn to_array_4d(self) -> [T; 4]
1103    where
1104        T: One,
1105    {
1106        [self.x, self.y, self.z, One::one()]
1107    }
1108
1109    /// Cast into a tuple with x, y and z.
1110    ///
1111    /// # Example
1112    ///
1113    /// ```rust
1114    /// # use euclid::{Point3D, point3};
1115    /// enum Mm {}
1116    ///
1117    /// let point: Point3D<_, Mm> = point3(1, -8, 0);
1118    ///
1119    /// assert_eq!(point.to_tuple(), (1, -8, 0));
1120    /// ```
1121    #[inline]
1122    pub fn to_tuple(self) -> (T, T, T) {
1123        (self.x, self.y, self.z)
1124    }
1125
1126    #[inline]
1127    pub fn to_tuple_4d(self) -> (T, T, T, T)
1128    where
1129        T: One,
1130    {
1131        (self.x, self.y, self.z, One::one())
1132    }
1133
1134    /// Drop the units, preserving only the numeric value.
1135    ///
1136    /// # Example
1137    ///
1138    /// ```rust
1139    /// # use euclid::{Point3D, point3};
1140    /// enum Mm {}
1141    ///
1142    /// let point: Point3D<_, Mm> = point3(1, -8, 0);
1143    ///
1144    /// assert_eq!(point.x, point.to_untyped().x);
1145    /// assert_eq!(point.y, point.to_untyped().y);
1146    /// assert_eq!(point.z, point.to_untyped().z);
1147    /// ```
1148    #[inline]
1149    pub fn to_untyped(self) -> Point3D<T, UnknownUnit> {
1150        point3(self.x, self.y, self.z)
1151    }
1152
1153    /// Cast the unit, preserving the numeric value.
1154    ///
1155    /// # Example
1156    ///
1157    /// ```rust
1158    /// # use euclid::{Point3D, point3};
1159    /// enum Mm {}
1160    /// enum Cm {}
1161    ///
1162    /// let point: Point3D<_, Mm> = point3(1, -8, 0);
1163    ///
1164    /// assert_eq!(point.x, point.cast_unit::<Cm>().x);
1165    /// assert_eq!(point.y, point.cast_unit::<Cm>().y);
1166    /// assert_eq!(point.z, point.cast_unit::<Cm>().z);
1167    /// ```
1168    #[inline]
1169    pub fn cast_unit<V>(self) -> Point3D<T, V> {
1170        point3(self.x, self.y, self.z)
1171    }
1172
1173    /// Convert into a 2d point.
1174    #[inline]
1175    pub fn to_2d(self) -> Point2D<T, U> {
1176        self.xy()
1177    }
1178
1179    /// Rounds each component to the nearest integer value.
1180    ///
1181    /// This behavior is preserved for negative values (unlike the basic cast).
1182    ///
1183    /// ```rust
1184    /// # use euclid::point3;
1185    /// enum Mm {}
1186    ///
1187    /// assert_eq!(point3::<_, Mm>(-0.1, -0.8, 0.4).round(), point3::<_, Mm>(0.0, -1.0, 0.0))
1188    /// ```
1189    #[inline]
1190    #[must_use]
1191    pub fn round(self) -> Self
1192    where
1193        T: Round,
1194    {
1195        point3(self.x.round(), self.y.round(), self.z.round())
1196    }
1197
1198    /// Rounds each component to the smallest integer equal or greater than the original value.
1199    ///
1200    /// This behavior is preserved for negative values (unlike the basic cast).
1201    ///
1202    /// ```rust
1203    /// # use euclid::point3;
1204    /// enum Mm {}
1205    ///
1206    /// assert_eq!(point3::<_, Mm>(-0.1, -0.8, 0.4).ceil(), point3::<_, Mm>(0.0, 0.0, 1.0))
1207    /// ```
1208    #[inline]
1209    #[must_use]
1210    pub fn ceil(self) -> Self
1211    where
1212        T: Ceil,
1213    {
1214        point3(self.x.ceil(), self.y.ceil(), self.z.ceil())
1215    }
1216
1217    /// Rounds each component to the biggest integer equal or lower than the original value.
1218    ///
1219    /// This behavior is preserved for negative values (unlike the basic cast).
1220    ///
1221    /// ```rust
1222    /// # use euclid::point3;
1223    /// enum Mm {}
1224    ///
1225    /// assert_eq!(point3::<_, Mm>(-0.1, -0.8, 0.4).floor(), point3::<_, Mm>(-1.0, -1.0, 0.0))
1226    /// ```
1227    #[inline]
1228    #[must_use]
1229    pub fn floor(self) -> Self
1230    where
1231        T: Floor,
1232    {
1233        point3(self.x.floor(), self.y.floor(), self.z.floor())
1234    }
1235
1236    /// Linearly interpolate between this point and another point.
1237    ///
1238    /// # Example
1239    ///
1240    /// ```rust
1241    /// use euclid::point3;
1242    /// use euclid::default::Point3D;
1243    ///
1244    /// let from: Point3D<_> = point3(0.0, 10.0, -1.0);
1245    /// let to:  Point3D<_> = point3(8.0, -4.0,  0.0);
1246    ///
1247    /// assert_eq!(from.lerp(to, -1.0), point3(-8.0,  24.0, -2.0));
1248    /// assert_eq!(from.lerp(to,  0.0), point3( 0.0,  10.0, -1.0));
1249    /// assert_eq!(from.lerp(to,  0.5), point3( 4.0,   3.0, -0.5));
1250    /// assert_eq!(from.lerp(to,  1.0), point3( 8.0,  -4.0,  0.0));
1251    /// assert_eq!(from.lerp(to,  2.0), point3(16.0, -18.0,  1.0));
1252    /// ```
1253    #[inline]
1254    pub fn lerp(self, other: Self, t: T) -> Self
1255    where
1256        T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
1257    {
1258        let one_t = T::one() - t;
1259        point3(
1260            one_t * self.x + t * other.x,
1261            one_t * self.y + t * other.y,
1262            one_t * self.z + t * other.z,
1263        )
1264    }
1265}
1266
1267impl<T: PartialOrd, U> Point3D<T, U> {
1268    #[inline]
1269    pub fn min(self, other: Self) -> Self {
1270        point3(
1271            min(self.x, other.x),
1272            min(self.y, other.y),
1273            min(self.z, other.z),
1274        )
1275    }
1276
1277    #[inline]
1278    pub fn max(self, other: Self) -> Self {
1279        point3(
1280            max(self.x, other.x),
1281            max(self.y, other.y),
1282            max(self.z, other.z),
1283        )
1284    }
1285
1286    /// Returns the point each component of which clamped by corresponding
1287    /// components of `start` and `end`.
1288    ///
1289    /// Shortcut for `self.max(start).min(end)`.
1290    #[inline]
1291    pub fn clamp(self, start: Self, end: Self) -> Self
1292    where
1293        T: Copy,
1294    {
1295        self.max(start).min(end)
1296    }
1297}
1298
1299impl<T: NumCast + Copy, U> Point3D<T, U> {
1300    /// Cast from one numeric representation to another, preserving the units.
1301    ///
1302    /// When casting from floating point to integer coordinates, the decimals are truncated
1303    /// as one would expect from a simple cast, but this behavior does not always make sense
1304    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
1305    #[inline]
1306    pub fn cast<NewT: NumCast>(self) -> Point3D<NewT, U> {
1307        self.try_cast().unwrap()
1308    }
1309
1310    /// Fallible cast from one numeric representation to another, preserving the units.
1311    ///
1312    /// When casting from floating point to integer coordinates, the decimals are truncated
1313    /// as one would expect from a simple cast, but this behavior does not always make sense
1314    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
1315    pub fn try_cast<NewT: NumCast>(self) -> Option<Point3D<NewT, U>> {
1316        match (
1317            NumCast::from(self.x),
1318            NumCast::from(self.y),
1319            NumCast::from(self.z),
1320        ) {
1321            (Some(x), Some(y), Some(z)) => Some(point3(x, y, z)),
1322            _ => None,
1323        }
1324    }
1325
1326    // Convenience functions for common casts
1327
1328    /// Cast into an `f32` point.
1329    #[inline]
1330    pub fn to_f32(self) -> Point3D<f32, U> {
1331        self.cast()
1332    }
1333
1334    /// Cast into an `f64` point.
1335    #[inline]
1336    pub fn to_f64(self) -> Point3D<f64, U> {
1337        self.cast()
1338    }
1339
1340    /// Cast into an `usize` point, truncating decimals if any.
1341    ///
1342    /// When casting from floating point points, it is worth considering whether
1343    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1344    /// the desired conversion behavior.
1345    #[inline]
1346    pub fn to_usize(self) -> Point3D<usize, U> {
1347        self.cast()
1348    }
1349
1350    /// Cast into an `u32` point, truncating decimals if any.
1351    ///
1352    /// When casting from floating point points, it is worth considering whether
1353    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1354    /// the desired conversion behavior.
1355    #[inline]
1356    pub fn to_u32(self) -> Point3D<u32, U> {
1357        self.cast()
1358    }
1359
1360    /// Cast into an `i32` point, truncating decimals if any.
1361    ///
1362    /// When casting from floating point points, it is worth considering whether
1363    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1364    /// the desired conversion behavior.
1365    #[inline]
1366    pub fn to_i32(self) -> Point3D<i32, U> {
1367        self.cast()
1368    }
1369
1370    /// Cast into an `i64` point, truncating decimals if any.
1371    ///
1372    /// When casting from floating point points, it is worth considering whether
1373    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1374    /// the desired conversion behavior.
1375    #[inline]
1376    pub fn to_i64(self) -> Point3D<i64, U> {
1377        self.cast()
1378    }
1379}
1380
1381impl<T: Copy + Add<T, Output = T>, U> Point3D<T, U> {
1382    #[inline]
1383    pub fn add_size(self, other: Size3D<T, U>) -> Self {
1384        point3(
1385            self.x + other.width,
1386            self.y + other.height,
1387            self.z + other.depth,
1388        )
1389    }
1390}
1391
1392impl<T: Neg, U> Neg for Point3D<T, U> {
1393    type Output = Point3D<T::Output, U>;
1394
1395    #[inline]
1396    fn neg(self) -> Self::Output {
1397        point3(-self.x, -self.y, -self.z)
1398    }
1399}
1400
1401impl<T: Add, U> Add<Size3D<T, U>> for Point3D<T, U> {
1402    type Output = Point3D<T::Output, U>;
1403
1404    #[inline]
1405    fn add(self, other: Size3D<T, U>) -> Self::Output {
1406        point3(
1407            self.x + other.width,
1408            self.y + other.height,
1409            self.z + other.depth,
1410        )
1411    }
1412}
1413
1414impl<T: AddAssign, U> AddAssign<Size3D<T, U>> for Point3D<T, U> {
1415    #[inline]
1416    fn add_assign(&mut self, other: Size3D<T, U>) {
1417        self.x += other.width;
1418        self.y += other.height;
1419        self.z += other.depth;
1420    }
1421}
1422
1423impl<T: Add, U> Add<Vector3D<T, U>> for Point3D<T, U> {
1424    type Output = Point3D<T::Output, U>;
1425
1426    #[inline]
1427    fn add(self, other: Vector3D<T, U>) -> Self::Output {
1428        point3(self.x + other.x, self.y + other.y, self.z + other.z)
1429    }
1430}
1431
1432impl<T: Copy + Add<T, Output = T>, U> AddAssign<Vector3D<T, U>> for Point3D<T, U> {
1433    #[inline]
1434    fn add_assign(&mut self, other: Vector3D<T, U>) {
1435        *self = *self + other;
1436    }
1437}
1438
1439impl<T: Sub, U> Sub for Point3D<T, U> {
1440    type Output = Vector3D<T::Output, U>;
1441
1442    #[inline]
1443    fn sub(self, other: Self) -> Self::Output {
1444        vec3(self.x - other.x, self.y - other.y, self.z - other.z)
1445    }
1446}
1447
1448impl<T: Sub, U> Sub<Size3D<T, U>> for Point3D<T, U> {
1449    type Output = Point3D<T::Output, U>;
1450
1451    #[inline]
1452    fn sub(self, other: Size3D<T, U>) -> Self::Output {
1453        point3(
1454            self.x - other.width,
1455            self.y - other.height,
1456            self.z - other.depth,
1457        )
1458    }
1459}
1460
1461impl<T: SubAssign, U> SubAssign<Size3D<T, U>> for Point3D<T, U> {
1462    #[inline]
1463    fn sub_assign(&mut self, other: Size3D<T, U>) {
1464        self.x -= other.width;
1465        self.y -= other.height;
1466        self.z -= other.depth;
1467    }
1468}
1469
1470impl<T: Sub, U> Sub<Vector3D<T, U>> for Point3D<T, U> {
1471    type Output = Point3D<T::Output, U>;
1472
1473    #[inline]
1474    fn sub(self, other: Vector3D<T, U>) -> Self::Output {
1475        point3(self.x - other.x, self.y - other.y, self.z - other.z)
1476    }
1477}
1478
1479impl<T: Copy + Sub<T, Output = T>, U> SubAssign<Vector3D<T, U>> for Point3D<T, U> {
1480    #[inline]
1481    fn sub_assign(&mut self, other: Vector3D<T, U>) {
1482        *self = *self - other;
1483    }
1484}
1485
1486impl<T: Copy + Mul, U> Mul<T> for Point3D<T, U> {
1487    type Output = Point3D<T::Output, U>;
1488
1489    #[inline]
1490    fn mul(self, scale: T) -> Self::Output {
1491        point3(self.x * scale, self.y * scale, self.z * scale)
1492    }
1493}
1494
1495impl<T: Copy + MulAssign, U> MulAssign<T> for Point3D<T, U> {
1496    #[inline]
1497    fn mul_assign(&mut self, scale: T) {
1498        self.x *= scale;
1499        self.y *= scale;
1500        self.z *= scale;
1501    }
1502}
1503
1504impl<T: Copy + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Point3D<T, U1> {
1505    type Output = Point3D<T::Output, U2>;
1506
1507    #[inline]
1508    fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
1509        point3(self.x * scale.0, self.y * scale.0, self.z * scale.0)
1510    }
1511}
1512
1513impl<T: Copy + MulAssign, U> MulAssign<Scale<T, U, U>> for Point3D<T, U> {
1514    #[inline]
1515    fn mul_assign(&mut self, scale: Scale<T, U, U>) {
1516        *self *= scale.0;
1517    }
1518}
1519
1520impl<T: Copy + Div, U> Div<T> for Point3D<T, U> {
1521    type Output = Point3D<T::Output, U>;
1522
1523    #[inline]
1524    fn div(self, scale: T) -> Self::Output {
1525        point3(self.x / scale, self.y / scale, self.z / scale)
1526    }
1527}
1528
1529impl<T: Copy + DivAssign, U> DivAssign<T> for Point3D<T, U> {
1530    #[inline]
1531    fn div_assign(&mut self, scale: T) {
1532        self.x /= scale;
1533        self.y /= scale;
1534        self.z /= scale;
1535    }
1536}
1537
1538impl<T: Copy + Div, U1, U2> Div<Scale<T, U1, U2>> for Point3D<T, U2> {
1539    type Output = Point3D<T::Output, U1>;
1540
1541    #[inline]
1542    fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
1543        point3(self.x / scale.0, self.y / scale.0, self.z / scale.0)
1544    }
1545}
1546
1547impl<T: Copy + DivAssign, U> DivAssign<Scale<T, U, U>> for Point3D<T, U> {
1548    #[inline]
1549    fn div_assign(&mut self, scale: Scale<T, U, U>) {
1550        *self /= scale.0;
1551    }
1552}
1553
1554impl<T: Zero, U> Zero for Point3D<T, U> {
1555    #[inline]
1556    fn zero() -> Self {
1557        Self::origin()
1558    }
1559}
1560
1561impl<T: Round, U> Round for Point3D<T, U> {
1562    /// See [`Point3D::round`].
1563    #[inline]
1564    fn round(self) -> Self {
1565        self.round()
1566    }
1567}
1568
1569impl<T: Ceil, U> Ceil for Point3D<T, U> {
1570    /// See [`Point3D::ceil`].
1571    #[inline]
1572    fn ceil(self) -> Self {
1573        self.ceil()
1574    }
1575}
1576
1577impl<T: Floor, U> Floor for Point3D<T, U> {
1578    /// See [`Point3D::floor`].
1579    #[inline]
1580    fn floor(self) -> Self {
1581        self.floor()
1582    }
1583}
1584
1585impl<T: Euclid, U> Point3D<T, U> {
1586    /// Calculates the least nonnegative remainder of `self (mod other)`.
1587    ///
1588    /// # Example
1589    ///
1590    /// ```rust
1591    /// use euclid::point3;
1592    /// use euclid::default::{Point3D, Size3D};
1593    ///
1594    /// let p = Point3D::new(7.0, -7.0, 0.0);
1595    /// let s = Size3D::new(4.0, -4.0, 12.0);
1596    ///
1597    /// assert_eq!(p.rem_euclid(&s), point3(3.0, 1.0, 0.0));
1598    /// assert_eq!((-p).rem_euclid(&s), point3(1.0, 3.0, 0.0));
1599    /// assert_eq!(p.rem_euclid(&-s), point3(3.0, 1.0, 0.0));
1600    /// ```
1601    #[inline]
1602    pub fn rem_euclid(&self, other: &Size3D<T, U>) -> Self {
1603        point3(
1604            self.x.rem_euclid(&other.width),
1605            self.y.rem_euclid(&other.height),
1606            self.z.rem_euclid(&other.depth),
1607        )
1608    }
1609
1610    /// Calculates Euclidean division, the matching method for `rem_euclid`.
1611    ///
1612    /// # Example
1613    ///
1614    /// ```rust
1615    /// use euclid::point3;
1616    /// use euclid::default::{Point3D, Size3D};
1617    ///
1618    /// let p = Point3D::new(7.0, -7.0, 0.0);
1619    /// let s = Size3D::new(4.0, -4.0, 12.0);
1620    ///
1621    /// assert_eq!(p.div_euclid(&s), point3(1.0, 2.0, 0.0));
1622    /// assert_eq!((-p).div_euclid(&s), point3(-2.0, -1.0, 0.0));
1623    /// assert_eq!(p.div_euclid(&-s), point3(-1.0, -2.0, 0.0));
1624    /// ```
1625    #[inline]
1626    pub fn div_euclid(&self, other: &Size3D<T, U>) -> Self {
1627        point3(
1628            self.x.div_euclid(&other.width),
1629            self.y.div_euclid(&other.height),
1630            self.z.div_euclid(&other.depth),
1631        )
1632    }
1633}
1634
1635impl<T, U> From<Point3D<T, U>> for [T; 3] {
1636    fn from(p: Point3D<T, U>) -> Self {
1637        [p.x, p.y, p.z]
1638    }
1639}
1640
1641impl<T, U> From<[T; 3]> for Point3D<T, U> {
1642    fn from([x, y, z]: [T; 3]) -> Self {
1643        point3(x, y, z)
1644    }
1645}
1646
1647impl<T, U> From<Point3D<T, U>> for (T, T, T) {
1648    fn from(p: Point3D<T, U>) -> Self {
1649        (p.x, p.y, p.z)
1650    }
1651}
1652
1653impl<T, U> From<(T, T, T)> for Point3D<T, U> {
1654    fn from(tuple: (T, T, T)) -> Self {
1655        point3(tuple.0, tuple.1, tuple.2)
1656    }
1657}
1658
1659/// Shorthand for `Point2D::new(x, y)`.
1660#[inline]
1661pub const fn point2<T, U>(x: T, y: T) -> Point2D<T, U> {
1662    Point2D {
1663        x,
1664        y,
1665        _unit: PhantomData,
1666    }
1667}
1668
1669/// Shorthand for `Point3D::new(x, y)`.
1670#[inline]
1671pub const fn point3<T, U>(x: T, y: T, z: T) -> Point3D<T, U> {
1672    Point3D {
1673        x,
1674        y,
1675        z,
1676        _unit: PhantomData,
1677    }
1678}
1679
1680#[cfg(any(feature = "std", feature = "libm"))]
1681mod point3d_float {
1682    use super::{point3, Point3D};
1683    use crate::approxeq::ApproxEq;
1684    use core::ops::Sub;
1685    use num_traits::{real::Real, Float};
1686
1687    impl<T: Float, U> Point3D<T, U> {
1688        /// Returns `true` if all members are finite.
1689        #[inline]
1690        pub fn is_finite(self) -> bool {
1691            self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
1692        }
1693    }
1694
1695    impl<T: Real + Sub<T, Output = T>, U> Point3D<T, U> {
1696        #[inline]
1697        pub fn distance_to(self, other: Self) -> T {
1698            (self - other).length()
1699        }
1700    }
1701
1702    impl<T: ApproxEq<T>, U> ApproxEq<Point3D<T, U>> for Point3D<T, U> {
1703        #[inline]
1704        fn approx_epsilon() -> Self {
1705            point3(
1706                T::approx_epsilon(),
1707                T::approx_epsilon(),
1708                T::approx_epsilon(),
1709            )
1710        }
1711
1712        #[inline]
1713        fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
1714            self.x.approx_eq_eps(&other.x, &eps.x)
1715                && self.y.approx_eq_eps(&other.y, &eps.y)
1716                && self.z.approx_eq_eps(&other.z, &eps.z)
1717        }
1718    }
1719}
1720
1721#[cfg(test)]
1722#[cfg(any(feature = "std", feature = "libm"))]
1723mod point2d {
1724    use crate::default::Point2D;
1725    use crate::point2;
1726
1727    #[cfg(feature = "mint")]
1728    use mint;
1729
1730    #[test]
1731    pub fn test_min() {
1732        let p1 = Point2D::new(1.0, 3.0);
1733        let p2 = Point2D::new(2.0, 2.0);
1734
1735        let result = p1.min(p2);
1736
1737        assert_eq!(result, Point2D::new(1.0, 2.0));
1738    }
1739
1740    #[test]
1741    pub fn test_max() {
1742        let p1 = Point2D::new(1.0, 3.0);
1743        let p2 = Point2D::new(2.0, 2.0);
1744
1745        let result = p1.max(p2);
1746
1747        assert_eq!(result, Point2D::new(2.0, 3.0));
1748    }
1749
1750    #[cfg(feature = "mint")]
1751    #[test]
1752    pub fn test_mint() {
1753        let p1 = Point2D::new(1.0, 3.0);
1754        let pm: mint::Point2<_> = p1.into();
1755        let p2 = Point2D::from(pm);
1756
1757        assert_eq!(p1, p2);
1758    }
1759
1760    #[test]
1761    pub fn test_conv_vector() {
1762        for i in 0..100 {
1763            // We don't care about these values as long as they are not the same.
1764            let x = i as f32 * 0.012345;
1765            let y = i as f32 * 0.987654;
1766            let p: Point2D<f32> = point2(x, y);
1767            assert_eq!(p.to_vector().to_point(), p);
1768        }
1769    }
1770
1771    #[test]
1772    pub fn test_swizzling() {
1773        let p: Point2D<i32> = point2(1, 2);
1774        assert_eq!(p.yx(), point2(2, 1));
1775    }
1776
1777    #[test]
1778    pub fn test_distance_to() {
1779        let p1 = Point2D::new(1.0, 2.0);
1780        let p2 = Point2D::new(2.0, 2.0);
1781
1782        assert_eq!(p1.distance_to(p2), 1.0);
1783
1784        let p1 = Point2D::new(1.0, 2.0);
1785        let p2 = Point2D::new(1.0, 4.0);
1786
1787        assert_eq!(p1.distance_to(p2), 2.0);
1788    }
1789
1790    mod ops {
1791        use crate::default::Point2D;
1792        use crate::scale::Scale;
1793        use crate::{size2, vec2, Vector2D};
1794
1795        pub enum Mm {}
1796        pub enum Cm {}
1797
1798        pub type Point2DMm<T> = crate::Point2D<T, Mm>;
1799        pub type Point2DCm<T> = crate::Point2D<T, Cm>;
1800
1801        #[test]
1802        pub fn test_neg() {
1803            assert_eq!(-Point2D::new(1.0, 2.0), Point2D::new(-1.0, -2.0));
1804            assert_eq!(-Point2D::new(0.0, 0.0), Point2D::new(-0.0, -0.0));
1805            assert_eq!(-Point2D::new(-1.0, -2.0), Point2D::new(1.0, 2.0));
1806        }
1807
1808        #[test]
1809        pub fn test_add_size() {
1810            let p1 = Point2DMm::new(1.0, 2.0);
1811            let p2 = size2(3.0, 4.0);
1812
1813            let result = p1 + p2;
1814
1815            assert_eq!(result, Point2DMm::new(4.0, 6.0));
1816        }
1817
1818        #[test]
1819        pub fn test_add_assign_size() {
1820            let mut p1 = Point2DMm::new(1.0, 2.0);
1821
1822            p1 += size2(3.0, 4.0);
1823
1824            assert_eq!(p1, Point2DMm::new(4.0, 6.0));
1825        }
1826
1827        #[test]
1828        pub fn test_add_vec() {
1829            let p1 = Point2DMm::new(1.0, 2.0);
1830            let p2 = vec2(3.0, 4.0);
1831
1832            let result = p1 + p2;
1833
1834            assert_eq!(result, Point2DMm::new(4.0, 6.0));
1835        }
1836
1837        #[test]
1838        pub fn test_add_assign_vec() {
1839            let mut p1 = Point2DMm::new(1.0, 2.0);
1840
1841            p1 += vec2(3.0, 4.0);
1842
1843            assert_eq!(p1, Point2DMm::new(4.0, 6.0));
1844        }
1845
1846        #[test]
1847        pub fn test_sub() {
1848            let p1 = Point2DMm::new(1.0, 2.0);
1849            let p2 = Point2DMm::new(3.0, 4.0);
1850
1851            let result = p1 - p2;
1852
1853            assert_eq!(result, Vector2D::<_, Mm>::new(-2.0, -2.0));
1854        }
1855
1856        #[test]
1857        pub fn test_sub_size() {
1858            let p1 = Point2DMm::new(1.0, 2.0);
1859            let p2 = size2(3.0, 4.0);
1860
1861            let result = p1 - p2;
1862
1863            assert_eq!(result, Point2DMm::new(-2.0, -2.0));
1864        }
1865
1866        #[test]
1867        pub fn test_sub_assign_size() {
1868            let mut p1 = Point2DMm::new(1.0, 2.0);
1869
1870            p1 -= size2(3.0, 4.0);
1871
1872            assert_eq!(p1, Point2DMm::new(-2.0, -2.0));
1873        }
1874
1875        #[test]
1876        pub fn test_sub_vec() {
1877            let p1 = Point2DMm::new(1.0, 2.0);
1878            let p2 = vec2(3.0, 4.0);
1879
1880            let result = p1 - p2;
1881
1882            assert_eq!(result, Point2DMm::new(-2.0, -2.0));
1883        }
1884
1885        #[test]
1886        pub fn test_sub_assign_vec() {
1887            let mut p1 = Point2DMm::new(1.0, 2.0);
1888
1889            p1 -= vec2(3.0, 4.0);
1890
1891            assert_eq!(p1, Point2DMm::new(-2.0, -2.0));
1892        }
1893
1894        #[test]
1895        pub fn test_mul_scalar() {
1896            let p1: Point2D<f32> = Point2D::new(3.0, 5.0);
1897
1898            let result = p1 * 5.0;
1899
1900            assert_eq!(result, Point2D::new(15.0, 25.0));
1901        }
1902
1903        #[test]
1904        pub fn test_mul_assign_scalar() {
1905            let mut p1 = Point2D::new(3.0, 5.0);
1906
1907            p1 *= 5.0;
1908
1909            assert_eq!(p1, Point2D::new(15.0, 25.0));
1910        }
1911
1912        #[test]
1913        pub fn test_mul_scale() {
1914            let p1 = Point2DMm::new(1.0, 2.0);
1915            let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1916
1917            let result = p1 * cm_per_mm;
1918
1919            assert_eq!(result, Point2DCm::new(0.1, 0.2));
1920        }
1921
1922        #[test]
1923        pub fn test_mul_assign_scale() {
1924            let mut p1 = Point2DMm::new(1.0, 2.0);
1925            let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1926
1927            p1 *= scale;
1928
1929            assert_eq!(p1, Point2DMm::new(0.1, 0.2));
1930        }
1931
1932        #[test]
1933        pub fn test_div_scalar() {
1934            let p1: Point2D<f32> = Point2D::new(15.0, 25.0);
1935
1936            let result = p1 / 5.0;
1937
1938            assert_eq!(result, Point2D::new(3.0, 5.0));
1939        }
1940
1941        #[test]
1942        pub fn test_div_assign_scalar() {
1943            let mut p1: Point2D<f32> = Point2D::new(15.0, 25.0);
1944
1945            p1 /= 5.0;
1946
1947            assert_eq!(p1, Point2D::new(3.0, 5.0));
1948        }
1949
1950        #[test]
1951        pub fn test_div_scale() {
1952            let p1 = Point2DCm::new(0.1, 0.2);
1953            let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1954
1955            let result = p1 / cm_per_mm;
1956
1957            assert_eq!(result, Point2DMm::new(1.0, 2.0));
1958        }
1959
1960        #[test]
1961        pub fn test_div_assign_scale() {
1962            let mut p1 = Point2DMm::new(0.1, 0.2);
1963            let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1964
1965            p1 /= scale;
1966
1967            assert_eq!(p1, Point2DMm::new(1.0, 2.0));
1968        }
1969
1970        #[test]
1971        pub fn test_point_debug_formatting() {
1972            let n = 1.23456789;
1973            let p1 = Point2D::new(n, -n);
1974            let should_be = format!("({:.4}, {:.4})", n, -n);
1975
1976            let got = format!("{:.4?}", p1);
1977
1978            assert_eq!(got, should_be);
1979        }
1980    }
1981
1982    mod euclid {
1983        use crate::default::{Point2D, Size2D};
1984        use crate::point2;
1985
1986        #[test]
1987        pub fn test_rem_euclid() {
1988            let p = Point2D::new(7.0, -7.0);
1989            let s = Size2D::new(4.0, -4.0);
1990
1991            assert_eq!(p.rem_euclid(&s), point2(3.0, 1.0));
1992            assert_eq!((-p).rem_euclid(&s), point2(1.0, 3.0));
1993            assert_eq!(p.rem_euclid(&-s), point2(3.0, 1.0));
1994        }
1995
1996        #[test]
1997        pub fn test_div_euclid() {
1998            let p = Point2D::new(7.0, -7.0);
1999            let s = Size2D::new(4.0, -4.0);
2000
2001            assert_eq!(p.div_euclid(&s), point2(1.0, 2.0));
2002            assert_eq!((-p).div_euclid(&s), point2(-2.0, -1.0));
2003            assert_eq!(p.div_euclid(&-s), point2(-1.0, -2.0));
2004        }
2005    }
2006}
2007
2008#[cfg(test)]
2009#[cfg(any(feature = "std", feature = "libm"))]
2010mod point3d {
2011    use crate::default;
2012    use crate::default::Point3D;
2013    use crate::{point2, point3};
2014    #[cfg(feature = "mint")]
2015    use mint;
2016
2017    #[test]
2018    pub fn test_min() {
2019        let p1 = Point3D::new(1.0, 3.0, 5.0);
2020        let p2 = Point3D::new(2.0, 2.0, -1.0);
2021
2022        let result = p1.min(p2);
2023
2024        assert_eq!(result, Point3D::new(1.0, 2.0, -1.0));
2025    }
2026
2027    #[test]
2028    pub fn test_max() {
2029        let p1 = Point3D::new(1.0, 3.0, 5.0);
2030        let p2 = Point3D::new(2.0, 2.0, -1.0);
2031
2032        let result = p1.max(p2);
2033
2034        assert_eq!(result, Point3D::new(2.0, 3.0, 5.0));
2035    }
2036
2037    #[test]
2038    pub fn test_conv_vector() {
2039        use crate::point3;
2040        for i in 0..100 {
2041            // We don't care about these values as long as they are not the same.
2042            let x = i as f32 * 0.012345;
2043            let y = i as f32 * 0.987654;
2044            let z = x * y;
2045            let p: Point3D<f32> = point3(x, y, z);
2046            assert_eq!(p.to_vector().to_point(), p);
2047        }
2048    }
2049
2050    #[test]
2051    pub fn test_swizzling() {
2052        let p: default::Point3D<i32> = point3(1, 2, 3);
2053        assert_eq!(p.xy(), point2(1, 2));
2054        assert_eq!(p.xz(), point2(1, 3));
2055        assert_eq!(p.yz(), point2(2, 3));
2056    }
2057
2058    #[test]
2059    pub fn test_distance_to() {
2060        let p1 = Point3D::new(1.0, 2.0, 3.0);
2061        let p2 = Point3D::new(2.0, 2.0, 3.0);
2062
2063        assert_eq!(p1.distance_to(p2), 1.0);
2064
2065        let p1 = Point3D::new(1.0, 2.0, 3.0);
2066        let p2 = Point3D::new(1.0, 4.0, 3.0);
2067
2068        assert_eq!(p1.distance_to(p2), 2.0);
2069
2070        let p1 = Point3D::new(1.0, 2.0, 3.0);
2071        let p2 = Point3D::new(1.0, 2.0, 6.0);
2072
2073        assert_eq!(p1.distance_to(p2), 3.0);
2074    }
2075
2076    #[cfg(feature = "mint")]
2077    #[test]
2078    pub fn test_mint() {
2079        let p1 = Point3D::new(1.0, 3.0, 5.0);
2080        let pm: mint::Point3<_> = p1.into();
2081        let p2 = Point3D::from(pm);
2082
2083        assert_eq!(p1, p2);
2084    }
2085
2086    mod ops {
2087        use crate::default::Point3D;
2088        use crate::scale::Scale;
2089        use crate::{size3, vec3, Vector3D};
2090
2091        pub enum Mm {}
2092        pub enum Cm {}
2093
2094        pub type Point3DMm<T> = crate::Point3D<T, Mm>;
2095        pub type Point3DCm<T> = crate::Point3D<T, Cm>;
2096
2097        #[test]
2098        pub fn test_neg() {
2099            assert_eq!(-Point3D::new(1.0, 2.0, 3.0), Point3D::new(-1.0, -2.0, -3.0));
2100            assert_eq!(-Point3D::new(0.0, 0.0, 0.0), Point3D::new(-0.0, -0.0, -0.0));
2101            assert_eq!(-Point3D::new(-1.0, -2.0, -3.0), Point3D::new(1.0, 2.0, 3.0));
2102        }
2103
2104        #[test]
2105        pub fn test_add_size() {
2106            let p1 = Point3DMm::new(1.0, 2.0, 3.0);
2107            let p2 = size3(4.0, 5.0, 6.0);
2108
2109            let result = p1 + p2;
2110
2111            assert_eq!(result, Point3DMm::new(5.0, 7.0, 9.0));
2112        }
2113
2114        #[test]
2115        pub fn test_add_assign_size() {
2116            let mut p1 = Point3DMm::new(1.0, 2.0, 3.0);
2117
2118            p1 += size3(4.0, 5.0, 6.0);
2119
2120            assert_eq!(p1, Point3DMm::new(5.0, 7.0, 9.0));
2121        }
2122
2123        #[test]
2124        pub fn test_add_vec() {
2125            let p1 = Point3DMm::new(1.0, 2.0, 3.0);
2126            let p2 = vec3(4.0, 5.0, 6.0);
2127
2128            let result = p1 + p2;
2129
2130            assert_eq!(result, Point3DMm::new(5.0, 7.0, 9.0));
2131        }
2132
2133        #[test]
2134        pub fn test_add_assign_vec() {
2135            let mut p1 = Point3DMm::new(1.0, 2.0, 3.0);
2136
2137            p1 += vec3(4.0, 5.0, 6.0);
2138
2139            assert_eq!(p1, Point3DMm::new(5.0, 7.0, 9.0));
2140        }
2141
2142        #[test]
2143        pub fn test_sub() {
2144            let p1 = Point3DMm::new(1.0, 2.0, 3.0);
2145            let p2 = Point3DMm::new(4.0, 5.0, 6.0);
2146
2147            let result = p1 - p2;
2148
2149            assert_eq!(result, Vector3D::<_, Mm>::new(-3.0, -3.0, -3.0));
2150        }
2151
2152        #[test]
2153        pub fn test_sub_size() {
2154            let p1 = Point3DMm::new(1.0, 2.0, 3.0);
2155            let p2 = size3(4.0, 5.0, 6.0);
2156
2157            let result = p1 - p2;
2158
2159            assert_eq!(result, Point3DMm::new(-3.0, -3.0, -3.0));
2160        }
2161
2162        #[test]
2163        pub fn test_sub_assign_size() {
2164            let mut p1 = Point3DMm::new(1.0, 2.0, 3.0);
2165
2166            p1 -= size3(4.0, 5.0, 6.0);
2167
2168            assert_eq!(p1, Point3DMm::new(-3.0, -3.0, -3.0));
2169        }
2170
2171        #[test]
2172        pub fn test_sub_vec() {
2173            let p1 = Point3DMm::new(1.0, 2.0, 3.0);
2174            let p2 = vec3(4.0, 5.0, 6.0);
2175
2176            let result = p1 - p2;
2177
2178            assert_eq!(result, Point3DMm::new(-3.0, -3.0, -3.0));
2179        }
2180
2181        #[test]
2182        pub fn test_sub_assign_vec() {
2183            let mut p1 = Point3DMm::new(1.0, 2.0, 3.0);
2184
2185            p1 -= vec3(4.0, 5.0, 6.0);
2186
2187            assert_eq!(p1, Point3DMm::new(-3.0, -3.0, -3.0));
2188        }
2189
2190        #[test]
2191        pub fn test_mul_scalar() {
2192            let p1: Point3D<f32> = Point3D::new(3.0, 5.0, 7.0);
2193
2194            let result = p1 * 5.0;
2195
2196            assert_eq!(result, Point3D::new(15.0, 25.0, 35.0));
2197        }
2198
2199        #[test]
2200        pub fn test_mul_assign_scalar() {
2201            let mut p1: Point3D<f32> = Point3D::new(3.0, 5.0, 7.0);
2202
2203            p1 *= 5.0;
2204
2205            assert_eq!(p1, Point3D::new(15.0, 25.0, 35.0));
2206        }
2207
2208        #[test]
2209        pub fn test_mul_scale() {
2210            let p1 = Point3DMm::new(1.0, 2.0, 3.0);
2211            let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
2212
2213            let result = p1 * cm_per_mm;
2214
2215            assert_eq!(result, Point3DCm::new(0.1, 0.2, 0.3));
2216        }
2217
2218        #[test]
2219        pub fn test_mul_assign_scale() {
2220            let mut p1 = Point3DMm::new(1.0, 2.0, 3.0);
2221            let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
2222
2223            p1 *= scale;
2224
2225            assert_eq!(p1, Point3DMm::new(0.1, 0.2, 0.3));
2226        }
2227
2228        #[test]
2229        pub fn test_div_scalar() {
2230            let p1: Point3D<f32> = Point3D::new(15.0, 25.0, 35.0);
2231
2232            let result = p1 / 5.0;
2233
2234            assert_eq!(result, Point3D::new(3.0, 5.0, 7.0));
2235        }
2236
2237        #[test]
2238        pub fn test_div_assign_scalar() {
2239            let mut p1: Point3D<f32> = Point3D::new(15.0, 25.0, 35.0);
2240
2241            p1 /= 5.0;
2242
2243            assert_eq!(p1, Point3D::new(3.0, 5.0, 7.0));
2244        }
2245
2246        #[test]
2247        pub fn test_div_scale() {
2248            let p1 = Point3DCm::new(0.1, 0.2, 0.3);
2249            let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
2250
2251            let result = p1 / cm_per_mm;
2252
2253            assert_eq!(result, Point3DMm::new(1.0, 2.0, 3.0));
2254        }
2255
2256        #[test]
2257        pub fn test_div_assign_scale() {
2258            let mut p1 = Point3DMm::new(0.1, 0.2, 0.3);
2259            let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
2260
2261            p1 /= scale;
2262
2263            assert_eq!(p1, Point3DMm::new(1.0, 2.0, 3.0));
2264        }
2265    }
2266
2267    mod euclid {
2268        use crate::default::{Point3D, Size3D};
2269        use crate::point3;
2270
2271        #[test]
2272        pub fn test_rem_euclid() {
2273            let p = Point3D::new(7.0, -7.0, 0.0);
2274            let s = Size3D::new(4.0, -4.0, 12.0);
2275
2276            assert_eq!(p.rem_euclid(&s), point3(3.0, 1.0, 0.0));
2277            assert_eq!((-p).rem_euclid(&s), point3(1.0, 3.0, 0.0));
2278            assert_eq!(p.rem_euclid(&-s), point3(3.0, 1.0, 0.0));
2279        }
2280
2281        #[test]
2282        pub fn test_div_euclid() {
2283            let p = Point3D::new(7.0, -7.0, 0.0);
2284            let s = Size3D::new(4.0, -4.0, 12.0);
2285
2286            assert_eq!(p.div_euclid(&s), point3(1.0, 2.0, 0.0));
2287            assert_eq!((-p).div_euclid(&s), point3(-2.0, -1.0, 0.0));
2288            assert_eq!(p.div_euclid(&-s), point3(-1.0, -2.0, 0.0));
2289        }
2290    }
2291}