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