crunch/
rect.rs

1/// A simple rectangle structure used for packing.
2#[derive(Debug, Copy, Clone, Default, PartialEq)]
3pub struct Rect {
4    pub x: usize,
5    pub y: usize,
6    pub w: usize,
7    pub h: usize,
8}
9
10impl Rect {
11    /// Create a new `Rect`.
12    #[inline]
13    pub const fn new(x: usize, y: usize, w: usize, h: usize) -> Self {
14        Self { x, y, w, h }
15    }
16
17    /// Create a new `Rect` with the size `w` x `h`.
18    ///
19    /// This is the same as calling `Rect::new(0, 0, w, h)`.
20    #[inline]
21    pub const fn of_size(w: usize, h: usize) -> Self {
22        Self::new(0, 0, w, h)
23    }
24
25    /// The area of the rectangle.
26    #[inline]
27    pub const fn area(&self) -> usize {
28        self.w * self.h
29    }
30
31    /// Returns true if `other` is fully contained inside `self`.
32    #[inline]
33    pub const fn contains(&self, other: &Rect) -> bool {
34        other.x >= self.x
35            && other.y >= self.y
36            && other.right() <= self.right()
37            && other.bottom() <= self.bottom()
38    }
39
40    /// Returns true if `other` overlaps `self`.
41    #[inline]
42    pub const fn overlaps(&self, other: &Rect) -> bool {
43        self.x < other.right()
44            && self.y < other.bottom()
45            && self.right() > other.x
46            && self.bottom() > other.y
47    }
48
49    /// The rectangle's top-left coordinates.
50    #[inline]
51    pub const fn top_left(&self) -> (usize, usize) {
52        (self.x, self.y)
53    }
54
55    /// The right edge of the rectangle.
56    #[inline]
57    pub const fn right(&self) -> usize {
58        self.x + self.w
59    }
60
61    /// The bottom edge of the rectangle.
62    #[inline]
63    pub const fn bottom(&self) -> usize {
64        self.y + self.h
65    }
66
67    #[inline]
68    pub(crate) fn split(&self, rect: &Rect) -> [Option<Self>; 4] {
69        let (self_r, self_b) = (self.right(), self.bottom());
70        let (rect_r, rect_b) = (rect.right(), rect.bottom());
71        [
72            (rect.x > self.x).then(|| Self::new(self.x, self.y, rect.x - self.x, self.h)),
73            (rect_r < self_r).then(|| Self::new(rect_r, self.y, self_r - rect_r, self.h)),
74            (rect.y > self.y).then(|| Self::new(self.x, self.y, self.w, rect.y - self.y)),
75            (rect_b < self_b).then(|| Self::new(self.x, rect_b, self.w, self_b - rect_b)),
76        ]
77    }
78}