use rstar::primitives::GeomWithData;
use rstar::{Envelope, PointDistance, RTreeObject};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::marker::PhantomData;
use crate::index::Index;
pub struct RStar<K, V, Q: RTreeObject, F: Fn(K, V) -> Q>(
rstar::RTree<GeomWithData<Q, K>>,
F,
PhantomData<V>,
);
impl<K, V, Q, F> RStar<K, V, Q, F>
where
Q: RTreeObject + PointDistance + Clone,
K: Clone,
F: Fn(K, V) -> Q,
{
pub fn new(f: F) -> Self {
RStar(rstar::RTree::new(), f, PhantomData)
}
pub fn nearest_neighbor(&self, q: &<Q::Envelope as Envelope>::Point) -> Option<(Q, K)> {
self.0
.nearest_neighbor(q)
.map(|g| (g.geom().to_owned(), g.data.clone()))
}
}
impl<K, V, Q, F> Index<K, V> for RStar<K, V, Q, F>
where
K: Eq + Ord + Serialize + DeserializeOwned + Clone + PartialEq,
V: Serialize + DeserializeOwned,
Q: RTreeObject + PartialEq + PointDistance,
F: Fn(K, V) -> Q,
{
fn insert(&mut self, key: K, value: V) {
self.0
.insert(GeomWithData::new(self.1(key.clone(), value), key));
}
fn remove(&mut self, key: K, value: V) {
self.0
.remove(&GeomWithData::new(self.1(key.clone(), value), key));
}
}
#[cfg(test)]
mod tests {
use crate::{index::JSStoreWithIndex, rtree::RStar};
#[test]
fn test() {
let mut x: JSStoreWithIndex<i32, (i32, i32), _> =
JSStoreWithIndex::new("testrtree.json", RStar::new(|_k, v| v)).unwrap();
x.insert(0, (1, 1)).unwrap();
x.insert(1, (2, 2)).unwrap();
x.insert(2, (3, 3)).unwrap();
let result = x.index().nearest_neighbor(&(4, 4));
assert_eq!(result, Some(((3, 3), 2)));
drop(x);
}
}