use std::ops::{Add, Mul, Sub};
use rand::Rng;
use kdtree_rust::{EuclideanDistance, KDTree};
fn nearest<'a,const D:usize,P>(p:&'a [P;D],positions:&'a [[P;D]]) -> &'a [P;D]
where P: PartialOrd + Mul + Add + Sub + Default,
&'a [P;D]: EuclideanDistance<&'a [P;D], Output = P> + 'a {
let s = &positions[0];
let mut r = s;
let mut distance = p.euclidean_distance(r);
for pt in positions.iter().skip(1) {
let d = p.euclidean_distance(pt);
if d <= distance {
r = pt;
distance = d;
}
}
r
}
#[test]
fn small_2d() {
const COUNT:usize = 100;
let mut kdt = KDTree::<2,f64,()>::new();
let mut rng = rand::thread_rng();
let mut positions:Vec<[f64;2]> = vec![];
for _ in 0..COUNT {
let mut pn = [0f64;2];
for i in 0..2 {
let mut p:f64 = rng.gen_range(-100000.0..100000.0);
let pi:u8 = rng.gen_range(0..10);
if let Some(last) = positions.last() {
if pi == 0 {
p = last[i];
}
}
pn[i] = p;
}
positions.push(pn.clone());
kdt.insert(pn,());
}
let mut success = 0;
for _ in 0..COUNT {
let x:f64 = rng.gen_range(-100000.0..100000.0);
let y:f64 = rng.gen_range(-100000.0..100000.0);
let p = [x,y];
let expected = nearest(&p,&positions);
let actual = kdt.nearest_position(&p);
if (p.euclidean_distance(expected) - p.euclidean_distance(&actual.unwrap())) < 1. {
success += 1;
} else {
dbg!(expected,actual.unwrap(),p.euclidean_distance(expected),p.euclidean_distance(&actual.unwrap()));
}
}
println!("正答率 {}%",success as f64 / COUNT as f64 * 100.);
}
#[test]
fn small_3d() {
const COUNT:usize = 100;
let mut kdt = KDTree::<3,f64,()>::new();
let mut rng = rand::thread_rng();
let mut positions:Vec<[f64;3]> = vec![];
for _ in 0..COUNT {
let mut pn = [0f64;3];
for i in 0..3 {
let mut p:f64 = rng.gen_range(-100000.0..100000.0);
let pi:u8 = rng.gen_range(0..10);
if let Some(last) = positions.last() {
if pi == 0 {
p = last[i];
}
}
pn[i] = p;
}
positions.push(pn.clone());
kdt.insert(pn,());
}
let mut success = 0;
for _ in 0..COUNT {
let x:f64 = rng.gen_range(-100000.0..100000.0);
let y:f64 = rng.gen_range(-100000.0..100000.0);
let z:f64 = rng.gen_range(-100000.0..100000.0);
let p = [x,y,z];
let expected = nearest(&p,&positions);
let actual = kdt.nearest_position(&p);
if (p.euclidean_distance(expected) - p.euclidean_distance(&actual.unwrap())) < 1. {
success += 1;
} else {
dbg!(expected,actual.unwrap(),p.euclidean_distance(expected),p.euclidean_distance(&actual.unwrap()));
}
}
println!("正答率 {}%",success as f64 / COUNT as f64 * 100.);
}
#[test]
fn small_2d_unbalance() {
const COUNT:usize = 100;
let mut kdt = KDTree::<2,f64,()>::new();
let mut rng = rand::thread_rng();
let mut positions:Vec<[f64;2]> = vec![];
for _ in 0..COUNT {
let mut pn = [0f64;2];
for i in 0..2 {
let mut p:f64 = rng.gen_range(-100000.0..100000.0);
let pi:u8 = rng.gen_range(0..10);
if let Some(last) = positions.last() {
if pi == 0 {
p = last[i];
}
}
pn[i] = p;
}
positions.push(pn.clone());
}
positions.sort_by(|a,b| a[0].partial_cmp(&b[0]).unwrap().then(a[1].partial_cmp(&b[1]).unwrap()) );
for p in &positions {
kdt.insert(p.clone(),());
}
let mut success = 0;
for _ in 0..COUNT {
let x:f64 = rng.gen_range(-100000.0..100000.0);
let y:f64 = rng.gen_range(-100000.0..100000.0);
let p = [x,y];
let expected = nearest(&p,&positions);
let actual = kdt.nearest_position(&p);
if (p.euclidean_distance(expected) - p.euclidean_distance(&actual.unwrap())) < 1. {
success += 1;
} else {
dbg!(expected,actual.unwrap(),p.euclidean_distance(expected),p.euclidean_distance(&actual.unwrap()));
}
}
println!("正答率 {}%",success as f64 / COUNT as f64 * 100.);
}
#[test]
fn large_2d() {
const COUNT:usize = 1000;
let mut kdt = KDTree::<2,f64,()>::new();
let mut rng = rand::thread_rng();
let mut positions:Vec<[f64;2]> = vec![];
for _ in 0..100000 {
let mut pn = [0f64;2];
for i in 0..2 {
let mut p:f64 = rng.gen_range(-100000.0..100000.0);
let pi:u8 = rng.gen_range(0..10);
if let Some(last) = positions.last() {
if pi == 0 {
p = last[i];
}
}
pn[i] = p;
}
positions.push(pn.clone());
kdt.insert(pn,());
}
for _ in 0..COUNT {
let x:f64 = rng.gen_range(-100000.0..100000.0);
let y:f64 = rng.gen_range(-100000.0..100000.0);
let p = [x,y];
let _ = kdt.nearest_position(&p);
}
}
#[test]
fn large_3d() {
const COUNT:usize = 1000;
let mut kdt = KDTree::<3,f64,()>::new();
let mut rng = rand::thread_rng();
let mut positions:Vec<[f64;3]> = vec![];
for _ in 0..100000 {
let mut pn = [0f64;3];
for i in 0..3 {
let mut p:f64 = rng.gen_range(-100000.0..100000.0);
let pi:u8 = rng.gen_range(0..10);
if let Some(last) = positions.last() {
if pi == 0 {
p = last[i];
}
}
pn[i] = p;
}
positions.push(pn.clone());
kdt.insert(pn,());
}
for _ in 0..COUNT {
let x:f64 = rng.gen_range(-100000.0..100000.0);
let y:f64 = rng.gen_range(-100000.0..100000.0);
let z:f64 = rng.gen_range(-100000.0..100000.0);
let p = [x,y,z];
let _ = kdt.nearest_position(&p);
}
}
#[test]
fn large_2d_unbalance() {
const COUNT:usize = 1000;
let mut kdt = KDTree::<2,f64,()>::new();
let mut rng = rand::thread_rng();
let mut positions:Vec<[f64;2]> = vec![];
for _ in 0..100000 {
let mut pn = [0f64;2];
for i in 0..2 {
let mut p:f64 = rng.gen_range(-100000.0..100000.0);
let pi:u8 = rng.gen_range(0..10);
if let Some(last) = positions.last() {
if pi == 0 {
p = last[i];
}
}
pn[i] = p;
}
positions.push(pn.clone());
}
positions.sort_by(|a,b| a[0].partial_cmp(&b[0]).unwrap().then(a[1].partial_cmp(&b[1]).unwrap()) );
for p in &positions {
kdt.insert(p.clone(),());
}
for _ in 0..COUNT {
let x:f64 = rng.gen_range(-100000.0..100000.0);
let y:f64 = rng.gen_range(-100000.0..100000.0);
let p = [x,y];
let _ = kdt.nearest_position(&p);
}
}