10个版本 (5个重大更新)
0.6.0 | 2024年4月20日 |
---|---|
0.5.3 | 2024年1月7日 |
0.5.1 | 2023年1月9日 |
0.5.0 | 2022年11月20日 |
0.2.0 | 2020年11月29日 |
#83 在 算法 中
4,354 每月下载量
用于 10 crates
53KB
1K SLoC
kd-tree
Rust中的多维树。
快速、简单、易于使用。
用法
// construct kd-tree
let kdtree = kd_tree::KdTree::build_by_ordered_float(vec![
[1.0, 2.0, 3.0],
[3.0, 1.0, 2.0],
[2.0, 3.0, 1.0],
]);
// search the nearest neighbor
let found = kdtree.nearest(&[3.1, 0.9, 2.1]).unwrap();
assert_eq!(found.item, &[3.0, 1.0, 2.0]);
// search k-nearest neighbors
let found = kdtree.nearests(&[1.5, 2.5, 1.8], 2);
assert_eq!(found[0].item, &[2.0, 3.0, 1.0]);
assert_eq!(found[1].item, &[1.0, 2.0, 3.0]);
// search points within a sphere
let found = kdtree.within_radius(&[2.0, 1.5, 2.5], 1.5);
assert_eq!(found.len(), 2);
assert!(found.iter().any(|&&p| p == [1.0, 2.0, 3.0]));
assert!(found.iter().any(|&&p| p == [3.0, 1.0, 2.0]));
使用或不使用 KdPoint
KdPoint
trait 表示多维点。
你可以选择使用或不使用 KdPoint
。
显式使用 KdPoint
use kd_tree::{KdPoint, KdTree};
// define your own item type.
struct Item {
point: [f64; 2],
id: usize,
}
// implement `KdPoint` for your item type.
impl KdPoint for Item {
type Scalar = f64;
type Dim = typenum::U2; // 2 dimensional tree.
fn at(&self, k: usize) -> f64 { self.point[k] }
}
// construct kd-tree from `Vec<Item>`.
// Note: you need to use `build_by_ordered_float()` because f64 doesn't implement `Ord` trait.
let kdtree: KdTree<Item> = KdTree::build_by_ordered_float(vec![
Item { point: [1.0, 2.0], id: 111 },
Item { point: [2.0, 3.0], id: 222 },
Item { point: [3.0, 4.0], id: 333 },
]);
// search nearest item from [1.9, 3.1]
assert_eq!(kdtree.nearest(&[1.9, 3.1]).unwrap().item.id, 222);
隐式使用 KdPoint
KdPoint
trait 对固定大小的数值类型数组进行了实现,例如 [f64; 3]
或 [i32, 2]
等。因此,你可以构建这些类型的kd树,而无需自定义 KdPoint
实现。
let items: Vec<[i32; 3]> = vec![[1, 2, 3], [3, 1, 2], [2, 3, 1]];
let kdtree = kd_tree::KdTree::build(items);
assert_eq!(kdtree.nearest(&[3, 1, 2]).unwrap().item, &[3, 1, 2]);
KdPoint
trait 还对 KdPoint
和任意类型的元组进行了实现,例如 (P, T)
,其中 P: KdPoint
。还定义了一个名为 KdMap<P, T>
的类型别名,作为 KdTree<(P, T)>
。因此,你可以从键值对构建kd树,如下所示
let kdmap: kd_tree::KdMap<[isize; 3], &'static str> = kd_tree::KdMap::build(vec![
([1, 2, 3], "foo"),
([2, 3, 1], "bar"),
([3, 1, 2], "buzz"),
]);
assert_eq!(kdmap.nearest(&[3, 1, 2]).unwrap().item.1, "buzz");
nalgebra
功能
KdPoint
trait 对 nalgebra
的向量和点进行了实现。
在 Cargo.toml 中启用 nalgebra
功能
kd-tree = { version = "...", features = ["nalgebra"] }
然后,你可以如下使用它
use nalgebra::Point3;
let items: Vec<Point3<i32>> = vec![
Point3::new(1, 2, 3),
Point3::new(3, 1, 2),
Point3::new(2, 3, 1)
];
let kdtree = kd_tree::KdTree::build(items);
let query = Point3::new(3, 1, 2);
assert_eq!(kdtree.nearest(&query).unwrap().item, &query);
不使用 KdPoint
use std::collections::HashMap;
let items: HashMap<&'static str, [i32; 2]> = vec![
("a", [10, 20]),
("b", [20, 10]),
("c", [20, 20]),
].into_iter().collect();
let kdtree = kd_tree::KdTree2::build_by_key(items.keys().collect(), |key, k| items[*key][k]);
assert_eq!(kdtree.nearest_by(&[18, 21], |key, k| items[*key][k]).unwrap().item, &&"c");
拥有,还是不拥有
KdSliceN<T, N>
和 KdTreeN<T, N>
类似于 str
和 String
,或者是 Path
和 PathBuf
。
KdSliceN<T, N>
不拥有自己的缓冲区,但KdTreeN<T, N>
是。KdSliceN<T, N>
不是Sized
,因此必须以引用方式处理。KdSliceN<T, N>
实现了Deref
到[T]
。KdTreeN<T, N>
实现了Deref
到KdSliceN<T, N>
。- 与可变的
PathBuf
或String
不同,KdTreeN<T, N>
是不可变的。
&KdSliceN<T, N>
可以直接构建,而不是通过 KdTreeN
,如下所示
let mut items: Vec<[i32; 3]> = vec![[1, 2, 3], [3, 1, 2], [2, 3, 1]];
let kdtree = kd_tree::KdSlice::sort(&mut items);
assert_eq!(kdtree.nearest(&[3, 1, 2]).unwrap().item, &[3, 1, 2]);
KdIndexTreeN
KdIndexTreeN
指向一个元素切片,[T]
,并包含指向元素的索引的kd树,KdTreeN<usize, N>
。与 KdSlice::sort
不同,KdIndexTree::build
不会对输入元素进行排序。
let items = vec![[1, 2, 3], [3, 1, 2], [2, 3, 1]];
let kdtree = kd_tree::KdIndexTree::build(&items);
assert_eq!(kdtree.nearest(&[3, 1, 2]).unwrap().item, &1); // nearest() returns an index of found item.
功能
"serde" 功能
[dependencies]
kd-tree = { version = "...", features = ["serde"] }
您可以使用此功能序列化/反序列化 KdTree<{可序列化 类型}>
。
let src: KdTree3<[i32; 3]> = KdTree::build(vec![[1, 2, 3], [4, 5, 6]]);
let json = serde_json::to_string(&src).unwrap();
assert_eq!(json, "[[1,2,3],[4,5,6]]");
let dst: KdTree3<[i32; 3]> = serde_json::from_str(&json).unwrap();
assert_eq!(src, dst);
"nalgebra" 功能
[dependencies]
kd-tree = { version = "...", features = ["nalgebra"] }
参见 上面
"nalgebra-serde" 功能
[dependencies]
kd-tree = { version = "...", features = ["nalgebra-serde"] }
您可以使用此功能序列化/反序列化 KdTree<{nalgebra 类型}>
。
use ::nalgebra as na;
let src: KdTree<na::Point3<f64>> = KdTree::build_by_ordered_float(vec![
na::Point3::new(1.0, 2.0, 3.0),
na::Point3::new(4.0, 5.0, 6.0),
]);
let json = serde_json::to_string(&src).unwrap();
assert_eq!(json, "[[1.0,2.0,3.0],[4.0,5.0,6.0]]");
let dst: KdTree3<na::Point3<f64>> = serde_json::from_str(&json).unwrap();
assert_eq!(src, dst);
"rayon" 功能
[dependencies]
kd-tree = { version = "...", features = ["rayon"] }
您可以使用 rayon
构建kd树更快。
let kdtree = KdTree::par_build_by_ordered_float(vec![...]);
许可证
此库根据 MIT 许可证 分发。
依赖项
~0.3–1.4MB
~30K SLoC