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