Skip to main content

dumap_layout/
rect.rs

1/// A rectangle in layout space (f64 for precision during subdivision).
2#[derive(Debug, Clone, Copy, PartialEq)]
3pub struct LayoutRect {
4    pub x: f64,
5    pub y: f64,
6    pub w: f64,
7    pub h: f64,
8}
9
10impl LayoutRect {
11    pub fn new(x: f64, y: f64, w: f64, h: f64) -> Self {
12        Self { x, y, w, h }
13    }
14
15    pub fn area(&self) -> f64 {
16        self.w * self.h
17    }
18
19    pub fn shorter_side(&self) -> f64 {
20        self.w.min(self.h)
21    }
22
23    pub fn is_wide(&self) -> bool {
24        self.w >= self.h
25    }
26
27    /// Whether this rect is large enough to be visible.
28    pub fn is_visible(&self, min_dimension: f64) -> bool {
29        self.w >= min_dimension && self.h >= min_dimension
30    }
31
32    /// Inset the rectangle by `amount` on all sides. Returns a zero-area rect
33    /// if the inset would collapse it.
34    pub fn inset(&self, amount: f64) -> Self {
35        let double = amount * 2.0;
36        if self.w <= double || self.h <= double {
37            return Self {
38                x: self.x + self.w / 2.0,
39                y: self.y + self.h / 2.0,
40                w: 0.0,
41                h: 0.0,
42            };
43        }
44        Self {
45            x: self.x + amount,
46            y: self.y + amount,
47            w: self.w - double,
48            h: self.h - double,
49        }
50    }
51
52    /// Split off a strip from the shorter side direction.
53    /// `fraction` is the proportion of area the strip occupies (0..1).
54    /// Returns (strip, remainder).
55    pub fn split_strip(&self, fraction: f64) -> (Self, Self) {
56        let fraction = fraction.clamp(0.0, 1.0);
57        if self.is_wide() {
58            // Split vertically — strip on the left
59            let strip_w = self.w * fraction;
60            let strip = Self {
61                x: self.x,
62                y: self.y,
63                w: strip_w,
64                h: self.h,
65            };
66            let remainder = Self {
67                x: self.x + strip_w,
68                y: self.y,
69                w: self.w - strip_w,
70                h: self.h,
71            };
72            (strip, remainder)
73        } else {
74            // Split horizontally — strip on top
75            let strip_h = self.h * fraction;
76            let strip = Self {
77                x: self.x,
78                y: self.y,
79                w: self.w,
80                h: strip_h,
81            };
82            let remainder = Self {
83                x: self.x,
84                y: self.y + strip_h,
85                w: self.w,
86                h: self.h - strip_h,
87            };
88            (strip, remainder)
89        }
90    }
91}
92
93#[cfg(test)]
94#[path = "rect_tests.rs"]
95mod rect_tests;