use std::collections::BinaryHeap;
use crate::geometry::{Box2D, Box3D, Point2D, Point3D};
#[derive(Clone, Copy)]
pub(crate) enum NeighborQuery2D {
Point(Point2D),
Box(Box2D),
}
impl NeighborQuery2D {
#[inline]
pub(crate) fn distance_squared_to(self, bounds: Box2D) -> f64 {
match self {
NeighborQuery2D::Point(point) => bounds.distance_squared_to(point),
NeighborQuery2D::Box(query) => bounds.distance_squared_to_box(query),
}
}
}
#[derive(Clone, Copy)]
pub(crate) enum NeighborQuery3D {
Point(Point3D),
Box(Box3D),
}
impl NeighborQuery3D {
#[inline]
pub(crate) fn distance_squared_to(self, bounds: Box3D) -> f64 {
match self {
NeighborQuery3D::Point(point) => bounds.distance_squared_to(point),
NeighborQuery3D::Box(query) => bounds.distance_squared_to_box(query),
}
}
}
#[derive(Debug, Default)]
pub struct NeighborWorkspace {
pub(crate) results: Vec<usize>,
pub(crate) queue: BinaryHeap<NeighborState>,
pub(crate) node_queue: BinaryHeap<NeighborNodeState>,
#[cfg(feature = "f32-storage")]
pub(crate) exact_queue: BinaryHeap<ExactNeighborState>,
}
impl NeighborWorkspace {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(results: usize, queue: usize) -> Self {
Self {
results: Vec::with_capacity(results),
queue: BinaryHeap::with_capacity(queue),
node_queue: BinaryHeap::with_capacity(queue),
#[cfg(feature = "f32-storage")]
exact_queue: BinaryHeap::with_capacity(results),
}
}
pub fn results(&self) -> &[usize] {
&self.results
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) struct NeighborState {
pub(crate) index: usize,
pub(crate) is_leaf: bool,
pub(crate) dist: f64,
}
impl NeighborState {
#[inline]
pub(crate) fn new(index: usize, is_leaf: bool, dist: f64) -> Self {
Self {
index,
is_leaf,
dist,
}
}
}
impl Eq for NeighborState {}
impl Ord for NeighborState {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other
.dist
.total_cmp(&self.dist)
.then_with(|| self.is_leaf.cmp(&other.is_leaf))
.then_with(|| other.index.cmp(&self.index))
}
}
impl PartialOrd for NeighborState {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) struct NeighborNodeState {
pub(crate) index: usize,
pub(crate) dist: f64,
}
impl NeighborNodeState {
#[inline]
pub(crate) fn new(index: usize, dist: f64) -> Self {
Self { index, dist }
}
}
impl Eq for NeighborNodeState {}
impl Ord for NeighborNodeState {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other
.dist
.total_cmp(&self.dist)
.then_with(|| other.index.cmp(&self.index))
}
}
impl PartialOrd for NeighborNodeState {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[cfg(feature = "f32-storage")]
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) struct ExactNeighborState {
pub(crate) index: usize,
pub(crate) dist: f64,
}
#[cfg(feature = "f32-storage")]
impl ExactNeighborState {
#[inline]
pub(crate) fn new(index: usize, dist: f64) -> Self {
Self { index, dist }
}
}
#[cfg(feature = "f32-storage")]
impl Eq for ExactNeighborState {}
#[cfg(feature = "f32-storage")]
impl Ord for ExactNeighborState {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.dist
.total_cmp(&other.dist)
.then_with(|| self.index.cmp(&other.index))
}
}
#[cfg(feature = "f32-storage")]
impl PartialOrd for ExactNeighborState {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
pub(crate) fn max_distance_squared(max_distance: f64) -> Option<f64> {
if max_distance.is_nan() || max_distance.is_sign_negative() {
None
} else {
Some(max_distance * max_distance)
}
}