1use super::UnknownUnit;
11#[cfg(feature = "mint")]
12use mint;
13use length::Length;
14use scale::TypedScale;
15use vector::{TypedVector2D, vec2, BoolVector2D};
16use vector::{TypedVector3D, vec3, BoolVector3D};
17use num::*;
18
19use num_traits::{Float, NumCast, Signed};
20use core::fmt;
21use core::ops::{Add, Div, Mul, Sub};
22use core::marker::PhantomData;
23
24#[derive(EuclidMatrix)]
26#[repr(C)]
27pub struct TypedSize2D<T, U> {
28 pub width: T,
29 pub height: T,
30 #[doc(hidden)]
31 pub _unit: PhantomData<U>,
32}
33
34pub type Size2D<T> = TypedSize2D<T, UnknownUnit>;
38
39impl<T: fmt::Debug, U> fmt::Debug for TypedSize2D<T, U> {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 write!(f, "{:?}×{:?}", self.width, self.height)
42 }
43}
44
45impl<T: fmt::Display, U> fmt::Display for TypedSize2D<T, U> {
46 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
47 write!(formatter, "({}x{})", self.width, self.height)
48 }
49}
50
51impl<T: Default, U> Default for TypedSize2D<T, U> {
52 fn default() -> Self {
53 TypedSize2D::new(Default::default(), Default::default())
54 }
55}
56
57impl<T, U> TypedSize2D<T, U> {
58 pub fn new(width: T, height: T) -> Self {
60 TypedSize2D {
61 width,
62 height,
63 _unit: PhantomData,
64 }
65 }
66}
67
68impl<T: Clone, U> TypedSize2D<T, U> {
69 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
71 TypedSize2D::new(width.get(), height.get())
72 }
73}
74
75impl<T: Round, U> TypedSize2D<T, U> {
76 pub fn round(&self) -> Self {
80 TypedSize2D::new(self.width.round(), self.height.round())
81 }
82}
83
84impl<T: Ceil, U> TypedSize2D<T, U> {
85 pub fn ceil(&self) -> Self {
89 TypedSize2D::new(self.width.ceil(), self.height.ceil())
90 }
91}
92
93impl<T: Floor, U> TypedSize2D<T, U> {
94 pub fn floor(&self) -> Self {
98 TypedSize2D::new(self.width.floor(), self.height.floor())
99 }
100}
101
102impl<T: Copy + Add<T, Output = T>, U> Add for TypedSize2D<T, U> {
103 type Output = Self;
104 fn add(self, other: Self) -> Self {
105 TypedSize2D::new(self.width + other.width, self.height + other.height)
106 }
107}
108
109impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedSize2D<T, U> {
110 type Output = Self;
111 fn sub(self, other: Self) -> Self {
112 TypedSize2D::new(self.width - other.width, self.height - other.height)
113 }
114}
115
116impl<T: Copy + Clone + Mul<T>, U> TypedSize2D<T, U> {
117 pub fn area(&self) -> T::Output {
118 self.width * self.height
119 }
120}
121
122impl<T, U> TypedSize2D<T, U>
123where
124 T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
125{
126 #[inline]
130 pub fn lerp(&self, other: Self, t: T) -> Self {
131 let one_t = T::one() - t;
132 size2(
133 one_t * self.width + t * other.width,
134 one_t * self.height + t * other.height,
135 )
136 }
137}
138
139impl<T: Zero + PartialOrd, U> TypedSize2D<T, U> {
140 pub fn is_empty_or_negative(&self) -> bool {
141 let zero = T::zero();
142 self.width <= zero || self.height <= zero
143 }
144}
145
146impl<T: Zero, U> TypedSize2D<T, U> {
147 pub fn zero() -> Self {
148 TypedSize2D::new(Zero::zero(), Zero::zero())
149 }
150}
151
152impl<T: Zero, U> Zero for TypedSize2D<T, U> {
153 fn zero() -> Self {
154 TypedSize2D::new(Zero::zero(), Zero::zero())
155 }
156}
157
158impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedSize2D<T, U> {
159 type Output = Self;
160 #[inline]
161 fn mul(self, scale: T) -> Self {
162 TypedSize2D::new(self.width * scale, self.height * scale)
163 }
164}
165
166impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedSize2D<T, U> {
167 type Output = Self;
168 #[inline]
169 fn div(self, scale: T) -> Self {
170 TypedSize2D::new(self.width / scale, self.height / scale)
171 }
172}
173
174impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedSize2D<T, U1> {
175 type Output = TypedSize2D<T, U2>;
176 #[inline]
177 fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedSize2D<T, U2> {
178 TypedSize2D::new(self.width * scale.get(), self.height * scale.get())
179 }
180}
181
182impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedSize2D<T, U2> {
183 type Output = TypedSize2D<T, U1>;
184 #[inline]
185 fn div(self, scale: TypedScale<T, U1, U2>) -> TypedSize2D<T, U1> {
186 TypedSize2D::new(self.width / scale.get(), self.height / scale.get())
187 }
188}
189
190impl<T: Copy, U> TypedSize2D<T, U> {
191 #[inline]
193 pub fn width_typed(&self) -> Length<T, U> {
194 Length::new(self.width)
195 }
196
197 #[inline]
199 pub fn height_typed(&self) -> Length<T, U> {
200 Length::new(self.height)
201 }
202
203 #[inline]
204 pub fn to_array(&self) -> [T; 2] {
205 [self.width, self.height]
206 }
207
208 #[inline]
209 pub fn to_tuple(&self) -> (T, T) {
210 (self.width, self.height)
211 }
212
213 #[inline]
214 pub fn to_vector(&self) -> TypedVector2D<T, U> {
215 vec2(self.width, self.height)
216 }
217
218 pub fn to_untyped(&self) -> Size2D<T> {
220 TypedSize2D::new(self.width, self.height)
221 }
222
223 pub fn from_untyped(p: &Size2D<T>) -> Self {
225 TypedSize2D::new(p.width, p.height)
226 }
227}
228
229impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
230 pub fn cast<NewT: NumCast + Copy>(&self) -> TypedSize2D<NewT, Unit> {
236 self.try_cast().unwrap()
237 }
238
239 pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize2D<NewT, Unit>> {
245 match (NumCast::from(self.width), NumCast::from(self.height)) {
246 (Some(w), Some(h)) => Some(TypedSize2D::new(w, h)),
247 _ => None,
248 }
249 }
250
251 pub fn to_f32(&self) -> TypedSize2D<f32, Unit> {
255 self.cast()
256 }
257
258 pub fn to_f64(&self) -> TypedSize2D<f64, Unit> {
260 self.cast()
261 }
262
263 pub fn to_usize(&self) -> TypedSize2D<usize, Unit> {
269 self.cast()
270 }
271
272 pub fn to_u32(&self) -> TypedSize2D<u32, Unit> {
278 self.cast()
279 }
280
281 pub fn to_i32(&self) -> TypedSize2D<i32, Unit> {
287 self.cast()
288 }
289
290 pub fn to_i64(&self) -> TypedSize2D<i64, Unit> {
296 self.cast()
297 }
298}
299
300impl<T, U> TypedSize2D<T, U>
301where
302 T: Signed,
303{
304 pub fn abs(&self) -> Self {
305 size2(self.width.abs(), self.height.abs())
306 }
307
308 pub fn is_positive(&self) -> bool {
309 self.width.is_positive() && self.height.is_positive()
310 }
311}
312
313impl<T: PartialOrd, U> TypedSize2D<T, U> {
314 pub fn greater_than(&self, other: &Self) -> BoolVector2D {
315 BoolVector2D {
316 x: self.width > other.width,
317 y: self.height > other.height,
318 }
319 }
320
321 pub fn lower_than(&self, other: &Self) -> BoolVector2D {
322 BoolVector2D {
323 x: self.width < other.width,
324 y: self.height < other.height,
325 }
326 }
327}
328
329
330impl<T: PartialEq, U> TypedSize2D<T, U> {
331 pub fn equal(&self, other: &Self) -> BoolVector2D {
332 BoolVector2D {
333 x: self.width == other.width,
334 y: self.height == other.height,
335 }
336 }
337
338 pub fn not_equal(&self, other: &Self) -> BoolVector2D {
339 BoolVector2D {
340 x: self.width != other.width,
341 y: self.height != other.height,
342 }
343 }
344}
345
346impl<T: Float, U> TypedSize2D<T, U> {
347 #[inline]
348 pub fn min(self, other: Self) -> Self {
349 size2(
350 self.width.min(other.width),
351 self.height.min(other.height),
352 )
353 }
354
355 #[inline]
356 pub fn max(self, other: Self) -> Self {
357 size2(
358 self.width.max(other.width),
359 self.height.max(other.height),
360 )
361 }
362
363 #[inline]
364 pub fn clamp(&self, start: Self, end: Self) -> Self {
365 self.max(start).min(end)
366 }
367}
368
369
370pub fn size2<T, U>(w: T, h: T) -> TypedSize2D<T, U> {
372 TypedSize2D::new(w, h)
373}
374
375#[cfg(feature = "mint")]
376impl<T, U> From<mint::Vector2<T>> for TypedSize2D<T, U> {
377 fn from(v: mint::Vector2<T>) -> Self {
378 TypedSize2D {
379 width: v.x,
380 height: v.y,
381 _unit: PhantomData,
382 }
383 }
384}
385#[cfg(feature = "mint")]
386impl<T, U> Into<mint::Vector2<T>> for TypedSize2D<T, U> {
387 fn into(self) -> mint::Vector2<T> {
388 mint::Vector2 {
389 x: self.width,
390 y: self.height,
391 }
392 }
393}
394
395impl<T: Copy, U> Into<[T; 2]> for TypedSize2D<T, U> {
396 fn into(self) -> [T; 2] {
397 self.to_array()
398 }
399}
400
401impl<T: Copy, U> From<[T; 2]> for TypedSize2D<T, U> {
402 fn from(array: [T; 2]) -> Self {
403 size2(array[0], array[1])
404 }
405}
406
407impl<T: Copy, U> Into<(T, T)> for TypedSize2D<T, U> {
408 fn into(self) -> (T, T) {
409 self.to_tuple()
410 }
411}
412
413impl<T: Copy, U> From<(T, T)> for TypedSize2D<T, U> {
414 fn from(tuple: (T, T)) -> Self {
415 size2(tuple.0, tuple.1)
416 }
417}
418
419#[cfg(test)]
420mod size2d {
421 use super::Size2D;
422 #[cfg(feature = "mint")]
423 use mint;
424
425 #[test]
426 pub fn test_add() {
427 let p1 = Size2D::new(1.0, 2.0);
428 let p2 = Size2D::new(3.0, 4.0);
429 assert_eq!(p1 + p2, Size2D::new(4.0, 6.0));
430
431 let p1 = Size2D::new(1.0, 2.0);
432 let p2 = Size2D::new(0.0, 0.0);
433 assert_eq!(p1 + p2, Size2D::new(1.0, 2.0));
434
435 let p1 = Size2D::new(1.0, 2.0);
436 let p2 = Size2D::new(-3.0, -4.0);
437 assert_eq!(p1 + p2, Size2D::new(-2.0, -2.0));
438
439 let p1 = Size2D::new(0.0, 0.0);
440 let p2 = Size2D::new(0.0, 0.0);
441 assert_eq!(p1 + p2, Size2D::new(0.0, 0.0));
442 }
443
444 #[test]
445 pub fn test_sub() {
446 let p1 = Size2D::new(1.0, 2.0);
447 let p2 = Size2D::new(3.0, 4.0);
448 assert_eq!(p1 - p2, Size2D::new(-2.0, -2.0));
449
450 let p1 = Size2D::new(1.0, 2.0);
451 let p2 = Size2D::new(0.0, 0.0);
452 assert_eq!(p1 - p2, Size2D::new(1.0, 2.0));
453
454 let p1 = Size2D::new(1.0, 2.0);
455 let p2 = Size2D::new(-3.0, -4.0);
456 assert_eq!(p1 - p2, Size2D::new(4.0, 6.0));
457
458 let p1 = Size2D::new(0.0, 0.0);
459 let p2 = Size2D::new(0.0, 0.0);
460 assert_eq!(p1 - p2, Size2D::new(0.0, 0.0));
461 }
462
463 #[test]
464 pub fn test_area() {
465 let p = Size2D::new(1.5, 2.0);
466 assert_eq!(p.area(), 3.0);
467 }
468
469 #[cfg(feature = "mint")]
470 #[test]
471 pub fn test_mint() {
472 let s1 = Size2D::new(1.0, 2.0);
473 let sm: mint::Vector2<_> = s1.into();
474 let s2 = Size2D::from(sm);
475
476 assert_eq!(s1, s2);
477 }
478}
479
480#[derive(EuclidMatrix)]
482#[repr(C)]
483pub struct TypedSize3D<T, U> {
484 pub width: T,
485 pub height: T,
486 pub depth: T,
487 #[doc(hidden)]
488 pub _unit: PhantomData<U>,
489}
490
491pub type Size3D<T> = TypedSize3D<T, UnknownUnit>;
495
496impl<T: fmt::Debug, U> fmt::Debug for TypedSize3D<T, U> {
497 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
498 write!(f, "{:?}×{:?}×{:?}", self.width, self.height, self.depth)
499 }
500}
501
502impl<T: fmt::Display, U> fmt::Display for TypedSize3D<T, U> {
503 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
504 write!(formatter, "({}x{}x{})", self.width, self.height, self.depth)
505 }
506}
507
508impl<T: Default, U> Default for TypedSize3D<T, U> {
509 fn default() -> Self {
510 TypedSize3D::new(Default::default(), Default::default(), Default::default())
511 }
512}
513
514impl<T, U> TypedSize3D<T, U> {
515 pub fn new(width: T, height: T, depth: T) -> Self {
517 TypedSize3D {
518 width,
519 height,
520 depth,
521 _unit: PhantomData,
522 }
523 }
524}
525
526impl<T: Clone, U> TypedSize3D<T, U> {
527 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
529 TypedSize3D::new(width.get(), height.get(), depth.get())
530 }
531}
532
533impl<T: Round, U> TypedSize3D<T, U> {
534 pub fn round(&self) -> Self {
538 TypedSize3D::new(self.width.round(), self.height.round(), self.depth.round())
539 }
540}
541
542impl<T: Ceil, U> TypedSize3D<T, U> {
543 pub fn ceil(&self) -> Self {
547 TypedSize3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
548 }
549}
550
551impl<T: Floor, U> TypedSize3D<T, U> {
552 pub fn floor(&self) -> Self {
556 TypedSize3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
557 }
558}
559
560impl<T: Copy + Add<T, Output = T>, U> Add for TypedSize3D<T, U> {
561 type Output = Self;
562 fn add(self, other: Self) -> Self {
563 TypedSize3D::new(self.width + other.width, self.height + other.height, self.depth + other.depth)
564 }
565}
566
567impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedSize3D<T, U> {
568 type Output = Self;
569 fn sub(self, other: Self) -> Self {
570 TypedSize3D::new(self.width - other.width, self.height - other.height, self.depth - other.depth)
571 }
572}
573
574impl<T: Copy + Clone + Mul<T, Output=T>, U> TypedSize3D<T, U> {
575 pub fn volume(&self) -> T {
576 self.width * self.height * self.depth
577 }
578}
579
580impl<T, U> TypedSize3D<T, U>
581where
582 T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
583{
584 #[inline]
588 pub fn lerp(&self, other: Self, t: T) -> Self {
589 let one_t = T::one() - t;
590 size3(
591 one_t * self.width + t * other.width,
592 one_t * self.height + t * other.height,
593 one_t * self.depth + t * other.depth,
594 )
595 }
596}
597
598impl<T: Zero + PartialOrd, U> TypedSize3D<T, U> {
599 pub fn is_empty_or_negative(&self) -> bool {
600 let zero = T::zero();
601 self.width <= zero || self.height <= zero || self.depth <= zero
602 }
603}
604
605impl<T: Zero, U> TypedSize3D<T, U> {
606 pub fn zero() -> Self {
607 TypedSize3D::new(Zero::zero(), Zero::zero(), Zero::zero())
608 }
609}
610
611impl<T: Zero, U> Zero for TypedSize3D<T, U> {
612 fn zero() -> Self {
613 TypedSize3D::new(Zero::zero(), Zero::zero(), Zero::zero())
614 }
615}
616
617impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedSize3D<T, U> {
618 type Output = Self;
619 #[inline]
620 fn mul(self, scale: T) -> Self {
621 TypedSize3D::new(self.width * scale, self.height * scale, self.depth * scale)
622 }
623}
624
625impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedSize3D<T, U> {
626 type Output = Self;
627 #[inline]
628 fn div(self, scale: T) -> Self {
629 TypedSize3D::new(self.width / scale, self.height / scale, self.depth / scale)
630 }
631}
632
633impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedSize3D<T, U1> {
634 type Output = TypedSize3D<T, U2>;
635 #[inline]
636 fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedSize3D<T, U2> {
637 TypedSize3D::new(self.width * scale.get(), self.height * scale.get(), self.depth * scale.get())
638 }
639}
640
641impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedSize3D<T, U2> {
642 type Output = TypedSize3D<T, U1>;
643 #[inline]
644 fn div(self, scale: TypedScale<T, U1, U2>) -> TypedSize3D<T, U1> {
645 TypedSize3D::new(self.width / scale.get(), self.height / scale.get(), self.depth / scale.get())
646 }
647}
648
649impl<T: Copy, U> TypedSize3D<T, U> {
650 #[inline]
652 pub fn width_typed(&self) -> Length<T, U> {
653 Length::new(self.width)
654 }
655
656 #[inline]
658 pub fn height_typed(&self) -> Length<T, U> {
659 Length::new(self.height)
660 }
661
662 #[inline]
664 pub fn depth_typed(&self) -> Length<T, U> {
665 Length::new(self.depth)
666 }
667
668 #[inline]
669 pub fn to_array(&self) -> [T; 3] {
670 [self.width, self.height, self.depth]
671 }
672
673 #[inline]
674 pub fn to_vector(&self) -> TypedVector3D<T, U> {
675 vec3(self.width, self.height, self.depth)
676 }
677
678 pub fn to_untyped(&self) -> Size3D<T> {
680 TypedSize3D::new(self.width, self.height, self.depth)
681 }
682
683 pub fn from_untyped(p: &Size3D<T>) -> Self {
685 TypedSize3D::new(p.width, p.height, p.depth)
686 }
687}
688
689impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
690 pub fn cast<NewT: NumCast + Copy>(&self) -> TypedSize3D<NewT, Unit> {
696 self.try_cast().unwrap()
697 }
698
699 pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize3D<NewT, Unit>> {
705 match (NumCast::from(self.width), NumCast::from(self.height), NumCast::from(self.depth)) {
706 (Some(w), Some(h), Some(d)) => Some(TypedSize3D::new(w, h, d)),
707 _ => None,
708 }
709 }
710
711 pub fn to_f32(&self) -> TypedSize3D<f32, Unit> {
715 self.cast()
716 }
717
718 pub fn to_f64(&self) -> TypedSize3D<f64, Unit> {
720 self.cast()
721 }
722
723 pub fn to_usize(&self) -> TypedSize3D<usize, Unit> {
729 self.cast()
730 }
731
732 pub fn to_u32(&self) -> TypedSize3D<u32, Unit> {
738 self.cast()
739 }
740
741 pub fn to_i32(&self) -> TypedSize3D<i32, Unit> {
747 self.cast()
748 }
749
750 pub fn to_i64(&self) -> TypedSize3D<i64, Unit> {
756 self.cast()
757 }
758}
759
760impl<T, U> TypedSize3D<T, U>
761where
762 T: Signed,
763{
764 pub fn abs(&self) -> Self {
765 size3(self.width.abs(), self.height.abs(), self.depth.abs())
766 }
767
768 pub fn is_positive(&self) -> bool {
769 self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
770 }
771}
772
773impl<T: PartialOrd, U> TypedSize3D<T, U> {
774 pub fn greater_than(&self, other: &Self) -> BoolVector3D {
775 BoolVector3D {
776 x: self.width > other.width,
777 y: self.height > other.height,
778 z: self.depth > other.depth,
779 }
780 }
781
782 pub fn lower_than(&self, other: &Self) -> BoolVector3D {
783 BoolVector3D {
784 x: self.width < other.width,
785 y: self.height < other.height,
786 z: self.depth < other.depth,
787 }
788 }
789}
790
791
792impl<T: PartialEq, U> TypedSize3D<T, U> {
793 pub fn equal(&self, other: &Self) -> BoolVector3D {
794 BoolVector3D {
795 x: self.width == other.width,
796 y: self.height == other.height,
797 z: self.depth == other.depth,
798 }
799 }
800
801 pub fn not_equal(&self, other: &Self) -> BoolVector3D {
802 BoolVector3D {
803 x: self.width != other.width,
804 y: self.height != other.height,
805 z: self.depth != other.depth,
806 }
807 }
808}
809
810impl<T: Float, U> TypedSize3D<T, U> {
811 #[inline]
812 pub fn min(self, other: Self) -> Self {
813 size3(
814 self.width.min(other.width),
815 self.height.min(other.height),
816 self.depth.min(other.depth),
817 )
818 }
819
820 #[inline]
821 pub fn max(self, other: Self) -> Self {
822 size3(
823 self.width.max(other.width),
824 self.height.max(other.height),
825 self.depth.max(other.depth),
826 )
827 }
828
829 #[inline]
830 pub fn clamp(&self, start: Self, end: Self) -> Self {
831 self.max(start).min(end)
832 }
833}
834
835
836pub fn size3<T, U>(w: T, h: T, d: T) -> TypedSize3D<T, U> {
838 TypedSize3D::new(w, h, d)
839}
840
841#[cfg(feature = "mint")]
842impl<T, U> From<mint::Vector3<T>> for TypedSize3D<T, U> {
843 fn from(v: mint::Vector3<T>) -> Self {
844 TypedSize3D {
845 width: v.x,
846 height: v.y,
847 depth: v.z,
848 _unit: PhantomData,
849 }
850 }
851}
852#[cfg(feature = "mint")]
853impl<T, U> Into<mint::Vector3<T>> for TypedSize3D<T, U> {
854 fn into(self) -> mint::Vector3<T> {
855 mint::Vector3 {
856 x: self.width,
857 y: self.height,
858 z: self.depth,
859 }
860 }
861}