#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BBox {
pub left: f32,
pub right: f32,
pub top: f32,
pub bottom: f32,
}
impl BBox {
pub fn height(&self) -> f32 {
(self.top - self.bottom).max(0.0)
}
pub fn width(&self) -> f32 {
(self.right - self.left).max(0.0)
}
pub fn x_center(&self) -> f32 {
(self.left + self.right) / 2.0
}
pub fn y_center(&self) -> f32 {
(self.top + self.bottom) / 2.0
}
pub fn empty() -> Self {
Self {
left: 0.0,
right: 0.0,
top: 0.0,
bottom: 0.0,
}
}
pub(super) fn merge(self, other: BBox) -> BBox {
BBox {
left: self.left.min(other.left),
right: self.right.max(other.right),
top: self.top.max(other.top),
bottom: self.bottom.min(other.bottom),
}
}
}
pub trait Bounded {
fn bbox(&self) -> BBox;
fn char_count(&self) -> usize {
let w = self.bbox().width();
if w <= 0.0 {
0
} else {
(w / 5.0).round().max(0.0) as usize
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SplitDir {
Vertical,
Horizontal,
}
#[derive(Debug)]
pub enum Zone<T: Bounded> {
Leaf {
bbox: BBox,
items: Vec<T>,
},
Split {
dir: SplitDir,
bbox: BBox,
children: Vec<Zone<T>>,
},
Table {
bbox: BBox,
rows: Vec<Vec<Zone<T>>>,
},
}
impl<T: Bounded> Zone<T> {
pub fn bbox(&self) -> BBox {
match self {
Zone::Leaf { bbox, .. } => *bbox,
Zone::Split { bbox, .. } => *bbox,
Zone::Table { bbox, .. } => *bbox,
}
}
pub fn item_count(&self) -> usize {
match self {
Zone::Leaf { items, .. } => items.len(),
Zone::Split { children, .. } => children.iter().map(|c| c.item_count()).sum(),
Zone::Table { rows, .. } => rows
.iter()
.flat_map(|r| r.iter())
.map(|c| c.item_count())
.sum(),
}
}
pub fn leaf_count(&self) -> usize {
match self {
Zone::Leaf { .. } => 1,
Zone::Split { children, .. } => children.iter().map(|c| c.leaf_count()).sum(),
Zone::Table { rows, .. } => rows
.iter()
.flat_map(|r| r.iter())
.map(|c| c.leaf_count())
.sum(),
}
}
}