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