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