#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use {
crate::{
area::{Area, AreaBuilder},
entry::Entry,
point::Point,
types::StoreType,
},
num::PrimInt,
std::{default::Default, fmt::Debug},
};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct QTInner<U>
where
U: PrimInt + Default,
{
depth: usize,
region: Area<U>,
kept_handles: Vec<u64>,
subquadrants: Option<[Box<QTInner<U>>; 4]>,
handle_counter: u64,
}
impl<U> Debug for QTInner<U>
where
U: PrimInt + Default + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if self.subquadrants.is_some() {
write!(
f,
"{:?} :: {:?} {:#?}",
self.region,
self.kept_handles,
self.subquadrants.as_ref().unwrap()
)
} else {
write!(f, "{:?} :: {:?}", self.region, self.kept_handles,)
}
}
}
impl<U> QTInner<U>
where
U: PrimInt + Default,
{
pub fn new(anchor: Point<U>, depth: usize) -> Self {
#[allow(clippy::cast_possible_truncation)]
let width: U = Self::two().pow(depth as u32);
let height: U = width;
Self::new_with_area(
AreaBuilder::default()
.anchor(anchor)
.dimensions((width, height))
.build()
.expect("Unexpected error in QTInner::new()."),
depth,
)
}
pub fn depth(&self) -> usize {
self.depth
}
pub fn region(&self) -> Area<U> {
self.region
}
pub fn handles(&self) -> &Vec<u64> {
&self.kept_handles
}
pub fn subquadrants(&self) -> &Option<[Box<Self>; 4]> {
&self.subquadrants
}
pub fn reset(&mut self) {
self.kept_handles.clear();
self.subquadrants = None;
}
pub fn insert_val_at_region<V>(
&mut self,
req: Area<U>,
val: V,
store: &mut StoreType<U, V>,
) -> u64 {
let handle = self.handle_counter;
self.handle_counter += 1;
store.insert(handle, Entry::new((req, val), handle));
self.insert_handle_at_region(req, handle, store);
handle
}
pub fn delete_by_handle(&mut self, handle: u64, req: Area<U>) {
self.kept_handles.retain(|&x| x != handle);
if let Some(sqs) = self.subquadrants.as_mut() {
for sq in sqs.iter_mut() {
if sq.region.intersects(req) {
sq.delete_by_handle(handle, req);
}
}
}
}
fn new_with_area(region: Area<U>, depth: usize) -> Self {
Self {
depth,
region,
kept_handles: Vec::new(),
subquadrants: None,
handle_counter: 0_u64,
}
}
fn insert_handle_at_region<V>(
&mut self,
req: Area<U>,
handle: u64,
_store: &mut StoreType<U, V>,
) {
if self.depth == 0 {
self.kept_handles.push(handle);
return;
}
if req.contains(self.region) {
self.kept_handles.push(handle);
return;
}
if req == self.region {
self.kept_handles.push(handle);
return;
}
if self.subquadrants.is_none() {
self.expand_subquadrants_by_pt(self.region.center_pt());
}
assert!(self.subquadrants.is_some());
if let Some(sqs) = self.subquadrants.as_mut() {
for sq in sqs.iter_mut() {
if sq.region.intersects(req) {
sq.insert_handle_at_region(req, handle, _store);
}
}
}
}
fn expand_subquadrants_by_pt(&mut self, p: Point<U>) {
assert!(self.region.contains_pt(p));
self.subquadrants = Some([
Box::new(Self::new(
Point {
x: p.x(),
y: self.region.anchor().y(),
},
self.depth - 1,
)),
Box::new(Self::new(self.region.anchor(), self.depth - 1)),
Box::new(Self::new(p, self.depth - 1)),
Box::new(Self::new(
Point {
x: self.region.anchor().x(),
y: p.y(),
},
self.depth - 1,
)),
]);
}
fn two() -> U {
U::one() + U::one()
}
}