use crate::aabb::Aabb; use std::collections::HashSet; pub struct QuadTree { bounding_box: Aabb, depth: usize, inner_node_capacity: usize, subtrees: Option; 4]>>, pairs: Vec<(Aabb, T)>, } impl QuadTree { pub fn new(bounding_box: Aabb, depth: usize, inner_node_capacity: usize) -> Self { QuadTree { bounding_box, depth, inner_node_capacity, subtrees: None, pairs: Vec::new(), } } pub fn insert(&mut self, bounding_box: Aabb, value: T) -> bool { if !crate::aabb::bounding_boxes_overlap(&bounding_box, &self.bounding_box) { return false; } if self.depth > 0 && self.pairs.len() >= self.inner_node_capacity { self.ensure_subtrees(); for tree in self.subtrees.as_mut().unwrap().iter_mut() { tree.insert(bounding_box, value.clone()); } } else { self.pairs.push((bounding_box, value)); } true } pub fn find(&self, bounding_box: &Aabb) -> HashSet where T: Eq + std::hash::Hash + Clone, { let mut set = HashSet::new(); self.find_internal(bounding_box, &mut set); set } fn find_internal(&self, bounding_box: &Aabb, set: &mut HashSet) where T: Eq + std::hash::Hash + Clone, { if !crate::aabb::bounding_boxes_overlap(bounding_box, &self.bounding_box) { return; } for (key, value) in &self.pairs { if crate::aabb::bounding_boxes_overlap(bounding_box, key) { set.insert(value.clone()); } } if let Some(subtrees) = &self.subtrees { for tree in subtrees.iter() { tree.find_internal(bounding_box, set); } } } fn ensure_subtrees(&mut self) { if self.subtrees.is_some() { return; } let mid_x = (self.bounding_box.left + self.bounding_box.right) / 2.; let mid_y = (self.bounding_box.top + self.bounding_box.bottom) / 2.; self.subtrees = Some(Box::new([ QuadTree::new( Aabb { top: self.bounding_box.top, right: mid_x, bottom: mid_y, left: self.bounding_box.left, }, self.depth - 1, self.inner_node_capacity, ), QuadTree::new( Aabb { top: self.bounding_box.top, right: self.bounding_box.right, bottom: mid_y, left: mid_x, }, self.depth - 1, self.inner_node_capacity, ), QuadTree::new( Aabb { top: mid_y, right: mid_x, bottom: self.bounding_box.bottom, left: self.bounding_box.left, }, self.depth - 1, self.inner_node_capacity, ), QuadTree::new( Aabb { top: mid_y, right: self.bounding_box.right, bottom: self.bounding_box.bottom, left: mid_x, }, self.depth - 1, self.inner_node_capacity, ), ])); } }