atagen

monolith

public
Star0
Watch0
b110d9b8bf6444cdeeb83ae7296f175318229728
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
crates/planner/src/geom.rsRust106 lines2.5 KB
1
#[derive(Clone, Copy, Debug, PartialEq, Default)]
2
pub struct Rect {
3
    pub x: f64,
4
    pub y: f64,
5
    pub w: f64,
6
    pub h: f64,
7
}
8
9
pub(crate) const TOL: f64 = 0.05;
10
11
impl Rect {
12
    pub const fn new(x: f64, y: f64, w: f64, h: f64) -> Self {
13
        Self { x, y, w, h }
14
    }
15
16
    pub fn right(&self) -> f64 {
17
        self.x + self.w
18
    }
19
20
    pub fn bottom(&self) -> f64 {
21
        self.y + self.h
22
    }
23
24
    pub fn center_x(&self) -> f64 {
25
        self.x + self.w / 2.0
26
    }
27
28
    pub fn center_y(&self) -> f64 {
29
        self.y + self.h / 2.0
30
    }
31
32
    pub fn lerp(&self, other: &Rect, s: f64) -> Rect {
33
        Rect::new(
34
            self.x + (other.x - self.x) * s,
35
            self.y + (other.y - self.y) * s,
36
            self.w + (other.w - self.w) * s,
37
            self.h + (other.h - self.h) * s,
38
        )
39
    }
40
41
    pub(crate) fn same_x(&self, o: &Rect) -> bool {
42
        (self.x - o.x).abs() < TOL && (self.w - o.w).abs() < TOL
43
    }
44
45
    pub(crate) fn same_y(&self, o: &Rect) -> bool {
46
        (self.y - o.y).abs() < TOL && (self.h - o.h).abs() < TOL
47
    }
48
49
    /// Takes the horizontal extent of `x_from` and the vertical extent of `y_from`.
50
    pub(crate) fn mixed(x_from: &Rect, y_from: &Rect) -> Rect {
51
        Rect::new(x_from.x, y_from.y, x_from.w, y_from.h)
52
    }
53
54
    pub(crate) fn bounding<'a>(rects: impl IntoIterator<Item = &'a Rect>) -> Rect {
55
        let (mut x0, mut y0, mut x1, mut y1) = (
56
            f64::INFINITY,
57
            f64::INFINITY,
58
            f64::NEG_INFINITY,
59
            f64::NEG_INFINITY,
60
        );
61
        for r in rects {
62
            x0 = x0.min(r.x);
63
            y0 = y0.min(r.y);
64
            x1 = x1.max(r.right());
65
            y1 = y1.max(r.bottom());
66
        }
67
        Rect::new(x0, y0, x1 - x0, y1 - y0)
68
    }
69
70
    pub(crate) fn expanded(&self, by: f64) -> Rect {
71
        Rect::new(
72
            self.x - by,
73
            self.y - by,
74
            self.w + 2.0 * by,
75
            self.h + 2.0 * by,
76
        )
77
    }
78
79
    pub(crate) fn intersects(&self, o: &Rect) -> bool {
80
        self.x < o.right() && o.x < self.right() && self.y < o.bottom() && o.y < self.bottom()
81
    }
82
}
83
84
/// How a window changes between two keyframes.
85
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
86
pub(crate) struct Change {
87
    pub x: bool,
88
    pub y: bool,
89
}
90
91
impl Change {
92
    pub fn between(a: &Rect, b: &Rect) -> Self {
93
        Self {
94
            x: !a.same_x(b),
95
            y: !a.same_y(b),
96
        }
97
    }
98
99
    pub fn moves(&self) -> bool {
100
        self.x || self.y
101
    }
102
103
    pub fn both(&self) -> bool {
104
        self.x && self.y
105
    }
106
}