Skip to main content

bonsai/backends/
mod.rs

1//! Spatial backend trait and implementations.
2//!
3//! All four spatial index backends implement the [`SpatialBackend`] trait,
4//! which provides a uniform interface for insert, remove, range query, kNN
5//! query, spatial join, and bulk loading.
6
7use crate::types::{BBox, BackendKind, CoordType, EntryId, Point};
8
9pub mod grid;
10pub mod kdtree;
11pub mod quadtree;
12pub mod rtree;
13
14pub use grid::GridIndex;
15pub use kdtree::KDTree;
16pub use quadtree::Quadtree;
17pub use rtree::RTree;
18
19/// Uniform interface implemented by all spatial index backends.
20///
21/// # Type Parameters
22/// - `T`: payload type stored alongside each point
23/// - `C`: coordinate scalar type (must implement [`CoordType`])
24/// - `D`: number of spatial dimensions (const generic)
25pub trait SpatialBackend<T, C, const D: usize>: Send + Sync
26where
27    C: CoordType,
28{
29    /// Insert a point with an associated payload. Returns the unique [`EntryId`]
30    /// assigned to this entry.
31    fn insert(&mut self, point: Point<C, D>, payload: T) -> EntryId;
32
33    /// Remove the entry with the given [`EntryId`]. Returns the payload if the
34    /// entry existed, or `None` otherwise.
35    fn remove(&mut self, id: EntryId) -> Option<T>;
36
37    /// Return all entries whose positions are contained within `bbox`.
38    fn range_query(&self, bbox: &BBox<C, D>) -> Vec<(EntryId, &T)>;
39
40    /// Return the `k` nearest entries to `point`, ordered by ascending
41    /// Euclidean distance. Each result is `(distance, id, payload_ref)`.
42    fn knn_query(&self, point: &Point<C, D>, k: usize) -> Vec<(f64, EntryId, &T)>;
43
44    /// Return all pairs `(id_a, id_b)` where the bounding box of entry `id_a`
45    /// in `self` intersects the bounding box of entry `id_b` in `other`.
46    ///
47    /// For point-only backends the "bounding box" of a point is the degenerate
48    /// box `[p, p]`.
49    fn spatial_join(&self, other: &dyn SpatialBackend<T, C, D>) -> Vec<(EntryId, EntryId)>;
50
51    /// Bulk-load a set of `(point, payload)` pairs into a new backend instance.
52    ///
53    /// Implementations may sort entries (e.g. by Hilbert index) for better
54    /// spatial locality.
55    fn bulk_load(entries: Vec<(Point<C, D>, T)>) -> Self
56    where
57        Self: Sized;
58
59    /// Return the number of entries currently stored.
60    fn len(&self) -> usize;
61
62    /// Return `true` if the backend contains no entries.
63    fn is_empty(&self) -> bool {
64        self.len() == 0
65    }
66
67    /// Return the [`BackendKind`] discriminant for this backend.
68    fn kind(&self) -> BackendKind;
69
70    /// Return all `(point, id, payload)` triples — used by `spatial_join`
71    /// implementations that need to iterate over the other backend's entries.
72    fn all_entries(&self) -> Vec<(Point<C, D>, EntryId, &T)>;
73}