use {
crate::{area::Area, qtinner::QTInner, traversal::Traversal},
num::PrimInt,
std::{collections::HashSet, default::Default, iter::FusedIterator},
};
#[derive(Clone, Debug)]
pub(crate) struct HandleIter<'a, U>
where
U: PrimInt + Default,
{
search_area: Area<U>,
handle_stack: Vec<u64>,
qt_stack: Vec<&'a QTInner<U>>,
visited: HashSet<u64>,
}
impl<'a, U> HandleIter<'a, U>
where
U: PrimInt + Default,
{
pub(crate) fn new(qt: &'a QTInner<U>, search_area: Area<U>) -> HandleIter<'a, U> {
HandleIter {
search_area,
handle_stack: vec![],
qt_stack: vec![qt],
visited: HashSet::new(),
}
}
pub(crate) fn query_optimization(&mut self, req: Area<U>, traversal_method: Traversal) {
assert!(self.qt_stack.len() == 1);
assert!(self.handle_stack.is_empty());
assert!(self.visited.is_empty());
self.descend_recurse_step(req, traversal_method);
}
fn descend_recurse_step(&mut self, req: Area<U>, traversal_method: Traversal) {
assert!(self.qt_stack.len() == 1);
if let Some(qt) = self.qt_stack.last() {
if !qt.region().contains(req) {
return;
}
assert!(qt.region().contains(req));
if let Some(subquadrants) = qt.subquadrants().as_ref() {
for subquadrant in subquadrants.iter() {
if subquadrant.region().contains(req) {
if traversal_method == Traversal::Overlapping {
self.handle_stack.extend(qt.handles());
}
assert!(self.qt_stack.len() == 1);
self.qt_stack = vec![subquadrant];
return self.descend_recurse_step(req, traversal_method);
}
}
}
}
}
}
impl<U> Iterator for HandleIter<'_, U>
where
U: PrimInt + Default,
{
type Item = u64;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
while let Some(handle) = self.handle_stack.pop() {
if self.visited.insert(handle) {
return Some(handle);
}
}
if let Some(qt) = self.qt_stack.pop() {
if let Some(sub_quadrants) = qt.subquadrants().as_ref() {
for sub_quadrant in sub_quadrants {
if sub_quadrant.region().intersects(self.search_area) {
self.qt_stack.push(sub_quadrant)
}
}
}
match qt.handles().len() {
0 => (),
1 => {
if self.visited.insert(qt.handles()[0]) {
return Some(qt.handles()[0]);
}
}
_ => self.handle_stack.extend(qt.handles()),
}
continue;
}
return None;
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
impl<U> FusedIterator for HandleIter<'_, U> where U: PrimInt + Default {}