use aabb::HilbertRTree;
use rand::Rng;
use rand::SeedableRng;
use std::time::Instant;
fn add_random_box<R: Rng>(rng: &mut R, boxes: &mut Vec<f64>, max_size: f64) {
let min_x = rng.random_range(0.0..(100.0 - max_size));
let min_y = rng.random_range(0.0..(100.0 - max_size));
let box_width = rng.random_range(0.0..max_size);
let box_height = rng.random_range(0.0..max_size);
let max_x = min_x + box_width;
let max_y = min_y + box_height;
boxes.push(min_x);
boxes.push(min_y);
boxes.push(max_x);
boxes.push(max_y);
}
fn bench_search(
tree: &HilbertRTree,
boxes: &[f64],
num_tests: usize,
percentage_str: &str,
) {
let mut results = Vec::new();
let start = Instant::now();
for chunk in boxes.chunks(4) {
if chunk.len() == 4 {
results.clear();
tree.query_intersecting(chunk[0], chunk[1], chunk[2], chunk[3], &mut results);
}
}
let elapsed = start.elapsed();
println!(
"{} searches {}%: {}ms",
num_tests,
percentage_str,
elapsed.as_millis()
);
}
fn bench_neighbors(
tree: &HilbertRTree,
coords: &[f64],
num_tests: usize,
k: usize,
) {
let mut results = Vec::new();
let start = Instant::now();
for i in 0..num_tests {
results.clear();
let x = coords[4 * i];
let y = coords[4 * i + 1];
tree.query_nearest_k(x, y, k, &mut results);
}
let elapsed = start.elapsed();
println!(
"{} searches of {} neighbors: {}ms",
num_tests,
k,
elapsed.as_millis()
);
}
fn main() {
println!("AABB Hierarchical Hilbert R-tree Benchmark");
println!("=========================================\n");
let num_items = 1_000_000;
let num_tests = 1_000;
let seed = 95756739_u64;
let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
let mut coords = Vec::new();
for _ in 0..num_items {
add_random_box(&mut rng, &mut coords, 1.0);
}
let mut boxes_100 = Vec::new(); let mut boxes_10 = Vec::new(); let mut boxes_1 = Vec::new(); let mut boxes_50 = Vec::new(); let mut boxes_100_full = Vec::new();
for _ in 0..num_tests {
boxes_100_full.push(0.0);
boxes_100_full.push(0.0);
boxes_100_full.push(100.0);
boxes_100_full.push(100.0);
add_random_box(&mut rng, &mut boxes_50, (0.5_f64).sqrt() * 100.0);
add_random_box(&mut rng, &mut boxes_100, (0.1_f64).sqrt() * 100.0);
add_random_box(&mut rng, &mut boxes_10, 10.0);
add_random_box(&mut rng, &mut boxes_1, 1.0);
}
println!("Building index with {} items...", num_items);
let start = Instant::now();
let mut tree = HilbertRTree::with_capacity(num_items);
for chunk in coords.chunks(4) {
if chunk.len() == 4 {
tree.add(chunk[0], chunk[1], chunk[2], chunk[3]);
}
}
tree.build();
let build_time = start.elapsed();
println!(
"Index built in {:.2}ms\n",
build_time.as_secs_f64() * 1000.0
);
println!("Running query benchmarks:");
println!("-----------------------");
bench_search(&tree, &boxes_100_full, num_tests, "100");
bench_search(&tree, &boxes_50, num_tests, "50");
bench_search(&tree, &boxes_100, num_tests, "10");
bench_search(&tree, &boxes_10, num_tests, "1");
bench_search(&tree, &boxes_1, num_tests, "0.01");
println!();
println!("Running neighbor benchmarks:");
println!("-----------------------");
bench_neighbors(&tree, &coords, num_tests, 100);
bench_neighbors(&tree, &coords, 1, num_items);
bench_neighbors(&tree, &coords, num_items / 10, 1);
println!();
}