Skip to content

Commit

Permalink
Add geo-traits integration (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron authored Dec 25, 2024
1 parent 256312f commit 1f45cce
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 3 deletions.
30 changes: 30 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ categories = ["data-structures", "algorithms", "science::geo"]
[dependencies]
bytemuck = "1"
float_next_after = "1"
geo-traits = "0.2"
num-traits = "0.2"
rayon = { version = "1.8.0", optional = true }
thiserror = "1"
Expand Down
31 changes: 30 additions & 1 deletion src/kdtree/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ use std::cmp;
use std::marker::PhantomData;

use bytemuck::cast_slice_mut;
use geo_traits::{CoordTrait, PointTrait};

use crate::error::Result;
use crate::indices::MutableIndices;
use crate::kdtree::constants::{KDBUSH_HEADER_SIZE, KDBUSH_MAGIC, KDBUSH_VERSION};
use crate::kdtree::OwnedKDTree;
use crate::r#type::IndexableNum;
use crate::GeoIndexError;

const DEFAULT_NODE_SIZE: u16 = 64;

Expand Down Expand Up @@ -68,7 +71,10 @@ impl<N: IndexableNum> KDTreeBuilder<N> {
}
}

/// Add a point to the index.
/// Add a point to the KDTree.
///
/// This returns a positional index that provides a lookup back into the original data.
#[inline]
pub fn add(&mut self, x: N, y: N) -> usize {
let index = self.pos >> 1;
let (coords, mut ids) = split_data_borrow(
Expand All @@ -88,6 +94,29 @@ impl<N: IndexableNum> KDTreeBuilder<N> {
index
}

/// Add a coord to the KDTree.
///
/// This returns a positional index that provides a lookup back into the original data.
#[inline]
pub fn add_coord(&mut self, coord: &impl CoordTrait<T = N>) -> usize {
self.add(coord.x(), coord.y())
}

/// Add a point to the KDTree.
///
/// This returns a positional index that provides a lookup back into the original data.
///
/// ## Errors
///
/// - If the point is empty.
#[inline]
pub fn add_point(&mut self, point: &impl PointTrait<T = N>) -> Result<usize> {
let coord = point.coord().ok_or(GeoIndexError::General(
"Unable to add empty point to KDTree".to_string(),
))?;
Ok(self.add_coord(&coord))
}

/// Consume this builder, perfoming the k-d sort and generating a KDTree ready for queries.
pub fn finish(mut self) -> OwnedKDTree<N> {
assert_eq!(
Expand Down
23 changes: 23 additions & 0 deletions src/kdtree/trait.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;

use geo_traits::{CoordTrait, RectTrait};
use tinyvec::TinyVec;

use crate::indices::Indices;
Expand Down Expand Up @@ -80,6 +81,18 @@ pub trait KDTreeIndex<N: IndexableNum> {
result
}

/// Search the index for items within a given bounding box.
///
/// Returns indices of found items
fn range_rect(&self, rect: &impl RectTrait<T = N>) -> Vec<usize> {
self.range(
rect.min().x(),
rect.min().y(),
rect.max().x(),
rect.max().y(),
)
}

/// Search the index for items within a given radius.
///
/// - qx: x value of query point
Expand Down Expand Up @@ -144,6 +157,16 @@ pub trait KDTreeIndex<N: IndexableNum> {
}
result
}

/// Search the index for items within a given radius.
///
/// - coord: coordinate of query point
/// - r: radius
///
/// Returns indices of found items
fn within_coord(&self, coord: &impl CoordTrait<T = N>, r: N) -> Vec<usize> {
self.within(coord.x(), coord.y(), r)
}
}

impl<N: IndexableNum> KDTreeIndex<N> for KDTreeRef<'_, N> {
Expand Down
18 changes: 17 additions & 1 deletion src/rtree/builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bytemuck::cast_slice_mut;
use geo_traits::{CoordTrait, RectTrait};

use crate::indices::MutableIndices;
use crate::r#type::IndexableNum;
Expand Down Expand Up @@ -73,7 +74,9 @@ impl<N: IndexableNum> RTreeBuilder<N> {
}
}

/// Add a given rectangle to the index.
/// Add a given rectangle to the RTree.
///
/// This returns a positional index that provides a lookup back into the original data.
#[inline]
pub fn add(&mut self, min_x: N, min_y: N, max_x: N, max_y: N) -> usize {
let index = self.pos >> 2;
Expand Down Expand Up @@ -110,6 +113,19 @@ impl<N: IndexableNum> RTreeBuilder<N> {
index
}

/// Add a given rectangle to the RTree.
///
/// This returns a positional index that provides a lookup back into the original data.
#[inline]
pub fn add_rect(&mut self, rect: &impl RectTrait<T = N>) -> usize {
self.add(
rect.min().x(),
rect.min().y(),
rect.max().x(),
rect.max().y(),
)
}

/// Consume this builder, perfoming the sort and generating an RTree ready for queries.
pub fn finish<S: Sort<N>>(mut self) -> OwnedRTree<N> {
assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion src/rtree/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub(crate) struct TreeMetadata<N: IndexableNum> {
}

impl<N: IndexableNum> TreeMetadata<N> {
pub fn try_new(data: &[u8]) -> Result<Self> {
fn try_new(data: &[u8]) -> Result<Self> {
let magic = data[0];
if magic != 0xfb {
return Err(GeoIndexError::General(
Expand Down
14 changes: 14 additions & 0 deletions src/rtree/trait.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use geo_traits::{CoordTrait, RectTrait};

use crate::error::Result;
use crate::indices::Indices;
use crate::r#type::IndexableNum;
Expand Down Expand Up @@ -97,6 +99,18 @@ pub trait RTreeIndex<N: IndexableNum>: Sized {
results
}

/// Search an RTree given the provided bounding box.
///
/// Results are the indexes of the inserted objects in insertion order.
fn search_rect(&self, rect: &impl RectTrait<T = N>) -> Vec<usize> {
self.search(
rect.min().x(),
rect.min().y(),
rect.max().x(),
rect.max().y(),
)
}

// #[allow(unused_mut, unused_labels, unused_variables)]
// fn neighbors(&self, x: N, y: N, max_distance: Option<N>) -> Vec<usize> {
// let boxes = self.boxes();
Expand Down

0 comments on commit 1f45cce

Please sign in to comment.