mirror of
https://github.com/andreytkachenko/kdtree-rust.git
synced 2024-11-22 09:26:25 +04:00
Added benches, lookup remaining
This commit is contained in:
parent
7ae4d8fd9d
commit
7a6734cd4d
10
Cargo.toml
10
Cargo.toml
@ -3,8 +3,18 @@ name = "kdtree-rust"
|
||||
version = "0.1.0"
|
||||
authors = ["Aleksander Fular <ntszar@gmail.com>"]
|
||||
|
||||
[lib]
|
||||
name = "kdtree"
|
||||
path = "src//lib.rs"
|
||||
bench = false
|
||||
|
||||
[[bench]]
|
||||
name = "bench"
|
||||
harness = false
|
||||
|
||||
[dependencies]
|
||||
rand = "*"
|
||||
bencher = "*"
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.3"
|
46
src/bench.rs
Normal file
46
src/bench.rs
Normal file
@ -0,0 +1,46 @@
|
||||
#[macro_use]
|
||||
extern crate bencher;
|
||||
extern crate kdtree;
|
||||
extern crate rand;
|
||||
|
||||
use bencher::Bencher;
|
||||
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct Point2WithId {
|
||||
dims: [f64; 2],
|
||||
pub id: i32,
|
||||
}
|
||||
|
||||
impl Point2WithId {
|
||||
pub fn new(id: i32, x: f64, y: f64) -> Point2WithId {
|
||||
Point2WithId {
|
||||
dims: [x, y],
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl kdtree::kdtree::KdtreePointTrait for Point2WithId {
|
||||
fn dims(&self) -> &[f64] {
|
||||
return &self.dims;
|
||||
}
|
||||
}
|
||||
|
||||
fn a(b: &mut Bencher) {
|
||||
let len = 1000usize;
|
||||
let mut points : Vec<Point2WithId> = vec![];
|
||||
//let mut kdtree = KdTree::new_with_capacity(3, 16);
|
||||
for id in 0..len {
|
||||
let x : f64 = rand::random();
|
||||
points.push(Point2WithId::new(id as i32, x, x));
|
||||
// points.push(rand_data());
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
let tree = kdtree::kdtree::Kdtree::new(points.clone());
|
||||
});
|
||||
}
|
||||
|
||||
benchmark_group!(benches, a);
|
||||
benchmark_main!(benches);
|
@ -1,4 +1,3 @@
|
||||
|
||||
use ::kdtree::*;
|
||||
|
||||
pub struct Bounds {
|
||||
@ -11,7 +10,7 @@ impl Bounds {
|
||||
bounds: vec![],
|
||||
};
|
||||
|
||||
bounds.bounds.resize(points[0].dims().len(), (0.,0.));
|
||||
bounds.bounds.resize(points[0].dims().len(), (0., 0.));
|
||||
|
||||
for i in 0..points[0].dims().len() {
|
||||
bounds.bounds[i].0 = points[0].dims()[i];
|
||||
@ -43,6 +42,28 @@ impl Bounds {
|
||||
|
||||
widest_dimension
|
||||
}
|
||||
|
||||
pub fn get_midvalue_of_widest_dim(&self) -> f64 {
|
||||
(self.bounds[self.get_widest_dim()].0 + self.bounds[self.get_widest_dim()].1) / 2.0
|
||||
}
|
||||
|
||||
pub fn clone_moving_max(&self, value: f64, dimension: usize) -> Bounds {
|
||||
let mut cloned = Bounds {
|
||||
bounds: self.bounds.clone()
|
||||
};
|
||||
cloned.bounds[dimension].1 = value;
|
||||
|
||||
cloned
|
||||
}
|
||||
|
||||
pub fn clone_moving_min(&self, value: f64, dimension: usize) -> Bounds {
|
||||
let mut cloned = Bounds {
|
||||
bounds: self.bounds.clone()
|
||||
};
|
||||
cloned.bounds[dimension].0 = value;
|
||||
|
||||
cloned
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -53,9 +74,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn bounds_test() {
|
||||
let p1 = Point2WithId::new(1,1.0,0.5);
|
||||
let p2 = Point2WithId::new(1,3.0,4.0);
|
||||
let v = vec![p1,p2];
|
||||
let p1 = Point2WithId::new(1, 1.0, 0.5);
|
||||
let p2 = Point2WithId::new(1, 3.0, 4.0);
|
||||
let v = vec![p1, p2];
|
||||
|
||||
|
||||
let bounds = Bounds::new_from_points(&v);
|
||||
|
||||
@ -63,6 +85,5 @@ mod tests {
|
||||
assert_eq!((0.5, 4.0), bounds.bounds[1]);
|
||||
|
||||
assert_eq!(1, bounds.get_widest_dim());
|
||||
|
||||
}
|
||||
}
|
@ -13,32 +13,50 @@ pub struct Kdtree<T> {
|
||||
nodes: Vec<KdtreeNode<T>>,
|
||||
}
|
||||
|
||||
impl<T: KdtreePointTrait> Kdtree<T> {
|
||||
pub fn new(points: Vec<T>) -> Kdtree<T> {
|
||||
impl<T: KdtreePointTrait + Copy> Kdtree<T> {
|
||||
pub fn new(mut points: Vec<T>) -> Kdtree<T> {
|
||||
if points.len() == 0 {
|
||||
panic!("empty vector point not allowed");
|
||||
}
|
||||
|
||||
let rect = Bounds::new_from_points(&points);
|
||||
|
||||
Kdtree {
|
||||
let mut tree = Kdtree {
|
||||
nodes: vec![],
|
||||
}
|
||||
};
|
||||
|
||||
tree.build_tree(&mut points, &rect);
|
||||
|
||||
tree
|
||||
}
|
||||
|
||||
fn add_node(&mut self, p: T) {
|
||||
fn add_node(&mut self, p: T) -> usize {
|
||||
let node = KdtreeNode::new(p);
|
||||
|
||||
self.nodes.push(node);
|
||||
self.nodes.len() - 1
|
||||
}
|
||||
|
||||
fn add_left_node(&mut self, for_node: usize, ) {
|
||||
{
|
||||
let len = self.nodes.len();
|
||||
let node = self.nodes.get_mut(for_node).unwrap();
|
||||
node.left_node = Some(len);
|
||||
fn build_tree(&mut self, nodes: &mut [T], bounds: &Bounds) -> usize {
|
||||
let (splitting_index, pivot_value) = partition::partition_sliding_midpoint(nodes, bounds.get_midvalue_of_widest_dim(), bounds.get_widest_dim());
|
||||
|
||||
let node_id = self.add_node(nodes[splitting_index]);
|
||||
let nodes_len = nodes.len();
|
||||
|
||||
if splitting_index > 0 {
|
||||
let left_rect = bounds.clone_moving_max(bounds.get_midvalue_of_widest_dim(), bounds.get_widest_dim());
|
||||
let left_child_id = self.build_tree(&mut nodes[0..splitting_index], &left_rect);
|
||||
self.nodes[node_id].left_node = Some(left_child_id);
|
||||
}
|
||||
//self.nodes.push(KdtreeNode::new());
|
||||
|
||||
if splitting_index < nodes.len() - 1 {
|
||||
let right_rect = bounds.clone_moving_min(bounds.get_midvalue_of_widest_dim(), bounds.get_widest_dim());
|
||||
|
||||
let right_child_id = self.build_tree(&mut nodes[splitting_index + 1..nodes_len], &right_rect);
|
||||
self.nodes[node_id].right_node = Some(right_child_id);
|
||||
}
|
||||
|
||||
node_id
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,12 +92,44 @@ mod tests {
|
||||
Kdtree::new(empty_vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test2() {
|
||||
let p1 = Point2WithId::new(1, 1., 2.);
|
||||
let p2 = Point2WithId::new(1, 1., 2.);
|
||||
let vec = vec![p1, p2];
|
||||
quickcheck! {
|
||||
fn tree_build_creates_tree_with_as_many_leafs_as_there_is_points(xs : Vec<f64>) -> bool {
|
||||
if(xs.len() == 0) {
|
||||
return true;
|
||||
}
|
||||
let mut vec : Vec<Point2WithId> = vec![];
|
||||
for i in 0 .. xs.len() {
|
||||
let p = Point2WithId::new(i as i32, xs[i], xs[i]);
|
||||
|
||||
Kdtree::new(vec);
|
||||
vec.push(p);
|
||||
}
|
||||
|
||||
let tree = Kdtree::new(vec);
|
||||
|
||||
let mut to_iterate : Vec<usize> = vec![];
|
||||
to_iterate.push(0);
|
||||
|
||||
let mut str = String::new();
|
||||
|
||||
while to_iterate.len() > 0 {
|
||||
let last_index = to_iterate.last().unwrap().clone();
|
||||
let ref x = tree.nodes.get(last_index).unwrap();
|
||||
to_iterate.pop();
|
||||
if x.left_node.is_some() {
|
||||
to_iterate.push(x.left_node.unwrap());
|
||||
}
|
||||
if x.right_node.is_some() {
|
||||
to_iterate.push(x.right_node.unwrap());
|
||||
}
|
||||
|
||||
str.push_str(&format!("Index: {} has ln {} has rn {} \n", last_index, x.left_node.is_some(), x.right_node.is_some()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
// println!("str is: {}", str);
|
||||
|
||||
xs.len() == tree.nodes.len()
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ struct PartitionPointHelper {
|
||||
index_of_splitter: usize,
|
||||
}
|
||||
|
||||
fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
|
||||
fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut [T], midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
|
||||
let mut closest_index = 0;
|
||||
let mut closest_distance = (vec[0].dims()[partition_on_dimension] - midpoint_value).abs();
|
||||
|
||||
@ -51,10 +51,13 @@ fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midp
|
||||
}
|
||||
}
|
||||
|
||||
pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
|
||||
pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut [T], midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
|
||||
let vec_len = vec.len();
|
||||
debug_assert!(vec[0].dims().len() > partition_on_dimension);
|
||||
debug_assert!(vec.len() > 1);
|
||||
|
||||
if vec.len() == 1 {
|
||||
return (0, vec[0].dims()[partition_on_dimension]);
|
||||
}
|
||||
|
||||
let partition_point_data = partition_sliding_midpoint_helper(vec, midpoint_value, partition_on_dimension);
|
||||
|
||||
@ -74,7 +77,7 @@ pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoin
|
||||
}
|
||||
}
|
||||
|
||||
fn partition_kdtree<T: KdtreePointTrait>(vec: &mut Vec<T>, index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
|
||||
fn partition_kdtree<T: KdtreePointTrait>(vec: &mut [T], index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
|
||||
if vec.len() == 1 {
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user