use crate::{Rectangle, Serialize, Deserialize};
pub trait Vector<Rhs = Self>: Clone + PartialEq + std::fmt::Debug {
fn as_point(&self) -> (u32, u32);
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct QuadTree<T: Vector> {
boundary: Rectangle,
capacity: usize,
points: Vec<T>,
children: Option<[Box<QuadTree<T>>; 4]>,
}
impl<'a, T: Vector> QuadTree<T> {
pub fn new(boundary: Rectangle, capacity: usize) -> Self {
Self {
boundary,
capacity,
points: Vec::with_capacity(capacity as usize),
children: None,
}
}
fn subdivide(boundary: Rectangle, capacity: usize) -> [Box<QuadTree<T>>; 4] {
let x = boundary.x;
let y = boundary.y;
let w = boundary.w / 2;
let h = boundary.h / 2;
let nw = Rectangle::new(x, y, w, h);
let ne = Rectangle::new(x + w, y, w, h);
let sw = Rectangle::new(x, y + h, w, h);
let se = Rectangle::new(x + w, y + h, w, h);
[
Box::new(QuadTree::new(nw, capacity)),
Box::new(QuadTree::new(ne, capacity)),
Box::new(QuadTree::new(sw, capacity)),
Box::new(QuadTree::new(se, capacity)),
]
}
pub fn replace(&mut self, item: &T) -> Option<T> {
if !self.boundary.contains(item) {
return None;
}
if let Some(idx) = self.points.iter().position(|x| x.as_point() == item.as_point()) {
let old_item = self.points.remove(idx);
self.points.push(item.clone());
return Some(old_item);
}
self.children
.iter_mut()
.flatten()
.find_map(|child| child.replace(item))
}
pub fn insert(&mut self, item: &T) -> bool {
if !self.boundary.contains(item) {
return false;
}
if self.points.len() < self.capacity as usize && !self.points.contains(item) {
self.points.push(item.clone());
return true;
}
if self.points.len() == self.capacity {
let (b, c) = (self.boundary, self.capacity);
return self.children
.get_or_insert_with(move || Self::subdivide(b, c))
.iter_mut()
.any(|c| c.insert(item));
}
false
}
pub fn remove(&mut self, item: &T) -> bool {
if self.points.contains(item) {
self.points = self.points.iter().filter(|p| *p != item).map(Clone::clone).collect();
return true;
}
if let Some(c) = &mut self.children {
for child in c.iter_mut() {
if child.remove(item) {
return true;
}
}
}
false
}
pub fn query_mut<F: FnMut(&mut T)>(&mut self, _range: &Rectangle, _func: &mut F) {
todo!();
}
pub fn query<F: FnMut(&T)>(&self, range: Option<&Rectangle>, func: &mut F) {
let range = range.unwrap_or(&self.boundary);
if !range.intersects(&self.boundary) {
return;
}
for p in &self.points {
if range.contains(p) {
func(p);
}
}
if let Some(c) = self.children.as_ref() { c.iter().for_each(|c| c.query(Some(&range), func)) }
}
pub fn len(&self) -> usize {
self.points.len()
+ self
.children
.as_ref()
.map(|c| c.iter().fold(0, |x, c| x + c.len()))
.unwrap_or(0)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn contains(&self, item: &T) -> bool {
if self.points.contains(item) {
return true;
}
if let Some(child) = &self.children {
return child.iter().any(|ch| ch.contains(item));
}
false
}
pub fn iter() {
todo!();
}
pub fn iter_mut() {
todo!();
}
pub fn into_iter() {
todo!();
}
}