anathema_geometry/
region.rs1use crate::{Pos, Size};
2
3#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct Region {
6 pub from: Pos,
8 pub to: Pos,
10}
11
12impl Region {
13 pub const ZERO: Self = Self::new(Pos::ZERO, Pos::ZERO);
15
16 pub const fn new(from: Pos, to: Pos) -> Self {
18 Self { from, to }
19 }
20
21 pub const fn intersects(&self, other: &Region) -> bool {
23 if other.to.x <= self.from.x || other.from.x >= self.to.x {
24 return false;
25 }
26
27 if other.from.y >= self.to.y || other.to.y <= self.from.y {
28 return false;
29 }
30
31 true
32 }
33
34 pub fn intersect_with(self, other: &Region) -> Self {
36 if !self.intersects(other) {
39 return Self::ZERO;
40 }
41
42 let from_x = self.from.x.max(other.from.x);
43 let from_y = self.from.y.max(other.from.y);
44
45 let to_x = self.to.x.min(other.to.x);
46 let to_y = self.to.y.min(other.to.y);
47
48 Region::new(Pos::new(from_x, from_y), Pos::new(to_x, to_y))
49 }
50
51 pub const fn contains(&self, pos: Pos) -> bool {
55 pos.x >= self.from.x && pos.x < self.to.x && pos.y >= self.from.y && pos.y < self.to.y
56 }
57
58 pub fn constrain(&mut self, other: &Region) {
60 self.from.x = self.from.x.max(other.from.x);
61 self.from.y = self.from.y.max(other.from.y);
62 self.to.x = self.to.x.min(other.to.x);
63 self.to.y = self.to.y.min(other.to.y);
64 }
65}
66
67impl From<(Pos, Size)> for Region {
68 fn from((from, size): (Pos, Size)) -> Self {
69 let to = Pos::new(from.x + size.width as i32, from.y + size.height as i32);
70 Self::new(from, to)
71 }
72}
73
74#[cfg(test)]
75mod test {
76 use super::*;
77
78 #[test]
79 fn region_inersect() {
80 let a = Region::new(Pos::ZERO, Pos::new(10, 10));
81 let b = Region::new(Pos::new(5, 5), Pos::new(8, 8));
82 assert!(a.intersects(&b));
83 assert!(b.intersects(&a));
84 }
85
86 #[test]
87 fn region_contains() {
88 let a = Region::new(Pos::ZERO, Pos::new(10, 10));
89 assert!(a.contains(Pos::ZERO));
90 assert!(a.contains(Pos::new(9, 9)));
91 assert!(!a.contains(Pos::new(10, 10)));
92 }
93
94 #[test]
95 fn constrain_region() {
96 let inner = Region::from((Pos::ZERO, Size::new(10, 10)));
97 let mut outer = Region::from((Pos::ZERO, Size::new(100, 100)));
98 outer.constrain(&inner);
99 let expected = inner;
100 assert_eq!(expected, outer);
101 }
102}