yakui_core/geometry/
rect.rs

1use glam::Vec2;
2
3/// A bounding rectangle with floating point coordinates.
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct Rect {
6    pos: Vec2,
7    size: Vec2,
8}
9
10impl Rect {
11    /// A zero-sized rectangle at the origin.
12    pub const ZERO: Self = Self {
13        pos: Vec2::ZERO,
14        size: Vec2::ZERO,
15    };
16
17    /// A rectangle of size (1, 1) at the origin.
18    pub const ONE: Self = Self {
19        pos: Vec2::ZERO,
20        size: Vec2::ONE,
21    };
22
23    /// Create a `Rect` from a position and size.
24    #[inline]
25    pub fn from_pos_size(pos: Vec2, size: Vec2) -> Self {
26        Self { pos, size }
27    }
28
29    /// The position of the rectangle's upper-left corner. This is the minimum
30    /// value enclosed by the rectangle.
31    #[inline]
32    pub fn pos(&self) -> Vec2 {
33        self.pos
34    }
35
36    /// The size of the rectangle.
37    #[inline]
38    pub fn size(&self) -> Vec2 {
39        self.size
40    }
41
42    /// The maximum value enclosed by the rectangle.
43    #[inline]
44    pub fn max(&self) -> Vec2 {
45        self.pos + self.size
46    }
47
48    /// Set the rectangle's position.
49    #[inline]
50    pub fn set_pos(&mut self, pos: Vec2) {
51        self.pos = pos;
52    }
53
54    /// Set the rectangle's size.
55    #[inline]
56    pub fn set_size(&mut self, size: Vec2) {
57        self.size = size;
58    }
59
60    /// Set the rectangle's maximum extent.
61    #[inline]
62    pub fn set_max(&mut self, max: Vec2) {
63        self.size = max - self.pos;
64    }
65
66    /// Tells whether the given point is contained within the rectangle.
67    ///
68    /// If the point lies on the rectangle's boundary, it is considered
69    /// **inside**.
70    #[inline]
71    pub fn contains_point(&self, point: Vec2) -> bool {
72        point.x >= self.pos.x
73            && point.x <= self.pos.x + self.size.x
74            && point.y >= self.pos.y
75            && point.y <= self.pos.y + self.size.y
76    }
77
78    /// Tells whether two rectangles intersect.
79    ///
80    /// If the rectangles touch but do not overlap, they are considered **not
81    /// intersecting**.
82    #[inline]
83    pub fn intersects(&self, other: &Self) -> bool {
84        let self_max = self.max();
85        let other_max = other.max();
86
87        let x_intersect = self.pos.x < other_max.x && self_max.x > other.pos.x;
88        let y_intersect = self.pos.y < other_max.y && self_max.y > other.pos.y;
89
90        x_intersect && y_intersect
91    }
92
93    /// Scale the rectangle by dividing it by a vector.
94    #[inline]
95    pub fn div_vec2(&self, size: Vec2) -> Self {
96        Self::from_pos_size(self.pos / size, self.size / size)
97    }
98
99    /// Returns a rectangle that fits this rectangle and the given rectangle.
100    #[inline]
101    pub fn constrain(mut self, other: Rect) -> Self {
102        let min = self.pos().max(other.pos());
103        let max = self.max().min(other.max());
104
105        self.set_pos(min);
106        self.set_max(max);
107        self
108    }
109}