Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "quadtree_rs"
version = "0.1.3"
authors = ["James Adam Buckland <james.adam.buckland@gmail.com>"]
edition = "2018"
edition = "2021"
description = "Point/region Quadtree with support for overlapping regions."

publish = true
Expand All @@ -26,9 +26,9 @@ license = "Apache-2.0"
maintenance = { status = "actively-developed" }

[dependencies]
num = "0.2"
derive_builder = "0.7"
serde = { version = "1.0.152", features = ["derive"], optional=true}
num = "0.4"
derive_builder = "0.12"
serde = { version = "1", features = ["derive"], optional = true }

[features]
serde = ["dep:serde"]
Expand All @@ -39,5 +39,9 @@ serde = ["dep:serde"]
[dev-dependencies.cargo-husky]
version = "1"
default-features = false # Disable features which are enabled by default
features = ["precommit-hook", "run-cargo-test", "run-cargo-clippy", "run-cargo-fmt"]

features = [
"precommit-hook",
"run-cargo-test",
"run-cargo-clippy",
"run-cargo-fmt",
]
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ badge](https://img.shields.io/crates/v/quadtree_rs.svg)](https://crates.io/crate
badge](https://docs.rs/quadtree_rs/badge.svg)](https://docs.rs/quadtree_rs)
[![license](https://img.shields.io/crates/l/quadtree_rs.svg)](https://github.com/ambuc/quadtree/blob/master/LICENSE)

[Point/region Quadtree](https://en.wikipedia.org/wiki/Quadtree) with support for
[Point/region Quadtree](https://en.wikipedia.org/wiki/Quadtree) with support for
overlapping regions.

For documentation, see [docs.rs/quadtree_rs](https://docs.rs/quadtree_rs/).
Expand All @@ -16,9 +16,9 @@ For documentation, see [docs.rs/quadtree_rs](https://docs.rs/quadtree_rs/).
```rust
use quadtree_rs::{area::AreaBuilder, point::Point, Quadtree};

// Instantiate a new quadtree which associates String values with u64
// Instantiate a new quadtree which associates String values with u64
// coordinates.
let mut qt = Quadtree::<u64, String>::new(/*depth=*/4);
let mut qt = Quadtree::new(/*depth=*/4);

// A depth of four means a square with width (and height) 2^4.
assert_eq!(qt.width(), 16);
Expand All @@ -37,7 +37,7 @@ let region_b = AreaBuilder::default()
.build().unwrap();
let mut query = qt.query(region_b);

// The query region (region_b) intersects the region "foo" is associated with
// The query region (region_b) intersects the region "foo" is associated with
// (region_a), so the query iterator returns "foo" by reference.
assert_eq!(query.next().unwrap().value_ref(), "foo");
```
Expand All @@ -60,7 +60,7 @@ This project is licensed under the Apache 2.0 license.

# Disclaimer

This is not an official Google product.
This is not an official Google product.

# TODO
- [ ] Pretty-print quadtree function which plots a density map
Expand Down
1 change: 1 addition & 0 deletions rust-toolchain
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nightly
8 changes: 3 additions & 5 deletions src/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@

//! A rectangular region in the tree.

use crate::point;
use num::PrimInt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use {
crate::point,
num::PrimInt,
std::{cmp::PartialOrd, default::Default, fmt::Debug},
};
use std::{cmp::PartialOrd, default::Default, fmt::Debug};

/// A rectangular region in 2d space.
///
Expand Down
12 changes: 5 additions & 7 deletions src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
//! A view into a single entry in the Quadtree.
// Influenced by https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html.

use crate::{area::Area, point::Point};
use num::PrimInt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use {
crate::{area::Area, point::Point},
num::PrimInt,
std::default::Default,
};
use std::default::Default;

/// A region/value association in the [`Quadtree`].
///
Expand All @@ -34,10 +32,10 @@ use {
/// ```
/// use quadtree_rs::{
/// area::AreaBuilder,
/// Quadtree,
/// HashQuadtree as Quadtree,
/// };
///
/// let mut qt = Quadtree::<u32, f64>::new(4);
/// let mut qt = Quadtree::new(4);
/// let region_a = AreaBuilder::default()
/// .anchor((1, 1).into())
/// .dimensions((3, 2))
Expand Down
10 changes: 4 additions & 6 deletions src/handle_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use {
crate::{area::Area, qtinner::QTInner, traversal::Traversal},
num::PrimInt,
std::{collections::HashSet, default::Default, iter::FusedIterator},
};
use crate::{area::Area, qtinner::QTInner, traversal::Traversal};
use num::PrimInt;
use std::{collections::HashSet, default::Default, iter::FusedIterator};

#[derive(Clone, Debug)]
pub(crate) struct HandleIter<'a, U>
where
U: PrimInt + Default,
U: PrimInt + Default + 'static,
{
search_area: Area<U>,
handle_stack: Vec<u64>,
Expand Down
116 changes: 77 additions & 39 deletions src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use {
crate::{
area::Area, entry::Entry, handle_iter::HandleIter, qtinner::QTInner, traversal::Traversal,
types::StoreType,
},
num::PrimInt,
std::iter::FusedIterator,
use crate::{
area::Area, entry::Entry, handle_iter::HandleIter, map::Map, qtinner::QTInner,
traversal::Traversal,
};
use num::PrimInt;
use std::{iter::FusedIterator, marker::PhantomData};

/// An iterator over all regions and values of a [`Quadtree`].
///
Expand All @@ -28,29 +26,35 @@ use {
/// [`iter`]: ../struct.Quadtree.html#method.iter
/// [`Quadtree`]: ../struct.Quadtree.html
#[derive(Clone, Debug)]
pub struct Iter<'a, U, V>
pub struct Iter<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
{
store: &'a StoreType<U, V>,
store: &'a M,
handle_iter: HandleIter<'a, U>,
_v: PhantomData<V>,
}

impl<'a, U, V> Iter<'a, U, V>
impl<'a, U, V, M> Iter<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
{
pub(crate) fn new(qt: &'a QTInner<U>, store: &'a StoreType<U, V>) -> Iter<'a, U, V> {
pub(crate) fn new(qt: &'a QTInner<U>, store: &'a M) -> Self {
Iter {
store,
handle_iter: HandleIter::new(qt, qt.region()),
_v: Default::default(),
}
}
}

impl<'a, U, V> Iterator for Iter<'a, U, V>
impl<'a, U, V, M> Iterator for Iter<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
type Item = &'a Entry<U, V>;

Expand All @@ -59,7 +63,7 @@ where
match self.handle_iter.next() {
Some(handle) => Some(
self.store
.get(&handle)
.get(handle)
.expect("Shouldn't have an handle in the tree which isn't in the store."),
),
None => None,
Expand All @@ -72,7 +76,13 @@ where
}
}

impl<U, V> FusedIterator for Iter<'_, U, V> where U: PrimInt + Default {}
impl<'a, U, V, M> FusedIterator for Iter<'a, U, V, M>
where
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
}

/// A consuming iterator over all region/value associations held in a [`Quadtree`].
///
Expand Down Expand Up @@ -114,26 +124,27 @@ impl<U, V> FusedIterator for IntoIter<U, V> where U: PrimInt + Default {}
/// [`query`]: ../struct.Quadtree.html#method.query
/// [`Quadtree`]: ../struct.Quadtree.html
#[derive(Clone, Debug)]
pub struct Query<'a, U, V>
pub struct Query<'a, U, V, M>
where
U: PrimInt + Default,
U: PrimInt + Default + 'static,
{
query_region: Area<U>,
handle_iter: HandleIter<'a, U>,
store: &'a StoreType<U, V>,
store: &'a M,
traversal_method: Traversal,
_v: PhantomData<V>,
}

impl<'a, U, V> Query<'a, U, V>
impl<'a, U, V, M> Query<'a, U, V, M>
where
U: PrimInt + Default,
{
pub(crate) fn new(
query_region: Area<U>,
qt: &'a QTInner<U>,
store: &'a StoreType<U, V>,
store: &'a M,
traversal_method: Traversal,
) -> Query<'a, U, V>
) -> Self
where
U: PrimInt + Default,
{
Expand All @@ -150,19 +161,22 @@ where
handle_iter,
store,
traversal_method,
_v: Default::default(),
}
}
}

impl<'a, U, V> Iterator for Query<'a, U, V>
impl<'a, U, V, M> Iterator for Query<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
type Item = &'a Entry<U, V>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for handle in self.handle_iter.by_ref() {
if let Some(entry) = self.store.get(&handle) {
if let Some(entry) = self.store.get(handle) {
if self.traversal_method.eval(entry.area(), self.query_region) {
return Some(entry);
}
Expand All @@ -177,7 +191,13 @@ where
}
}

impl<U, V> FusedIterator for Query<'_, U, V> where U: PrimInt + Default {}
impl<'a, U, V, M> FusedIterator for Query<'a, U, V, M>
where
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
}

/// An iterator over the values held within a [`Quadtree`].
///
Expand All @@ -186,16 +206,19 @@ impl<U, V> FusedIterator for Query<'_, U, V> where U: PrimInt + Default {}
/// [`values`]: ../struct.Quadtree.html#method.values
/// [`Quadtree`]: ../struct.Quadtree.html
#[derive(Clone, Debug)]
pub struct Values<'a, U, V>
pub struct Values<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
{
pub(crate) inner: Iter<'a, U, V>,
pub(crate) inner: Iter<'a, U, V, M>,
}

impl<'a, U, V> Iterator for Values<'a, U, V>
impl<'a, U, V, M> Iterator for Values<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
type Item = &'a V;

Expand All @@ -210,7 +233,13 @@ where
}
}

impl<U, V> FusedIterator for Values<'_, U, V> where U: PrimInt + Default {}
impl<'a, U, V, M> FusedIterator for Values<'a, U, V, M>
where
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
}

/// An iterator over the regions held within a [`Quadtree`].
///
Expand All @@ -219,16 +248,19 @@ impl<U, V> FusedIterator for Values<'_, U, V> where U: PrimInt + Default {}
/// [`regions`]: ../struct.Quadtree.html#method.regions
/// [`Quadtree`]: ../struct.Quadtree.html
#[derive(Clone, Debug)]
pub struct Regions<'a, U, V>
pub struct Regions<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
{
pub(crate) inner: Iter<'a, U, V>,
pub(crate) inner: Iter<'a, U, V, M>,
}

impl<'a, U, V> Iterator for Regions<'a, U, V>
impl<'a, U, V, M> Iterator for Regions<'a, U, V, M>
where
U: PrimInt + Default,
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
type Item = Area<U>;

Expand All @@ -243,4 +275,10 @@ where
}
}

impl<U, V> FusedIterator for Regions<'_, U, V> where U: PrimInt + Default {}
impl<'a, U, V, M> FusedIterator for Regions<'a, U, V, M>
where
M: Map<U, V>,
U: PrimInt + Default + 'static,
V: 'a,
{
}
Loading