#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Geometry {
pub cols: u32,
pub rows: u32,
pub px_w: u32,
pub px_h: u32,
pub cell_px_w: u32,
pub cell_px_h: u32,
}
impl Geometry {
pub const fn cells(cols: u32, rows: u32, cell_px: (u32, u32)) -> Self {
Self {
cols,
rows,
px_w: cols * cell_px.0,
px_h: rows * cell_px.1,
cell_px_w: cell_px.0,
cell_px_h: cell_px.1,
}
}
pub const fn is_empty(&self) -> bool {
self.cols == 0 || self.rows == 0
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Rect {
pub x: u32,
pub y: u32,
pub w: u32,
pub h: u32,
}
impl Rect {
pub const fn new(x: u32, y: u32, w: u32, h: u32) -> Self {
Self { x, y, w, h }
}
pub const fn is_empty(&self) -> bool {
self.w == 0 || self.h == 0
}
pub const fn right(&self) -> u32 {
self.x.saturating_add(self.w)
}
pub const fn bottom(&self) -> u32 {
self.y.saturating_add(self.h)
}
pub const fn area(&self) -> u64 {
self.w as u64 * self.h as u64
}
pub fn clamp(self, width: u32, height: u32) -> Option<Self> {
let right = self.right().min(width);
let bottom = self.bottom().min(height);
(self.x < right && self.y < bottom).then(|| Self {
x: self.x,
y: self.y,
w: right - self.x,
h: bottom - self.y,
})
}
pub fn contains_rect(&self, other: &Self) -> bool {
other.x >= self.x
&& other.y >= self.y
&& other.right() <= self.right()
&& other.bottom() <= self.bottom()
}
pub fn union(&self, other: &Self) -> Self {
let x = self.x.min(other.x);
let y = self.y.min(other.y);
Self {
x,
y,
w: self.right().max(other.right()) - x,
h: self.bottom().max(other.bottom()) - y,
}
}
}