use {
crate::{area::Area, qtinner::QTInner, traversal::Traversal},
num::PrimInt,
std::{collections::HashSet, default::Default, iter::FusedIterator, ops::Deref},
};
#[derive(Clone, Debug)]
pub(crate) struct HandleIter<'a, U>
where
U: PrimInt + Default,
{
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>) -> HandleIter<'a, U> {
HandleIter {
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);
}
}
}
return;
}
}
}
impl<U> Iterator for HandleIter<'_, U>
where
U: PrimInt + Default,
{
type Item = u64;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let Some(handle) = self.handle_stack.pop() {
if !self.visited.insert(handle) {
return self.next();
}
return Some(handle);
}
if let Some(qt) = self.qt_stack.pop() {
self.handle_stack.extend(qt.handles());
if let Some(subquadrants) = qt.subquadrants().as_ref() {
self.qt_stack.extend(subquadrants.iter().map(|x| x.deref()));
}
return self.next();
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
impl<U> FusedIterator for HandleIter<'_, U> where U: PrimInt + Default {}