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