Skip to main content

telar_geometry_core/
rect.rs

1#[derive(Debug, Clone, Copy, PartialEq)]
2pub struct Rect {
3    pub x: f32,
4    pub y: f32,
5    pub width: f32,
6    pub height: f32,
7}
8
9impl Rect {
10    pub fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
11        Self {
12            x,
13            y,
14            width,
15            height,
16        }
17    }
18
19    pub fn contains(&self, x: f32, y: f32) -> bool {
20        x >= self.x && x < self.x + self.width && y >= self.y && y < self.y + self.height
21    }
22
23    pub fn intersect(self, other: Rect) -> Option<Rect> {
24        let x = self.x.max(other.x);
25        let y = self.y.max(other.y);
26        let right = (self.x + self.width).min(other.x + other.width);
27        let bottom = (self.y + self.height).min(other.y + other.height);
28        if right > x && bottom > y {
29            Some(Rect::new(x, y, right - x, bottom - y))
30        } else {
31            None
32        }
33    }
34
35    pub fn union(self, other: Rect) -> Rect {
36        let x = self.x.min(other.x);
37        let y = self.y.min(other.y);
38        let right = (self.x + self.width).max(other.x + other.width);
39        let bottom = (self.y + self.height).max(other.y + other.height);
40        Rect::new(x, y, right - x, bottom - y)
41    }
42
43    pub fn overlaps(self, other: Rect) -> bool {
44        self.x < other.x + other.width
45            && self.x + self.width > other.x
46            && self.y < other.y + other.height
47            && self.y + self.height > other.y
48    }
49}
50
51impl Default for Rect {
52    fn default() -> Self {
53        Self::new(0.0, 0.0, 0.0, 0.0)
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn rect_new_stores_fields() {
63        let r = Rect::new(1.0, 2.0, 10.0, 20.0);
64        assert_eq!(r.x, 1.0);
65        assert_eq!(r.y, 2.0);
66        assert_eq!(r.width, 10.0);
67        assert_eq!(r.height, 20.0);
68    }
69
70    #[test]
71    fn rect_default_is_zero() {
72        let r = Rect::default();
73        assert_eq!(r.x, 0.0);
74        assert_eq!(r.y, 0.0);
75        assert_eq!(r.width, 0.0);
76        assert_eq!(r.height, 0.0);
77    }
78
79    #[test]
80    fn rect_intersect_overlapping() {
81        let a = Rect::new(0.0, 0.0, 10.0, 10.0);
82        let b = Rect::new(5.0, 5.0, 10.0, 10.0);
83        let result = a.intersect(b).unwrap();
84        assert_eq!(result.x, 5.0);
85        assert_eq!(result.y, 5.0);
86        assert_eq!(result.width, 5.0);
87        assert_eq!(result.height, 5.0);
88    }
89
90    #[test]
91    fn rect_intersect_non_overlapping() {
92        let a = Rect::new(0.0, 0.0, 5.0, 5.0);
93        let b = Rect::new(10.0, 10.0, 5.0, 5.0);
94        assert!(a.intersect(b).is_none());
95    }
96}