1mod nalgebra;
28mod nearest;
29mod nearests;
30mod sort;
31mod tests;
32mod within;
33use nearest::*;
34use nearests::*;
35use sort::*;
36use std::cmp::Ordering;
37use std::marker::PhantomData;
38use typenum::Unsigned;
39use within::*;
40
41pub trait KdPoint {
62 type Scalar: num_traits::NumAssign + Copy + PartialOrd;
63 type Dim: Unsigned;
64 fn dim() -> usize {
65 <Self::Dim as Unsigned>::to_usize()
66 }
67 fn at(&self, i: usize) -> Self::Scalar;
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub struct ItemAndDistance<'a, T, Scalar> {
72 pub item: &'a T,
73 pub squared_distance: Scalar,
74}
75
76#[derive(Debug, PartialEq, Eq)]
81pub struct KdSliceN<T, N: Unsigned>(PhantomData<N>, [T]);
82pub type KdSlice<T> = KdSliceN<T, <T as KdPoint>::Dim>;
83impl<T, N: Unsigned> std::ops::Deref for KdSliceN<T, N> {
84 type Target = [T];
85 fn deref(&self) -> &[T] {
86 &self.1
87 }
88}
89impl<T: Clone, N: Unsigned> std::borrow::ToOwned for KdSliceN<T, N> {
90 type Owned = KdTreeN<T, N>;
91 fn to_owned(&self) -> Self::Owned {
92 KdTreeN(PhantomData, self.1.to_vec())
93 }
94}
95impl<T, N: Unsigned> KdSliceN<T, N> {
96 pub fn items(&self) -> &[T] {
97 &self.1
98 }
99
100 unsafe fn new_unchecked(items: &[T]) -> &Self {
101 &*(items as *const _ as *const Self)
102 }
103
104 pub fn sort_by<F>(items: &mut [T], compare: F) -> &Self
119 where
120 F: Fn(&T, &T, usize) -> Ordering + Copy,
121 {
122 kd_sort_by(items, N::to_usize(), compare);
123 unsafe { Self::new_unchecked(items) }
124 }
125
126 pub fn sort_by_key<Key: Ord, F>(items: &mut [T], kd_key: F) -> &Self
142 where
143 F: Fn(&T, usize) -> Key + Copy,
144 {
145 Self::sort_by(items, |item1, item2, k| {
146 kd_key(item1, k).cmp(&kd_key(item2, k))
147 })
148 }
149
150 pub fn sort_by_ordered_float(points: &mut [T]) -> &Self
158 where
159 T: KdPoint<Dim = N>,
160 T::Scalar: ordered_float::FloatCore,
161 {
162 Self::sort_by_key(points, |item, k| ordered_float::OrderedFloat(item.at(k)))
163 }
164
165 pub fn sort(points: &mut [T]) -> &Self
173 where
174 T: KdPoint<Dim = N>,
175 T::Scalar: Ord,
176 {
177 Self::sort_by_key(points, |item, k| item.at(k))
178 }
179
180 pub fn nearest_by<Q: KdPoint<Dim = N>>(
197 &self,
198 query: &Q,
199 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
200 ) -> Option<ItemAndDistance<T, Q::Scalar>> {
201 if self.is_empty() {
202 None
203 } else {
204 Some(kd_nearest_by(self.items(), query, coord))
205 }
206 }
207
208 pub fn nearest(
216 &self,
217 query: &impl KdPoint<Scalar = T::Scalar, Dim = N>,
218 ) -> Option<ItemAndDistance<T, T::Scalar>>
219 where
220 T: KdPoint<Dim = N>,
221 {
222 if self.is_empty() {
223 None
224 } else {
225 Some(kd_nearest(self.items(), query))
226 }
227 }
228
229 pub fn nearests_by<Q: KdPoint<Dim = N>>(
267 &self,
268 query: &Q,
269 num: usize,
270 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
271 ) -> Vec<ItemAndDistance<T, Q::Scalar>> {
272 kd_nearests_by(self.items(), query, num, coord)
273 }
274
275 pub fn nearests(
286 &self,
287 query: &impl KdPoint<Scalar = T::Scalar, Dim = N>,
288 num: usize,
289 ) -> Vec<ItemAndDistance<T, T::Scalar>>
290 where
291 T: KdPoint<Dim = N>,
292 {
293 kd_nearests(self.items(), query, num)
294 }
295
296 pub fn within_by_cmp(&self, compare: impl Fn(&T, usize) -> Ordering + Copy) -> Vec<&T> {
297 kd_within_by_cmp(self, N::to_usize(), compare)
298 }
299
300 pub fn within_by<Q: KdPoint<Dim = N>>(
301 &self,
302 query: &[Q; 2],
303 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
304 ) -> Vec<&T> {
305 assert!((0..Q::dim()).all(|k| query[0].at(k) <= query[1].at(k)));
306 self.within_by_cmp(|item, k| {
307 let a = coord(item, k);
308 if a < query[0].at(k) {
309 Ordering::Less
310 } else if a > query[1].at(k) {
311 Ordering::Greater
312 } else {
313 Ordering::Equal
314 }
315 })
316 }
317
318 pub fn within(&self, query: &[impl KdPoint<Scalar = T::Scalar, Dim = N>; 2]) -> Vec<&T>
329 where
330 T: KdPoint<Dim = N>,
331 {
332 self.within_by(query, |item, k| item.at(k))
333 }
334
335 pub fn within_radius_by<Q: KdPoint<Dim = N>>(
336 &self,
337 query: &Q,
338 radius: Q::Scalar,
339 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
340 ) -> Vec<&T> {
341 let mut results = self.within_by_cmp(|item, k| {
342 let coord = coord(item, k);
343 if coord < query.at(k) - radius {
344 Ordering::Less
345 } else if coord > query.at(k) + radius {
346 Ordering::Greater
347 } else {
348 Ordering::Equal
349 }
350 });
351 results.retain(|item| {
352 let mut distance = <Q::Scalar as num_traits::Zero>::zero();
353 for k in 0..N::to_usize() {
354 let diff = coord(item, k) - query.at(k);
355 distance += diff * diff;
356 }
357 distance < radius * radius
358 });
359 results
360 }
361
362 pub fn within_radius(
364 &self,
365 query: &impl KdPoint<Scalar = T::Scalar, Dim = N>,
366 radius: T::Scalar,
367 ) -> Vec<&T>
368 where
369 T: KdPoint<Dim = N>,
370 {
371 self.within_radius_by(query, radius, |item, k| item.at(k))
372 }
373}
374#[cfg(feature = "rayon")]
375impl<T: Send, N: Unsigned> KdSliceN<T, N> {
376 pub fn par_sort_by<F>(items: &mut [T], compare: F) -> &Self
378 where
379 F: Fn(&T, &T, usize) -> Ordering + Copy + Send,
380 {
381 kd_par_sort_by(items, N::to_usize(), compare);
382 unsafe { Self::new_unchecked(items) }
383 }
384
385 pub fn par_sort_by_key<Key: Ord, F>(items: &mut [T], kd_key: F) -> &Self
387 where
388 F: Fn(&T, usize) -> Key + Copy + Send,
389 {
390 Self::par_sort_by(items, move |item1, item2, k| {
391 kd_key(item1, k).cmp(&kd_key(item2, k))
392 })
393 }
394
395 pub fn par_sort_by_ordered_float(points: &mut [T]) -> &Self
397 where
398 T: KdPoint<Dim = N>,
399 T::Scalar: ordered_float::FloatCore,
400 {
401 Self::par_sort_by_key(points, |item, k| ordered_float::OrderedFloat(item.at(k)))
402 }
403
404 pub fn par_sort(points: &mut [T]) -> &Self
406 where
407 T: KdPoint<Dim = N>,
408 T::Scalar: Ord,
409 {
410 Self::par_sort_by_key(points, |item, k| item.at(k))
411 }
412}
413
414#[derive(Debug, Clone, PartialEq, Eq, Default)]
417pub struct KdTreeN<T, N: Unsigned>(PhantomData<N>, Vec<T>);
418pub type KdTree<T> = KdTreeN<T, <T as KdPoint>::Dim>;
419impl<T, N: Unsigned> std::ops::Deref for KdTreeN<T, N> {
420 type Target = KdSliceN<T, N>;
421 fn deref(&self) -> &Self::Target {
422 unsafe { KdSliceN::new_unchecked(&self.1) }
423 }
424}
425impl<T, N: Unsigned> AsRef<KdSliceN<T, N>> for KdTreeN<T, N> {
426 fn as_ref(&self) -> &KdSliceN<T, N> {
427 self
428 }
429}
430impl<T, N: Unsigned> std::borrow::Borrow<KdSliceN<T, N>> for KdTreeN<T, N> {
431 fn borrow(&self) -> &KdSliceN<T, N> {
432 self
433 }
434}
435impl<T, N: Unsigned> From<KdTreeN<T, N>> for Vec<T> {
436 fn from(src: KdTreeN<T, N>) -> Self {
437 src.1
438 }
439}
440impl<T, N: Unsigned> KdTreeN<T, N> {
441 pub fn into_vec(self) -> Vec<T> {
442 self.1
443 }
444
445 pub fn build_by<F>(mut items: Vec<T>, compare: F) -> Self
462 where
463 F: Fn(&T, &T, usize) -> Ordering + Copy,
464 {
465 kd_sort_by(&mut items, N::to_usize(), compare);
466 Self(PhantomData, items)
467 }
468
469 pub fn build_by_key<Key, F>(items: Vec<T>, kd_key: F) -> Self
486 where
487 Key: Ord,
488 F: Fn(&T, usize) -> Key + Copy,
489 {
490 Self::build_by(items, |item1, item2, k| {
491 kd_key(item1, k).cmp(&kd_key(item2, k))
492 })
493 }
494
495 pub fn build_by_ordered_float(points: Vec<T>) -> Self
504 where
505 T: KdPoint<Dim = N>,
506 T::Scalar: ordered_float::FloatCore,
507 {
508 Self::build_by_key(points, |item, k| ordered_float::OrderedFloat(item.at(k)))
509 }
510
511 pub fn build(points: Vec<T>) -> Self
518 where
519 T: KdPoint<Dim = N>,
520 T::Scalar: Ord,
521 {
522 Self::build_by_key(points, |item, k| item.at(k))
523 }
524}
525#[cfg(feature = "serde")]
526mod impl_serde {
527 use super::{KdTreeN, PhantomData, Unsigned};
528 impl<T: serde::Serialize, N: Unsigned> serde::Serialize for KdTreeN<T, N> {
529 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
530 self.1.serialize(serializer)
531 }
532 }
533 impl<'de, T: serde::Deserialize<'de>, N: Unsigned> serde::Deserialize<'de> for KdTreeN<T, N> {
534 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
535 Vec::<T>::deserialize(deserializer).map(|items| Self(PhantomData, items))
536 }
537 }
538}
539#[cfg(feature = "rayon")]
540impl<T: Send, N: Unsigned> KdTreeN<T, N> {
541 pub fn par_build_by<F>(mut items: Vec<T>, compare: F) -> Self
543 where
544 F: Fn(&T, &T, usize) -> Ordering + Copy + Send,
545 {
546 kd_par_sort_by(&mut items, N::to_usize(), compare);
547 Self(PhantomData, items)
548 }
549
550 pub fn par_build_by_key<Key, F>(items: Vec<T>, kd_key: F) -> Self
552 where
553 Key: Ord,
554 F: Fn(&T, usize) -> Key + Copy + Send,
555 {
556 Self::par_build_by(items, move |item1, item2, k| {
557 kd_key(item1, k).cmp(&kd_key(item2, k))
558 })
559 }
560
561 pub fn par_build_by_ordered_float(points: Vec<T>) -> Self
563 where
564 T: KdPoint<Dim = N>,
565 T::Scalar: ordered_float::FloatCore,
566 {
567 Self::par_build_by_key(points, |item, k| ordered_float::OrderedFloat(item.at(k)))
568 }
569
570 pub fn par_build(points: Vec<T>) -> Self
572 where
573 T: KdPoint<Dim = N>,
574 T::Scalar: Ord,
575 {
576 Self::par_build_by_key(points, |item, k| item.at(k))
577 }
578}
579
580#[derive(Debug, Clone, PartialEq, Eq)]
588pub struct KdIndexTreeN<'a, T, N: Unsigned> {
589 source: &'a [T],
590 kdtree: KdTreeN<usize, N>,
591}
592pub type KdIndexTree<'a, T> = KdIndexTreeN<'a, T, <T as KdPoint>::Dim>;
593impl<'a, T, N: Unsigned> KdIndexTreeN<'a, T, N> {
594 pub fn source(&self) -> &'a [T] {
595 self.source
596 }
597
598 pub fn indices(&self) -> &KdSliceN<usize, N> {
599 &self.kdtree
600 }
601
602 pub fn item(&self, i: usize) -> &'a T {
603 &self.source[i]
604 }
605
606 pub fn build_by<F>(source: &'a [T], compare: F) -> Self
607 where
608 F: Fn(&T, &T, usize) -> Ordering + Copy,
609 {
610 Self {
611 source,
612 kdtree: KdTreeN::build_by((0..source.len()).collect(), |i1, i2, k| {
613 compare(&source[*i1], &source[*i2], k)
614 }),
615 }
616 }
617
618 pub fn build_by_key<Key, F>(source: &'a [T], kd_key: F) -> Self
619 where
620 Key: Ord,
621 F: Fn(&T, usize) -> Key + Copy,
622 {
623 Self::build_by(source, |item1, item2, k| {
624 kd_key(item1, k).cmp(&kd_key(item2, k))
625 })
626 }
627
628 pub fn build_by_ordered_float(points: &'a [T]) -> Self
629 where
630 T: KdPoint<Dim = N>,
631 T::Scalar: ordered_float::FloatCore,
632 {
633 Self::build_by_key(points, |item, k| ordered_float::OrderedFloat(item.at(k)))
634 }
635
636 pub fn build(points: &'a [T]) -> Self
637 where
638 T: KdPoint<Dim = N>,
639 T::Scalar: Ord,
640 {
641 Self::build_by_key(points, |item, k| item.at(k))
642 }
643
644 pub fn nearest_by<Q: KdPoint<Dim = N>>(
645 &self,
646 query: &Q,
647 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
648 ) -> Option<ItemAndDistance<usize, Q::Scalar>> {
649 self.kdtree
650 .nearest_by(query, |&index, k| coord(&self.source[index], k))
651 }
652
653 pub fn nearest(
660 &self,
661 query: &impl KdPoint<Scalar = T::Scalar, Dim = N>,
662 ) -> Option<ItemAndDistance<usize, T::Scalar>>
663 where
664 T: KdPoint<Dim = N>,
665 {
666 self.nearest_by(query, |item, k| item.at(k))
667 }
668
669 pub fn nearests_by<Q: KdPoint<Dim = N>>(
670 &self,
671 query: &Q,
672 num: usize,
673 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
674 ) -> Vec<ItemAndDistance<usize, Q::Scalar>> {
675 self.kdtree
676 .nearests_by(query, num, |&index, k| coord(&self.source[index], k))
677 }
678
679 pub fn nearests(
690 &self,
691 query: &impl KdPoint<Scalar = T::Scalar, Dim = N>,
692 num: usize,
693 ) -> Vec<ItemAndDistance<usize, T::Scalar>>
694 where
695 T: KdPoint<Dim = N>,
696 {
697 self.nearests_by(query, num, |item, k| item.at(k))
698 }
699
700 pub fn within_by_cmp(&self, compare: impl Fn(&T, usize) -> Ordering + Copy) -> Vec<&usize> {
701 self.kdtree
702 .within_by_cmp(|&index, k| compare(&self.source[index], k))
703 }
704
705 pub fn within_by<Q: KdPoint<Dim = N>>(
706 &self,
707 query: &[Q; 2],
708 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
709 ) -> Vec<&usize> {
710 self.kdtree
711 .within_by(query, |&index, k| coord(&self.source[index], k))
712 }
713
714 pub fn within(&self, query: &[impl KdPoint<Scalar = T::Scalar, Dim = N>; 2]) -> Vec<&usize>
715 where
716 T: KdPoint<Dim = N>,
717 {
718 self.within_by(query, |item, k| item.at(k))
719 }
720
721 pub fn within_radius_by<Q: KdPoint<Dim = N>>(
722 &self,
723 query: &Q,
724 radius: Q::Scalar,
725 coord: impl Fn(&T, usize) -> Q::Scalar + Copy,
726 ) -> Vec<&usize> {
727 self.kdtree
728 .within_radius_by(query, radius, |&index, k| coord(&self.source[index], k))
729 }
730
731 pub fn within_radius(
732 &self,
733 query: &impl KdPoint<Scalar = T::Scalar, Dim = N>,
734 radius: T::Scalar,
735 ) -> Vec<&usize>
736 where
737 T: KdPoint<Dim = N>,
738 {
739 self.within_radius_by(query, radius, |item, k| item.at(k))
740 }
741}
742#[cfg(feature = "rayon")]
743impl<'a, T: Sync, N: Unsigned> KdIndexTreeN<'a, T, N> {
744 pub fn par_build_by<F>(source: &'a [T], compare: F) -> Self
745 where
746 F: Fn(&T, &T, usize) -> Ordering + Copy + Send,
747 {
748 Self {
749 source,
750 kdtree: KdTreeN::par_build_by((0..source.len()).collect(), move |i1, i2, k| {
751 compare(&source[*i1], &source[*i2], k)
752 }),
753 }
754 }
755
756 pub fn par_build_by_key<Key, F>(source: &'a [T], kd_key: F) -> Self
757 where
758 Key: Ord,
759 F: Fn(&T, usize) -> Key + Copy + Send,
760 {
761 Self::par_build_by(source, move |item1, item2, k| {
762 kd_key(item1, k).cmp(&kd_key(item2, k))
763 })
764 }
765
766 pub fn par_build_by_ordered_float(points: &'a [T]) -> Self
767 where
768 T: KdPoint<Dim = N>,
769 T::Scalar: ordered_float::FloatCore,
770 {
771 Self::par_build_by_key(points, |item, k| ordered_float::OrderedFloat(item.at(k)))
772 }
773
774 pub fn par_build(points: &'a [T]) -> Self
775 where
776 T: KdPoint<Dim = N>,
777 T::Scalar: Ord,
778 {
779 Self::par_build_by_key(points, |item, k| item.at(k))
780 }
781}
782
783macro_rules! define_kdtree_aliases {
784 ($($dim:literal),*) => {
785 $(
786 paste::paste! {
787 pub type [<KdSlice $dim>]<T> = KdSliceN<T, typenum::[<U $dim>]>;
788 pub type [<KdTree $dim>]<T> = KdTreeN<T, typenum::[<U $dim>]>;
789 pub type [<KdIndexTree $dim>]<'a, T> = KdIndexTreeN<'a, T, typenum::[<U $dim>]>;
790 }
791 )*
792 };
793}
794define_kdtree_aliases!(1, 2, 3, 4, 5, 6, 7, 8);
795
796macro_rules! impl_kd_points {
797 ($($len:literal),*) => {
798 $(
799 paste::paste!{
800 impl<T: num_traits::NumAssign + Copy + PartialOrd> KdPoint for [T; $len] {
801 type Scalar = T;
802 type Dim = typenum::[<U $len>];
803 fn at(&self, i: usize) -> T { self[i] }
804 }
805 }
806 )*
807 };
808}
809impl_kd_points!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
810
811impl<P: KdPoint, T> KdPoint for (P, T) {
812 type Scalar = P::Scalar;
813 type Dim = P::Dim;
814 fn at(&self, k: usize) -> Self::Scalar {
815 self.0.at(k)
816 }
817}
818
819pub type KdMap<P, T> = KdTree<(P, T)>;
829
830pub type KdMapSlice<P, T> = KdSlice<(P, T)>;