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