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