1use super::UnknownUnit;
11use crate::approxord::{max, min};
12use crate::length::Length;
13use crate::num::*;
14use crate::scale::Scale;
15use crate::vector::{vec2, BoolVector2D, Vector2D};
16use crate::vector::{vec3, BoolVector3D, Vector3D};
17#[cfg(feature = "mint")]
18use mint;
19
20use core::cmp::{Eq, PartialEq};
21use core::fmt;
22use core::hash::Hash;
23use core::marker::PhantomData;
24use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
25use num_traits::{NumCast, Signed};
26#[cfg(feature = "serde")]
27use serde;
28
29#[repr(C)]
31pub struct Size2D<T, U> {
32 pub width: T,
34 pub height: T,
36 #[doc(hidden)]
37 pub _unit: PhantomData<U>,
38}
39
40impl<T: Copy, U> Copy for Size2D<T, U> {}
41
42impl<T: Clone, U> Clone for Size2D<T, U> {
43 fn clone(&self) -> Self {
44 Size2D {
45 width: self.width.clone(),
46 height: self.height.clone(),
47 _unit: PhantomData,
48 }
49 }
50}
51
52#[cfg(feature = "serde")]
53impl<'de, T, U> serde::Deserialize<'de> for Size2D<T, U>
54where
55 T: serde::Deserialize<'de>,
56{
57 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
59 where
60 D: serde::Deserializer<'de>,
61 {
62 let (width, height) = serde::Deserialize::deserialize(deserializer)?;
63 Ok(Size2D {
64 width,
65 height,
66 _unit: PhantomData,
67 })
68 }
69}
70
71#[cfg(feature = "serde")]
72impl<T, U> serde::Serialize for Size2D<T, U>
73where
74 T: serde::Serialize,
75{
76 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: serde::Serializer,
80 {
81 (&self.width, &self.height).serialize(serializer)
82 }
83}
84
85impl<T, U> Eq for Size2D<T, U> where T: Eq {}
86
87impl<T, U> PartialEq for Size2D<T, U>
88where
89 T: PartialEq,
90{
91 fn eq(&self, other: &Self) -> bool {
92 self.width == other.width && self.height == other.height
93 }
94}
95
96impl<T, U> Hash for Size2D<T, U>
97where
98 T: Hash,
99{
100 fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
101 self.width.hash(h);
102 self.height.hash(h);
103 }
104}
105
106impl<T: fmt::Debug, U> fmt::Debug for Size2D<T, U> {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 fmt::Debug::fmt(&self.width, f)?;
109 write!(f, "x")?;
110 fmt::Debug::fmt(&self.height, f)
111 }
112}
113
114impl<T: Default, U> Default for Size2D<T, U> {
115 fn default() -> Self {
116 Size2D::new(Default::default(), Default::default())
117 }
118}
119
120impl<T, U> Size2D<T, U> {
121 #[inline]
125 pub fn zero() -> Self
126 where
127 T: Zero,
128 {
129 Size2D::new(Zero::zero(), Zero::zero())
130 }
131
132 #[inline]
134 pub const fn new(width: T, height: T) -> Self {
135 Size2D {
136 width,
137 height,
138 _unit: PhantomData,
139 }
140 }
141 #[inline]
143 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
144 Size2D::new(width.0, height.0)
145 }
146
147 #[inline]
149 pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
150 Size2D::new(p.width, p.height)
151 }
152}
153
154impl<T: Copy, U> Size2D<T, U> {
155 #[inline]
157 pub fn to_array(self) -> [T; 2] {
158 [self.width, self.height]
159 }
160
161 #[inline]
163 pub fn to_tuple(self) -> (T, T) {
164 (self.width, self.height)
165 }
166
167 #[inline]
169 pub fn to_vector(self) -> Vector2D<T, U> {
170 vec2(self.width, self.height)
171 }
172
173 #[inline]
175 pub fn to_untyped(self) -> Size2D<T, UnknownUnit> {
176 self.cast_unit()
177 }
178
179 #[inline]
181 pub fn cast_unit<V>(self) -> Size2D<T, V> {
182 Size2D::new(self.width, self.height)
183 }
184
185 #[inline]
196 #[must_use]
197 pub fn round(self) -> Self
198 where
199 T: Round,
200 {
201 Size2D::new(self.width.round(), self.height.round())
202 }
203
204 #[inline]
215 #[must_use]
216 pub fn ceil(self) -> Self
217 where
218 T: Ceil,
219 {
220 Size2D::new(self.width.ceil(), self.height.ceil())
221 }
222
223 #[inline]
234 #[must_use]
235 pub fn floor(self) -> Self
236 where
237 T: Floor,
238 {
239 Size2D::new(self.width.floor(), self.height.floor())
240 }
241
242 pub fn area(self) -> T::Output
244 where
245 T: Mul,
246 {
247 self.width * self.height
248 }
249
250 #[inline]
268 pub fn lerp(self, other: Self, t: T) -> Self
269 where
270 T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
271 {
272 let one_t = T::one() - t;
273 self * one_t + other * t
274 }
275}
276
277impl<T: NumCast + Copy, U> Size2D<T, U> {
278 #[inline]
284 pub fn cast<NewT: NumCast>(self) -> Size2D<NewT, U> {
285 self.try_cast().unwrap()
286 }
287
288 pub fn try_cast<NewT: NumCast>(self) -> Option<Size2D<NewT, U>> {
294 match (NumCast::from(self.width), NumCast::from(self.height)) {
295 (Some(w), Some(h)) => Some(Size2D::new(w, h)),
296 _ => None,
297 }
298 }
299
300 #[inline]
304 pub fn to_f32(self) -> Size2D<f32, U> {
305 self.cast()
306 }
307
308 #[inline]
310 pub fn to_f64(self) -> Size2D<f64, U> {
311 self.cast()
312 }
313
314 #[inline]
320 pub fn to_usize(self) -> Size2D<usize, U> {
321 self.cast()
322 }
323
324 #[inline]
330 pub fn to_u32(self) -> Size2D<u32, U> {
331 self.cast()
332 }
333
334 #[inline]
340 pub fn to_u64(self) -> Size2D<u64, U> {
341 self.cast()
342 }
343
344 #[inline]
350 pub fn to_i32(self) -> Size2D<i32, U> {
351 self.cast()
352 }
353
354 #[inline]
360 pub fn to_i64(self) -> Size2D<i64, U> {
361 self.cast()
362 }
363}
364
365impl<T: Signed, U> Size2D<T, U> {
366 pub fn abs(self) -> Self {
372 size2(self.width.abs(), self.height.abs())
373 }
374
375 pub fn is_positive(self) -> bool {
377 self.width.is_positive() && self.height.is_positive()
378 }
379}
380
381impl<T: PartialOrd, U> Size2D<T, U> {
382 #[inline]
384 pub fn min(self, other: Self) -> Self {
385 size2(min(self.width, other.width), min(self.height, other.height))
386 }
387
388 #[inline]
390 pub fn max(self, other: Self) -> Self {
391 size2(max(self.width, other.width), max(self.height, other.height))
392 }
393
394 #[inline]
399 pub fn clamp(self, start: Self, end: Self) -> Self
400 where
401 T: Copy,
402 {
403 self.max(start).min(end)
404 }
405
406 pub fn greater_than(self, other: Self) -> BoolVector2D {
408 BoolVector2D {
409 x: self.width > other.width,
410 y: self.height > other.height,
411 }
412 }
413
414 pub fn lower_than(self, other: Self) -> BoolVector2D {
416 BoolVector2D {
417 x: self.width < other.width,
418 y: self.height < other.height,
419 }
420 }
421
422 pub fn is_empty(self) -> bool
424 where
425 T: Zero,
426 {
427 let zero = T::zero();
428 !(self.width > zero && self.height > zero)
431 }
432}
433
434impl<T: PartialEq, U> Size2D<T, U> {
435 pub fn equal(self, other: Self) -> BoolVector2D {
437 BoolVector2D {
438 x: self.width == other.width,
439 y: self.height == other.height,
440 }
441 }
442
443 pub fn not_equal(self, other: Self) -> BoolVector2D {
445 BoolVector2D {
446 x: self.width != other.width,
447 y: self.height != other.height,
448 }
449 }
450}
451
452impl<T: Round, U> Round for Size2D<T, U> {
453 #[inline]
455 fn round(self) -> Self {
456 self.round()
457 }
458}
459
460impl<T: Ceil, U> Ceil for Size2D<T, U> {
461 #[inline]
463 fn ceil(self) -> Self {
464 self.ceil()
465 }
466}
467
468impl<T: Floor, U> Floor for Size2D<T, U> {
469 #[inline]
471 fn floor(self) -> Self {
472 self.floor()
473 }
474}
475
476impl<T: Zero, U> Zero for Size2D<T, U> {
477 #[inline]
478 fn zero() -> Self {
479 Size2D::new(Zero::zero(), Zero::zero())
480 }
481}
482
483impl<T: Neg, U> Neg for Size2D<T, U> {
484 type Output = Size2D<T::Output, U>;
485
486 #[inline]
487 fn neg(self) -> Self::Output {
488 Size2D::new(-self.width, -self.height)
489 }
490}
491
492impl<T: Add, U> Add for Size2D<T, U> {
493 type Output = Size2D<T::Output, U>;
494
495 #[inline]
496 fn add(self, other: Self) -> Self::Output {
497 Size2D::new(self.width + other.width, self.height + other.height)
498 }
499}
500
501impl<T: AddAssign, U> AddAssign for Size2D<T, U> {
502 #[inline]
503 fn add_assign(&mut self, other: Self) {
504 self.width += other.width;
505 self.height += other.height;
506 }
507}
508
509impl<T: Sub, U> Sub for Size2D<T, U> {
510 type Output = Size2D<T::Output, U>;
511
512 #[inline]
513 fn sub(self, other: Self) -> Self::Output {
514 Size2D::new(self.width - other.width, self.height - other.height)
515 }
516}
517
518impl<T: SubAssign, U> SubAssign for Size2D<T, U> {
519 #[inline]
520 fn sub_assign(&mut self, other: Self) {
521 self.width -= other.width;
522 self.height -= other.height;
523 }
524}
525
526impl<T: Copy + Mul, U> Mul<T> for Size2D<T, U> {
527 type Output = Size2D<T::Output, U>;
528
529 #[inline]
530 fn mul(self, scale: T) -> Self::Output {
531 Size2D::new(self.width * scale, self.height * scale)
532 }
533}
534
535impl<T: Copy + MulAssign, U> MulAssign<T> for Size2D<T, U> {
536 #[inline]
537 fn mul_assign(&mut self, other: T) {
538 self.width *= other;
539 self.height *= other;
540 }
541}
542
543impl<T: Copy + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size2D<T, U1> {
544 type Output = Size2D<T::Output, U2>;
545
546 #[inline]
547 fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
548 Size2D::new(self.width * scale.0, self.height * scale.0)
549 }
550}
551
552impl<T: Copy + MulAssign, U> MulAssign<Scale<T, U, U>> for Size2D<T, U> {
553 #[inline]
554 fn mul_assign(&mut self, other: Scale<T, U, U>) {
555 *self *= other.0;
556 }
557}
558
559impl<T: Copy + Div, U> Div<T> for Size2D<T, U> {
560 type Output = Size2D<T::Output, U>;
561
562 #[inline]
563 fn div(self, scale: T) -> Self::Output {
564 Size2D::new(self.width / scale, self.height / scale)
565 }
566}
567
568impl<T: Copy + DivAssign, U> DivAssign<T> for Size2D<T, U> {
569 #[inline]
570 fn div_assign(&mut self, other: T) {
571 self.width /= other;
572 self.height /= other;
573 }
574}
575
576impl<T: Copy + Div, U1, U2> Div<Scale<T, U1, U2>> for Size2D<T, U2> {
577 type Output = Size2D<T::Output, U1>;
578
579 #[inline]
580 fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
581 Size2D::new(self.width / scale.0, self.height / scale.0)
582 }
583}
584
585impl<T: Copy + DivAssign, U> DivAssign<Scale<T, U, U>> for Size2D<T, U> {
586 #[inline]
587 fn div_assign(&mut self, other: Scale<T, U, U>) {
588 *self /= other.0;
589 }
590}
591
592#[inline]
594pub const fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
595 Size2D::new(w, h)
596}
597
598#[cfg(feature = "mint")]
599impl<T, U> From<mint::Vector2<T>> for Size2D<T, U> {
600 #[inline]
601 fn from(v: mint::Vector2<T>) -> Self {
602 Size2D {
603 width: v.x,
604 height: v.y,
605 _unit: PhantomData,
606 }
607 }
608}
609#[cfg(feature = "mint")]
610impl<T, U> Into<mint::Vector2<T>> for Size2D<T, U> {
611 #[inline]
612 fn into(self) -> mint::Vector2<T> {
613 mint::Vector2 {
614 x: self.width,
615 y: self.height,
616 }
617 }
618}
619
620impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
621 #[inline]
622 fn from(v: Vector2D<T, U>) -> Self {
623 size2(v.x, v.y)
624 }
625}
626
627impl<T, U> Into<[T; 2]> for Size2D<T, U> {
628 #[inline]
629 fn into(self) -> [T; 2] {
630 [self.width, self.height]
631 }
632}
633
634impl<T, U> From<[T; 2]> for Size2D<T, U> {
635 #[inline]
636 fn from([w, h]: [T; 2]) -> Self {
637 size2(w, h)
638 }
639}
640
641impl<T, U> Into<(T, T)> for Size2D<T, U> {
642 #[inline]
643 fn into(self) -> (T, T) {
644 (self.width, self.height)
645 }
646}
647
648impl<T, U> From<(T, T)> for Size2D<T, U> {
649 #[inline]
650 fn from(tuple: (T, T)) -> Self {
651 size2(tuple.0, tuple.1)
652 }
653}
654
655#[cfg(test)]
656mod size2d {
657 use crate::default::Size2D;
658 #[cfg(feature = "mint")]
659 use mint;
660
661 #[test]
662 pub fn test_area() {
663 let p = Size2D::new(1.5, 2.0);
664 assert_eq!(p.area(), 3.0);
665 }
666
667 #[cfg(feature = "mint")]
668 #[test]
669 pub fn test_mint() {
670 let s1 = Size2D::new(1.0, 2.0);
671 let sm: mint::Vector2<_> = s1.into();
672 let s2 = Size2D::from(sm);
673
674 assert_eq!(s1, s2);
675 }
676
677 mod ops {
678 use crate::default::Size2D;
679 use crate::scale::Scale;
680
681 pub enum Mm {}
682 pub enum Cm {}
683
684 pub type Size2DMm<T> = crate::Size2D<T, Mm>;
685 pub type Size2DCm<T> = crate::Size2D<T, Cm>;
686
687 #[test]
688 pub fn test_neg() {
689 assert_eq!(-Size2D::new(1.0, 2.0), Size2D::new(-1.0, -2.0));
690 assert_eq!(-Size2D::new(0.0, 0.0), Size2D::new(-0.0, -0.0));
691 assert_eq!(-Size2D::new(-1.0, -2.0), Size2D::new(1.0, 2.0));
692 }
693
694 #[test]
695 pub fn test_add() {
696 let s1 = Size2D::new(1.0, 2.0);
697 let s2 = Size2D::new(3.0, 4.0);
698 assert_eq!(s1 + s2, Size2D::new(4.0, 6.0));
699
700 let s1 = Size2D::new(1.0, 2.0);
701 let s2 = Size2D::new(0.0, 0.0);
702 assert_eq!(s1 + s2, Size2D::new(1.0, 2.0));
703
704 let s1 = Size2D::new(1.0, 2.0);
705 let s2 = Size2D::new(-3.0, -4.0);
706 assert_eq!(s1 + s2, Size2D::new(-2.0, -2.0));
707
708 let s1 = Size2D::new(0.0, 0.0);
709 let s2 = Size2D::new(0.0, 0.0);
710 assert_eq!(s1 + s2, Size2D::new(0.0, 0.0));
711 }
712
713 #[test]
714 pub fn test_add_assign() {
715 let mut s = Size2D::new(1.0, 2.0);
716 s += Size2D::new(3.0, 4.0);
717 assert_eq!(s, Size2D::new(4.0, 6.0));
718
719 let mut s = Size2D::new(1.0, 2.0);
720 s += Size2D::new(0.0, 0.0);
721 assert_eq!(s, Size2D::new(1.0, 2.0));
722
723 let mut s = Size2D::new(1.0, 2.0);
724 s += Size2D::new(-3.0, -4.0);
725 assert_eq!(s, Size2D::new(-2.0, -2.0));
726
727 let mut s = Size2D::new(0.0, 0.0);
728 s += Size2D::new(0.0, 0.0);
729 assert_eq!(s, Size2D::new(0.0, 0.0));
730 }
731
732 #[test]
733 pub fn test_sub() {
734 let s1 = Size2D::new(1.0, 2.0);
735 let s2 = Size2D::new(3.0, 4.0);
736 assert_eq!(s1 - s2, Size2D::new(-2.0, -2.0));
737
738 let s1 = Size2D::new(1.0, 2.0);
739 let s2 = Size2D::new(0.0, 0.0);
740 assert_eq!(s1 - s2, Size2D::new(1.0, 2.0));
741
742 let s1 = Size2D::new(1.0, 2.0);
743 let s2 = Size2D::new(-3.0, -4.0);
744 assert_eq!(s1 - s2, Size2D::new(4.0, 6.0));
745
746 let s1 = Size2D::new(0.0, 0.0);
747 let s2 = Size2D::new(0.0, 0.0);
748 assert_eq!(s1 - s2, Size2D::new(0.0, 0.0));
749 }
750
751 #[test]
752 pub fn test_sub_assign() {
753 let mut s = Size2D::new(1.0, 2.0);
754 s -= Size2D::new(3.0, 4.0);
755 assert_eq!(s, Size2D::new(-2.0, -2.0));
756
757 let mut s = Size2D::new(1.0, 2.0);
758 s -= Size2D::new(0.0, 0.0);
759 assert_eq!(s, Size2D::new(1.0, 2.0));
760
761 let mut s = Size2D::new(1.0, 2.0);
762 s -= Size2D::new(-3.0, -4.0);
763 assert_eq!(s, Size2D::new(4.0, 6.0));
764
765 let mut s = Size2D::new(0.0, 0.0);
766 s -= Size2D::new(0.0, 0.0);
767 assert_eq!(s, Size2D::new(0.0, 0.0));
768 }
769
770 #[test]
771 pub fn test_mul_scalar() {
772 let s1: Size2D<f32> = Size2D::new(3.0, 5.0);
773
774 let result = s1 * 5.0;
775
776 assert_eq!(result, Size2D::new(15.0, 25.0));
777 }
778
779 #[test]
780 pub fn test_mul_assign_scalar() {
781 let mut s1 = Size2D::new(3.0, 5.0);
782
783 s1 *= 5.0;
784
785 assert_eq!(s1, Size2D::new(15.0, 25.0));
786 }
787
788 #[test]
789 pub fn test_mul_scale() {
790 let s1 = Size2DMm::new(1.0, 2.0);
791 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
792
793 let result = s1 * cm_per_mm;
794
795 assert_eq!(result, Size2DCm::new(0.1, 0.2));
796 }
797
798 #[test]
799 pub fn test_mul_assign_scale() {
800 let mut s1 = Size2DMm::new(1.0, 2.0);
801 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
802
803 s1 *= scale;
804
805 assert_eq!(s1, Size2DMm::new(0.1, 0.2));
806 }
807
808 #[test]
809 pub fn test_div_scalar() {
810 let s1: Size2D<f32> = Size2D::new(15.0, 25.0);
811
812 let result = s1 / 5.0;
813
814 assert_eq!(result, Size2D::new(3.0, 5.0));
815 }
816
817 #[test]
818 pub fn test_div_assign_scalar() {
819 let mut s1: Size2D<f32> = Size2D::new(15.0, 25.0);
820
821 s1 /= 5.0;
822
823 assert_eq!(s1, Size2D::new(3.0, 5.0));
824 }
825
826 #[test]
827 pub fn test_div_scale() {
828 let s1 = Size2DCm::new(0.1, 0.2);
829 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
830
831 let result = s1 / cm_per_mm;
832
833 assert_eq!(result, Size2DMm::new(1.0, 2.0));
834 }
835
836 #[test]
837 pub fn test_div_assign_scale() {
838 let mut s1 = Size2DMm::new(0.1, 0.2);
839 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
840
841 s1 /= scale;
842
843 assert_eq!(s1, Size2DMm::new(1.0, 2.0));
844 }
845
846 #[test]
847 pub fn test_nan_empty() {
848 use std::f32::NAN;
849 assert!(Size2D::new(NAN, 2.0).is_empty());
850 assert!(Size2D::new(0.0, NAN).is_empty());
851 assert!(Size2D::new(NAN, -2.0).is_empty());
852 }
853 }
854}
855
856#[repr(C)]
858pub struct Size3D<T, U> {
859 pub width: T,
861 pub height: T,
863 pub depth: T,
865 #[doc(hidden)]
866 pub _unit: PhantomData<U>,
867}
868
869impl<T: Copy, U> Copy for Size3D<T, U> {}
870
871impl<T: Clone, U> Clone for Size3D<T, U> {
872 fn clone(&self) -> Self {
873 Size3D {
874 width: self.width.clone(),
875 height: self.height.clone(),
876 depth: self.depth.clone(),
877 _unit: PhantomData,
878 }
879 }
880}
881
882#[cfg(feature = "serde")]
883impl<'de, T, U> serde::Deserialize<'de> for Size3D<T, U>
884where
885 T: serde::Deserialize<'de>,
886{
887 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
888 where
889 D: serde::Deserializer<'de>,
890 {
891 let (width, height, depth) = serde::Deserialize::deserialize(deserializer)?;
892 Ok(Size3D {
893 width,
894 height,
895 depth,
896 _unit: PhantomData,
897 })
898 }
899}
900
901#[cfg(feature = "serde")]
902impl<T, U> serde::Serialize for Size3D<T, U>
903where
904 T: serde::Serialize,
905{
906 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
907 where
908 S: serde::Serializer,
909 {
910 (&self.width, &self.height, &self.depth).serialize(serializer)
911 }
912}
913
914impl<T, U> Eq for Size3D<T, U> where T: Eq {}
915
916impl<T, U> PartialEq for Size3D<T, U>
917where
918 T: PartialEq,
919{
920 fn eq(&self, other: &Self) -> bool {
921 self.width == other.width && self.height == other.height && self.depth == other.depth
922 }
923}
924
925impl<T, U> Hash for Size3D<T, U>
926where
927 T: Hash,
928{
929 fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
930 self.width.hash(h);
931 self.height.hash(h);
932 self.depth.hash(h);
933 }
934}
935
936impl<T: fmt::Debug, U> fmt::Debug for Size3D<T, U> {
937 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
938 fmt::Debug::fmt(&self.width, f)?;
939 write!(f, "x")?;
940 fmt::Debug::fmt(&self.height, f)?;
941 write!(f, "x")?;
942 fmt::Debug::fmt(&self.depth, f)
943 }
944}
945
946impl<T: Default, U> Default for Size3D<T, U> {
947 fn default() -> Self {
948 Size3D::new(Default::default(), Default::default(), Default::default())
949 }
950}
951
952impl<T, U> Size3D<T, U> {
953 pub fn zero() -> Self
957 where
958 T: Zero,
959 {
960 Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
961 }
962
963 #[inline]
965 pub const fn new(width: T, height: T, depth: T) -> Self {
966 Size3D {
967 width,
968 height,
969 depth,
970 _unit: PhantomData,
971 }
972 }
973
974 #[inline]
976 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
977 Size3D::new(width.0, height.0, depth.0)
978 }
979
980 #[inline]
982 pub fn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
983 Size3D::new(p.width, p.height, p.depth)
984 }
985}
986
987impl<T: Copy, U> Size3D<T, U> {
988 #[inline]
990 pub fn to_array(self) -> [T; 3] {
991 [self.width, self.height, self.depth]
992 }
993
994 #[inline]
996 pub fn to_tuple(self) -> (T, T, T) {
997 (self.width, self.height, self.depth)
998 }
999
1000 #[inline]
1002 pub fn to_vector(self) -> Vector3D<T, U> {
1003 vec3(self.width, self.height, self.depth)
1004 }
1005
1006 #[inline]
1008 pub fn to_untyped(self) -> Size3D<T, UnknownUnit> {
1009 self.cast_unit()
1010 }
1011
1012 #[inline]
1014 pub fn cast_unit<V>(self) -> Size3D<T, V> {
1015 Size3D::new(self.width, self.height, self.depth)
1016 }
1017
1018 #[inline]
1029 #[must_use]
1030 pub fn round(self) -> Self
1031 where
1032 T: Round,
1033 {
1034 Size3D::new(self.width.round(), self.height.round(), self.depth.round())
1035 }
1036
1037 #[inline]
1048 #[must_use]
1049 pub fn ceil(self) -> Self
1050 where
1051 T: Ceil,
1052 {
1053 Size3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
1054 }
1055
1056 #[inline]
1067 #[must_use]
1068 pub fn floor(self) -> Self
1069 where
1070 T: Floor,
1071 {
1072 Size3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
1073 }
1074
1075 pub fn volume(self) -> T
1077 where
1078 T: Mul<Output = T>,
1079 {
1080 self.width * self.height * self.depth
1081 }
1082
1083 #[inline]
1101 pub fn lerp(self, other: Self, t: T) -> Self
1102 where
1103 T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
1104 {
1105 let one_t = T::one() - t;
1106 self * one_t + other * t
1107 }
1108}
1109
1110impl<T: NumCast + Copy, U> Size3D<T, U> {
1111 #[inline]
1117 pub fn cast<NewT: NumCast>(self) -> Size3D<NewT, U> {
1118 self.try_cast().unwrap()
1119 }
1120
1121 pub fn try_cast<NewT: NumCast>(self) -> Option<Size3D<NewT, U>> {
1127 match (
1128 NumCast::from(self.width),
1129 NumCast::from(self.height),
1130 NumCast::from(self.depth),
1131 ) {
1132 (Some(w), Some(h), Some(d)) => Some(Size3D::new(w, h, d)),
1133 _ => None,
1134 }
1135 }
1136
1137 #[inline]
1141 pub fn to_f32(self) -> Size3D<f32, U> {
1142 self.cast()
1143 }
1144
1145 #[inline]
1147 pub fn to_f64(self) -> Size3D<f64, U> {
1148 self.cast()
1149 }
1150
1151 #[inline]
1157 pub fn to_usize(self) -> Size3D<usize, U> {
1158 self.cast()
1159 }
1160
1161 #[inline]
1167 pub fn to_u32(self) -> Size3D<u32, U> {
1168 self.cast()
1169 }
1170
1171 #[inline]
1177 pub fn to_i32(self) -> Size3D<i32, U> {
1178 self.cast()
1179 }
1180
1181 #[inline]
1187 pub fn to_i64(self) -> Size3D<i64, U> {
1188 self.cast()
1189 }
1190}
1191
1192impl<T: Signed, U> Size3D<T, U> {
1193 pub fn abs(self) -> Self {
1199 size3(self.width.abs(), self.height.abs(), self.depth.abs())
1200 }
1201
1202 pub fn is_positive(self) -> bool {
1204 self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
1205 }
1206}
1207
1208impl<T: PartialOrd, U> Size3D<T, U> {
1209 #[inline]
1211 pub fn min(self, other: Self) -> Self {
1212 size3(
1213 min(self.width, other.width),
1214 min(self.height, other.height),
1215 min(self.depth, other.depth),
1216 )
1217 }
1218
1219 #[inline]
1221 pub fn max(self, other: Self) -> Self {
1222 size3(
1223 max(self.width, other.width),
1224 max(self.height, other.height),
1225 max(self.depth, other.depth),
1226 )
1227 }
1228
1229 #[inline]
1234 pub fn clamp(self, start: Self, end: Self) -> Self
1235 where
1236 T: Copy,
1237 {
1238 self.max(start).min(end)
1239 }
1240
1241 pub fn greater_than(self, other: Self) -> BoolVector3D {
1243 BoolVector3D {
1244 x: self.width > other.width,
1245 y: self.height > other.height,
1246 z: self.depth > other.depth,
1247 }
1248 }
1249
1250 pub fn lower_than(self, other: Self) -> BoolVector3D {
1252 BoolVector3D {
1253 x: self.width < other.width,
1254 y: self.height < other.height,
1255 z: self.depth < other.depth,
1256 }
1257 }
1258
1259 pub fn is_empty(self) -> bool
1261 where
1262 T: Zero,
1263 {
1264 let zero = T::zero();
1265 !(self.width > zero && self.height > zero && self.depth <= zero)
1266 }
1267}
1268
1269impl<T: PartialEq, U> Size3D<T, U> {
1270 pub fn equal(self, other: Self) -> BoolVector3D {
1272 BoolVector3D {
1273 x: self.width == other.width,
1274 y: self.height == other.height,
1275 z: self.depth == other.depth,
1276 }
1277 }
1278
1279 pub fn not_equal(self, other: Self) -> BoolVector3D {
1281 BoolVector3D {
1282 x: self.width != other.width,
1283 y: self.height != other.height,
1284 z: self.depth != other.depth,
1285 }
1286 }
1287}
1288
1289impl<T: Round, U> Round for Size3D<T, U> {
1290 #[inline]
1292 fn round(self) -> Self {
1293 self.round()
1294 }
1295}
1296
1297impl<T: Ceil, U> Ceil for Size3D<T, U> {
1298 #[inline]
1300 fn ceil(self) -> Self {
1301 self.ceil()
1302 }
1303}
1304
1305impl<T: Floor, U> Floor for Size3D<T, U> {
1306 #[inline]
1308 fn floor(self) -> Self {
1309 self.floor()
1310 }
1311}
1312
1313impl<T: Zero, U> Zero for Size3D<T, U> {
1314 #[inline]
1315 fn zero() -> Self {
1316 Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
1317 }
1318}
1319
1320impl<T: Neg, U> Neg for Size3D<T, U> {
1321 type Output = Size3D<T::Output, U>;
1322
1323 #[inline]
1324 fn neg(self) -> Self::Output {
1325 Size3D::new(-self.width, -self.height, -self.depth)
1326 }
1327}
1328
1329impl<T: Add, U> Add for Size3D<T, U> {
1330 type Output = Size3D<T::Output, U>;
1331
1332 #[inline]
1333 fn add(self, other: Self) -> Self::Output {
1334 Size3D::new(
1335 self.width + other.width,
1336 self.height + other.height,
1337 self.depth + other.depth,
1338 )
1339 }
1340}
1341
1342impl<T: AddAssign, U> AddAssign for Size3D<T, U> {
1343 #[inline]
1344 fn add_assign(&mut self, other: Self) {
1345 self.width += other.width;
1346 self.height += other.height;
1347 self.depth += other.depth;
1348 }
1349}
1350
1351impl<T: Sub, U> Sub for Size3D<T, U> {
1352 type Output = Size3D<T::Output, U>;
1353
1354 #[inline]
1355 fn sub(self, other: Self) -> Self::Output {
1356 Size3D::new(
1357 self.width - other.width,
1358 self.height - other.height,
1359 self.depth - other.depth,
1360 )
1361 }
1362}
1363
1364impl<T: SubAssign, U> SubAssign for Size3D<T, U> {
1365 #[inline]
1366 fn sub_assign(&mut self, other: Self) {
1367 self.width -= other.width;
1368 self.height -= other.height;
1369 self.depth -= other.depth;
1370 }
1371}
1372
1373impl<T: Copy + Mul, U> Mul<T> for Size3D<T, U> {
1374 type Output = Size3D<T::Output, U>;
1375
1376 #[inline]
1377 fn mul(self, scale: T) -> Self::Output {
1378 Size3D::new(
1379 self.width * scale,
1380 self.height * scale,
1381 self.depth * scale,
1382 )
1383 }
1384}
1385
1386impl<T: Copy + MulAssign, U> MulAssign<T> for Size3D<T, U> {
1387 #[inline]
1388 fn mul_assign(&mut self, other: T) {
1389 self.width *= other;
1390 self.height *= other;
1391 self.depth *= other;
1392 }
1393}
1394
1395impl<T: Copy + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size3D<T, U1> {
1396 type Output = Size3D<T::Output, U2>;
1397
1398 #[inline]
1399 fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
1400 Size3D::new(
1401 self.width * scale.0,
1402 self.height * scale.0,
1403 self.depth * scale.0,
1404 )
1405 }
1406}
1407
1408impl<T: Copy + MulAssign, U> MulAssign<Scale<T, U, U>> for Size3D<T, U> {
1409 #[inline]
1410 fn mul_assign(&mut self, other: Scale<T, U, U>) {
1411 *self *= other.0;
1412 }
1413}
1414
1415impl<T: Copy + Div, U> Div<T> for Size3D<T, U> {
1416 type Output = Size3D<T::Output, U>;
1417
1418 #[inline]
1419 fn div(self, scale: T) -> Self::Output {
1420 Size3D::new(
1421 self.width / scale,
1422 self.height / scale,
1423 self.depth / scale,
1424 )
1425 }
1426}
1427
1428impl<T: Copy + DivAssign, U> DivAssign<T> for Size3D<T, U> {
1429 #[inline]
1430 fn div_assign(&mut self, other: T) {
1431 self.width /= other;
1432 self.height /= other;
1433 self.depth /= other;
1434 }
1435}
1436
1437impl<T: Copy + Div, U1, U2> Div<Scale<T, U1, U2>> for Size3D<T, U2> {
1438 type Output = Size3D<T::Output, U1>;
1439
1440 #[inline]
1441 fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
1442 Size3D::new(
1443 self.width / scale.0,
1444 self.height / scale.0,
1445 self.depth / scale.0,
1446 )
1447 }
1448}
1449
1450impl<T: Copy + DivAssign, U> DivAssign<Scale<T, U, U>> for Size3D<T, U> {
1451 #[inline]
1452 fn div_assign(&mut self, other: Scale<T, U, U>) {
1453 *self /= other.0;
1454 }
1455}
1456
1457#[cfg(feature = "mint")]
1458impl<T, U> From<mint::Vector3<T>> for Size3D<T, U> {
1459 #[inline]
1460 fn from(v: mint::Vector3<T>) -> Self {
1461 size3(v.x, v.y, v.z)
1462 }
1463}
1464#[cfg(feature = "mint")]
1465impl<T, U> Into<mint::Vector3<T>> for Size3D<T, U> {
1466 #[inline]
1467 fn into(self) -> mint::Vector3<T> {
1468 mint::Vector3 {
1469 x: self.width,
1470 y: self.height,
1471 z: self.depth,
1472 }
1473 }
1474}
1475
1476impl<T, U> From<Vector3D<T, U>> for Size3D<T, U> {
1477 #[inline]
1478 fn from(v: Vector3D<T, U>) -> Self {
1479 size3(v.x, v.y, v.z)
1480 }
1481}
1482
1483impl<T, U> Into<[T; 3]> for Size3D<T, U> {
1484 #[inline]
1485 fn into(self) -> [T; 3] {
1486 [self.width, self.height, self.depth]
1487 }
1488}
1489
1490impl<T, U> From<[T; 3]> for Size3D<T, U> {
1491 #[inline]
1492 fn from([w, h, d]: [T; 3]) -> Self {
1493 size3(w, h, d)
1494 }
1495}
1496
1497impl<T, U> Into<(T, T, T)> for Size3D<T, U> {
1498 #[inline]
1499 fn into(self) -> (T, T, T) {
1500 (self.width, self.height, self.depth)
1501 }
1502}
1503
1504impl<T, U> From<(T, T, T)> for Size3D<T, U> {
1505 #[inline]
1506 fn from(tuple: (T, T, T)) -> Self {
1507 size3(tuple.0, tuple.1, tuple.2)
1508 }
1509}
1510
1511#[inline]
1513pub const fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
1514 Size3D::new(w, h, d)
1515}
1516
1517#[cfg(test)]
1518mod size3d {
1519 mod ops {
1520 use crate::default::Size3D;
1521 use crate::scale::Scale;
1522
1523 pub enum Mm {}
1524 pub enum Cm {}
1525
1526 pub type Size3DMm<T> = crate::Size3D<T, Mm>;
1527 pub type Size3DCm<T> = crate::Size3D<T, Cm>;
1528
1529 #[test]
1530 pub fn test_neg() {
1531 assert_eq!(-Size3D::new(1.0, 2.0, 3.0), Size3D::new(-1.0, -2.0, -3.0));
1532 assert_eq!(-Size3D::new(0.0, 0.0, 0.0), Size3D::new(-0.0, -0.0, -0.0));
1533 assert_eq!(-Size3D::new(-1.0, -2.0, -3.0), Size3D::new(1.0, 2.0, 3.0));
1534 }
1535
1536 #[test]
1537 pub fn test_add() {
1538 let s1 = Size3D::new(1.0, 2.0, 3.0);
1539 let s2 = Size3D::new(4.0, 5.0, 6.0);
1540 assert_eq!(s1 + s2, Size3D::new(5.0, 7.0, 9.0));
1541
1542 let s1 = Size3D::new(1.0, 2.0, 3.0);
1543 let s2 = Size3D::new(0.0, 0.0, 0.0);
1544 assert_eq!(s1 + s2, Size3D::new(1.0, 2.0, 3.0));
1545
1546 let s1 = Size3D::new(1.0, 2.0, 3.0);
1547 let s2 = Size3D::new(-4.0, -5.0, -6.0);
1548 assert_eq!(s1 + s2, Size3D::new(-3.0, -3.0, -3.0));
1549
1550 let s1 = Size3D::new(0.0, 0.0, 0.0);
1551 let s2 = Size3D::new(0.0, 0.0, 0.0);
1552 assert_eq!(s1 + s2, Size3D::new(0.0, 0.0, 0.0));
1553 }
1554
1555 #[test]
1556 pub fn test_add_assign() {
1557 let mut s = Size3D::new(1.0, 2.0, 3.0);
1558 s += Size3D::new(4.0, 5.0, 6.0);
1559 assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1560
1561 let mut s = Size3D::new(1.0, 2.0, 3.0);
1562 s += Size3D::new(0.0, 0.0, 0.0);
1563 assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1564
1565 let mut s = Size3D::new(1.0, 2.0, 3.0);
1566 s += Size3D::new(-4.0, -5.0, -6.0);
1567 assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1568
1569 let mut s = Size3D::new(0.0, 0.0, 0.0);
1570 s += Size3D::new(0.0, 0.0, 0.0);
1571 assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1572 }
1573
1574 #[test]
1575 pub fn test_sub() {
1576 let s1 = Size3D::new(1.0, 2.0, 3.0);
1577 let s2 = Size3D::new(4.0, 5.0, 6.0);
1578 assert_eq!(s1 - s2, Size3D::new(-3.0, -3.0, -3.0));
1579
1580 let s1 = Size3D::new(1.0, 2.0, 3.0);
1581 let s2 = Size3D::new(0.0, 0.0, 0.0);
1582 assert_eq!(s1 - s2, Size3D::new(1.0, 2.0, 3.0));
1583
1584 let s1 = Size3D::new(1.0, 2.0, 3.0);
1585 let s2 = Size3D::new(-4.0, -5.0, -6.0);
1586 assert_eq!(s1 - s2, Size3D::new(5.0, 7.0, 9.0));
1587
1588 let s1 = Size3D::new(0.0, 0.0, 0.0);
1589 let s2 = Size3D::new(0.0, 0.0, 0.0);
1590 assert_eq!(s1 - s2, Size3D::new(0.0, 0.0, 0.0));
1591 }
1592
1593 #[test]
1594 pub fn test_sub_assign() {
1595 let mut s = Size3D::new(1.0, 2.0, 3.0);
1596 s -= Size3D::new(4.0, 5.0, 6.0);
1597 assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1598
1599 let mut s = Size3D::new(1.0, 2.0, 3.0);
1600 s -= Size3D::new(0.0, 0.0, 0.0);
1601 assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1602
1603 let mut s = Size3D::new(1.0, 2.0, 3.0);
1604 s -= Size3D::new(-4.0, -5.0, -6.0);
1605 assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1606
1607 let mut s = Size3D::new(0.0, 0.0, 0.0);
1608 s -= Size3D::new(0.0, 0.0, 0.0);
1609 assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1610 }
1611
1612 #[test]
1613 pub fn test_mul_scalar() {
1614 let s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1615
1616 let result = s1 * 5.0;
1617
1618 assert_eq!(result, Size3D::new(15.0, 25.0, 35.0));
1619 }
1620
1621 #[test]
1622 pub fn test_mul_assign_scalar() {
1623 let mut s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1624
1625 s1 *= 5.0;
1626
1627 assert_eq!(s1, Size3D::new(15.0, 25.0, 35.0));
1628 }
1629
1630 #[test]
1631 pub fn test_mul_scale() {
1632 let s1 = Size3DMm::new(1.0, 2.0, 3.0);
1633 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1634
1635 let result = s1 * cm_per_mm;
1636
1637 assert_eq!(result, Size3DCm::new(0.1, 0.2, 0.3));
1638 }
1639
1640 #[test]
1641 pub fn test_mul_assign_scale() {
1642 let mut s1 = Size3DMm::new(1.0, 2.0, 3.0);
1643 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1644
1645 s1 *= scale;
1646
1647 assert_eq!(s1, Size3DMm::new(0.1, 0.2, 0.3));
1648 }
1649
1650 #[test]
1651 pub fn test_div_scalar() {
1652 let s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1653
1654 let result = s1 / 5.0;
1655
1656 assert_eq!(result, Size3D::new(3.0, 5.0, 7.0));
1657 }
1658
1659 #[test]
1660 pub fn test_div_assign_scalar() {
1661 let mut s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1662
1663 s1 /= 5.0;
1664
1665 assert_eq!(s1, Size3D::new(3.0, 5.0, 7.0));
1666 }
1667
1668 #[test]
1669 pub fn test_div_scale() {
1670 let s1 = Size3DCm::new(0.1, 0.2, 0.3);
1671 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1672
1673 let result = s1 / cm_per_mm;
1674
1675 assert_eq!(result, Size3DMm::new(1.0, 2.0, 3.0));
1676 }
1677
1678 #[test]
1679 pub fn test_div_assign_scale() {
1680 let mut s1 = Size3DMm::new(0.1, 0.2, 0.3);
1681 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1682
1683 s1 /= scale;
1684
1685 assert_eq!(s1, Size3DMm::new(1.0, 2.0, 3.0));
1686 }
1687
1688 #[test]
1689 pub fn test_nan_empty() {
1690 use std::f32::NAN;
1691 assert!(Size3D::new(NAN, 2.0, 3.0).is_empty());
1692 assert!(Size3D::new(0.0, NAN, 0.0).is_empty());
1693 assert!(Size3D::new(1.0, 2.0, NAN).is_empty());
1694 }
1695 }
1696}