1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
use crate::*; #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[repr(C)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Rect<T> { pub origin: Point<T>, pub size: Size<T>, } impl<T> Rect<T> { #[inline] pub fn new(origin: impl Into<Point<T>>, size: impl Into<Size<T>>) -> Self { Self { origin: origin.into(), size: size.into(), } } } impl<T> Rect<T> where T: std::ops::Add<T, Output = T> + Copy, { pub fn endpoint(&self) -> Point<T> { self.origin + self.size } } impl<T> Rect<T> where T: std::ops::Sub<T, Output = T> + Copy + PartialOrd, { #[inline] pub fn from_points(a: impl Into<Point<T>>, b: impl Into<Point<T>>) -> Self { let a = a.into(); let b = b.into(); let (t, u) = { let (tx, ux) = (a.x < b.x).then(|| (a.x, b.x)).unwrap_or((b.x, a.x)); let (ty, uy) = (a.y < b.y).then(|| (a.y, b.y)).unwrap_or((b.y, a.y)); (point(tx, ty), point(ux, uy)) }; Self::new(t, u - t) } } impl<T> Rect<T> where T: std::ops::Add<T, Output = T> + Copy, { #[inline] pub fn translate(&self, d: impl Into<Vector<T>>) -> Self { let d = d.into(); Self::new(self.origin + d, self.size) } } impl<T> Rect<T> where T: std::ops::Mul<T, Output = T> + Copy, { #[inline] pub fn scale(&self, x: T, y: T) -> Self { Self::new(self.origin, (self.size.width * x, self.size.height * y)) } } impl<T: ToPrimitive> Rect<T> { #[inline] pub fn cast<U: NumCast>(self) -> Option<Rect<U>> { Some(Rect::new(self.origin.cast::<U>()?, self.size.cast::<U>()?)) } } #[inline] pub fn rect<T>(point: impl Into<Point<T>>, size: impl Into<Size<T>>) -> Rect<T> { Rect::new(point, size) } #[cfg(test)] mod tests { use super::*; #[test] fn eq_test() { assert!(rect((10, 20), (30, 40)) == rect((10, 20), (30, 40))); } #[test] fn from_points_test() { let rc = Rect::from_points((10, 20), (30, 40)); assert!(rc == rect((10, 20), (20, 20))); assert!(rc.endpoint() == (30, 40)); } #[test] fn translate_test() { assert!(rect((10, 20), (30, 40)).translate((1, 2)) == rect((11, 22), (30, 40))); } #[test] fn scale_test() { assert!(rect((10, 20), (30, 40)).scale(2, 3) == rect((10, 20), (60, 120))); } }