use vpsearch::{BestCandidate, MetricSpace};
use std::collections::HashSet;
#[derive(Clone, Debug)]
struct PointN {
data: Vec<f32>,
}
impl PointN {
pub fn new(data: impl Into<Vec<f32>>) -> Self {
Self { data: data.into() }
}
}
impl MetricSpace for PointN {
type UserData = ();
type Distance = f32;
fn distance(&self, other: &Self, _: &Self::UserData) -> Self::Distance {
self.data
.iter()
.zip(other.data.iter())
.map(|(s, o)| (s - o).powi(2))
.sum::<f32>()
.sqrt()
}
}
struct RadiusBasedNeighborhood<Item: MetricSpace<Impl>, Impl> {
max_distance: Item::Distance,
ids: HashSet<usize>,
}
impl<Item: MetricSpace<Impl>, Impl> RadiusBasedNeighborhood<Item, Impl> {
fn new(max_distance: Item::Distance) -> Self {
Self {
max_distance,
ids: HashSet::<usize>::new(),
}
}
}
impl<Item: MetricSpace<Impl> + Clone, Impl> BestCandidate<Item, Impl>
for RadiusBasedNeighborhood<Item, Impl>
{
type Output = HashSet<usize>;
#[inline]
fn consider(
&mut self,
_: &Item,
distance: Item::Distance,
candidate_index: usize,
_: &Item::UserData,
) {
if distance < self.max_distance {
self.ids.insert(candidate_index);
}
}
#[inline]
fn distance(&self) -> Item::Distance {
self.max_distance
}
fn result(self, _: &Item::UserData) -> Self::Output {
self.ids
}
}
fn main() {
let points = vec![
PointN::new([2.0, 3.0]),
PointN::new([0.0, 1.0]),
PointN::new([4.0, 5.0]),
];
let tree = vpsearch::Tree::new(&points);
let expected = HashSet::new();
let actual = tree.find_nearest_custom(
&PointN::new([1.0, 2.0]),
&(),
RadiusBasedNeighborhood::new(0.0f32),
);
assert_eq!(actual, expected);
let expected = [0, 1, 2].iter().copied().collect::<HashSet<usize>>();
let actual = tree.find_nearest_custom(
&PointN::new([1.0, 2.0]),
&(),
RadiusBasedNeighborhood::new(100.0f32),
);
assert_eq!(actual, expected);
}