use crate::core::Rect;
pub fn merge_intersecting_rects(rects: &[Rect]) -> Vec<Rect> {
if rects.is_empty() {
return Vec::new();
}
if rects.len() == 1 {
return rects.to_vec();
}
let mut remaining: Vec<Rect> = rects.to_vec();
let mut merged = Vec::new();
while let Some(mut current) = remaining.pop() {
let mut i = 0;
while i < remaining.len() {
if current.intersects(&remaining[i]) {
current = current.union(&remaining[i]);
remaining.swap_remove(i);
i = 0;
} else {
i += 1;
}
}
merged.push(current);
}
merged
}
pub fn bounding_rect(rects: &[Rect]) -> Option<Rect> {
if rects.is_empty() {
return None;
}
let mut result = rects[0];
for r in &rects[1..] {
result = result.union(r);
}
Some(result)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::Rect;
#[test]
fn test_merge_intersecting_empty() {
assert!(merge_intersecting_rects(&[]).is_empty());
}
#[test]
fn test_merge_intersecting_single() {
let r = Rect::new(10, 10, 50, 50);
assert_eq!(merge_intersecting_rects(&[r]), vec![r]);
}
#[test]
fn test_merge_intersecting_overlap() {
let rects = vec![Rect::new(0, 0, 100, 100), Rect::new(50, 50, 100, 100)];
let merged = merge_intersecting_rects(&rects);
assert_eq!(merged.len(), 1);
assert_eq!(merged[0], Rect::new(0, 0, 150, 150));
}
#[test]
fn test_merge_intersecting_disjoint() {
let rects =
vec![Rect::new(0, 0, 10, 10), Rect::new(100, 100, 10, 10), Rect::new(200, 200, 10, 10)];
let merged = merge_intersecting_rects(&rects);
assert_eq!(merged.len(), 3);
}
#[test]
fn test_bounding_rect_empty() {
assert!(bounding_rect(&[]).is_none());
}
#[test]
fn test_bounding_rect_single() {
let r = Rect::new(5, 5, 20, 20);
assert_eq!(bounding_rect(&[r]), Some(r));
}
#[test]
fn test_bounding_rect_multiple() {
let rects =
vec![Rect::new(0, 0, 10, 10), Rect::new(20, 20, 10, 10), Rect::new(100, 100, 50, 50)];
assert_eq!(bounding_rect(&rects), Some(Rect::new(0, 0, 150, 150)));
}
}