#![doc(test(attr(deny(warnings))))]
#[macro_use]
extern crate derive_builder;
extern crate num;
pub mod area;
pub mod entry;
pub mod iter;
pub mod point;
mod handle_iter;
mod qtinner;
mod traversal;
mod types;
use {
crate::{
area::{Area, AreaBuilder},
entry::Entry,
handle_iter::HandleIter,
iter::{IntoIter, Iter, Query, Regions, Values},
point::Point,
qtinner::QTInner,
traversal::Traversal,
types::StoreType,
},
num::PrimInt,
std::{
collections::{HashMap, HashSet},
default::Default,
hash::Hash,
},
};
#[derive(Debug, PartialEq, Eq)]
pub struct Quadtree<U, V>
where
U: PrimInt + Default,
{
inner: QTInner<U>,
store: StoreType<U, V>,
}
impl<U, V> Quadtree<U, V>
where
U: PrimInt + Default,
{
pub fn new(depth: usize) -> Self {
Self::new_with_anchor(
point::Point {
x: U::zero(),
y: U::zero(),
},
depth,
)
}
pub fn new_with_anchor(anchor: point::Point<U>, depth: usize) -> Self {
Self {
inner: QTInner::new(anchor, depth),
store: HashMap::new(),
}
}
pub fn anchor(&self) -> point::Point<U> {
self.inner.region().anchor()
}
pub fn width(&self) -> usize {
self.inner.region().width().to_usize().unwrap()
}
pub fn height(&self) -> usize {
self.inner.region().height().to_usize().unwrap()
}
pub fn depth(&self) -> usize {
self.inner.depth()
}
pub fn len(&self) -> usize {
self.store.len()
}
pub fn is_empty(&self) -> bool {
self.store.is_empty()
}
pub fn contains(&self, area: Area<U>) -> bool {
self.inner.region().contains(area)
}
pub fn insert(&mut self, region: Area<U>, val: V) -> Option<u64> {
if self.contains(region) {
return Some(
self.inner
.insert_val_at_region(region, val, &mut self.store),
);
}
None
}
pub fn insert_pt(&mut self, point: Point<U>, val: V) -> Option<u64> {
if let Ok(area) = AreaBuilder::default().anchor(point).build() {
return self.insert(area, val);
}
None
}
pub fn get(&self, handle: u64) -> Option<&Entry<U, V>> {
self.store.get(&handle)
}
pub fn get_mut(&mut self, handle: u64) -> Option<&mut Entry<U, V>> {
self.store.get_mut(&handle)
}
pub fn query(&self, area: Area<U>) -> Query<U, V> {
Query::new(area, &self.inner, &self.store, Traversal::Overlapping)
}
pub fn query_strict(&self, area: Area<U>) -> Query<U, V> {
Query::new(area, &self.inner, &self.store, Traversal::Strict)
}
pub fn modify<F>(&mut self, area: Area<U>, f: F)
where
F: Fn(&mut V) + Copy,
{
self.modify_region(|a| a.intersects(area), f);
}
pub fn modify_strict<F>(&mut self, area: Area<U>, f: F)
where
F: Fn(&mut V) + Copy,
{
self.modify_region(|a| area.contains(a), f);
}
pub fn modify_all<F>(&mut self, f: F)
where
F: Fn(&mut V) + Copy,
{
for entry in self.store.values_mut() {
f(&mut entry.value_mut());
}
}
pub fn reset(&mut self) {
self.store.clear();
self.inner.reset();
}
pub fn delete(&mut self, area: Area<U>) -> IntoIter<U, V> {
self.delete_handles_and_return(self.query(area).map(|e| e.handle()).collect())
}
pub fn delete_strict(&mut self, area: Area<U>) -> IntoIter<U, V> {
self.delete_handles_and_return(self.query_strict(area).map(|e| e.handle()).collect())
}
#[allow(clippy::needless_pass_by_value)]
fn delete_handles_and_return(&mut self, handles: HashSet<u64>) -> IntoIter<U, V> {
let error: &'static str = "I tried to look up an handle in the store which I found in the tree, but it wasn't there!";
let mut entries: Vec<Entry<U, V>> = vec![];
handles.iter().for_each(|u| {
entries.push(self.store.remove(u).expect(&error));
});
IntoIter { entries }
}
pub fn delete_by_handle(&mut self, handle: u64) -> Option<Entry<U, V>> {
if let Some(entry) = self.store.remove(&handle) {
self.inner.delete_by_handle(handle, entry.area());
return Some(entry);
}
None
}
pub fn retain<F>(&mut self, mut f: F) -> IntoIter<U, V>
where
F: FnMut(&mut V) -> bool,
U: Hash,
{
let mut doomed: HashSet<(u64, Area<U>)> = HashSet::new();
for (handle, entry) in &mut self.store {
if f(entry.value_mut()) {
doomed.insert((*handle, entry.area()));
}
}
let mut entries: Vec<Entry<U, V>> = vec![];
for (handle, region) in doomed {
entries.push(self.store.remove(&handle).unwrap());
self.inner.delete_by_handle(handle, region);
}
IntoIter { entries }
}
pub fn iter(&self) -> Iter<U, V> {
Iter::new(&self.inner, &self.store)
}
pub fn regions(&self) -> Regions<U, V> {
Regions {
inner: Iter::new(&self.inner, &self.store),
}
}
pub fn values(&self) -> Values<U, V> {
Values {
inner: Iter::new(&self.inner, &self.store),
}
}
fn modify_region<F, M>(&mut self, filter: F, modify: M)
where
F: Fn(Area<U>) -> bool,
M: Fn(&mut V) + Copy,
{
let relevant_handles: Vec<u64> = HandleIter::new(&self.inner).collect();
for i in relevant_handles {
if let Some(entry) = self.store.get_mut(&i) {
if filter(entry.area()) {
modify(&mut entry.value_mut());
}
}
}
}
}
impl<U, V> Extend<(point::Type<U>, V)> for Quadtree<U, V>
where
U: PrimInt + Default,
{
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = (point::Type<U>, V)>,
{
for ((x, y), val) in iter {
self.insert(
AreaBuilder::default()
.anchor(point::Point { x, y })
.build()
.unwrap(),
val,
);
}
}
}
impl<'a, U, V> IntoIterator for &'a Quadtree<U, V>
where
U: PrimInt + Default,
{
type Item = &'a Entry<U, V>;
type IntoIter = Iter<'a, U, V>;
fn into_iter(self) -> Iter<'a, U, V> {
Iter::new(&self.inner, &self.store)
}
}
impl<U, V> IntoIterator for Quadtree<U, V>
where
U: PrimInt + Default,
{
type Item = Entry<U, V>;
type IntoIter = IntoIter<U, V>;
fn into_iter(self) -> IntoIter<U, V> {
IntoIter {
entries: self
.store
.into_iter()
.map(|(_handle, entry)| entry)
.collect(),
}
}
}