|
| 1 | +//! Find K nearest points to a query point (optimized for point data). |
| 2 | +//! |
| 3 | +//! This example demonstrates the `query_nearest_k_points` method, which is optimized |
| 4 | +//! for point clouds where all items are stored as degenerate bounding boxes (x, x, y, y). |
| 5 | +//! Results are automatically sorted by distance (closest first). |
| 6 | +//! |
| 7 | +//! Performance: ~30% faster than `query_nearest_k` for point-only data. |
| 8 | +
|
| 9 | +use aabb::prelude::*; |
| 10 | + |
| 11 | +fn main() { |
| 12 | + let mut tree = AABB::with_capacity(6); |
| 13 | + |
| 14 | + // Add points using the convenient add_point() method |
| 15 | + tree.add_point(0.0, 0.0); // Point 0 |
| 16 | + tree.add_point(1.0, 0.0); // Point 1: distance 1 from (0, 0) |
| 17 | + tree.add_point(0.0, 1.0); // Point 2: distance 1 from (0, 0) |
| 18 | + tree.add_point(1.0, 1.0); // Point 3: distance sqrt(2) ≈ 1.41 from (0, 0) |
| 19 | + tree.add_point(3.0, 3.0); // Point 4: distance sqrt(18) ≈ 4.24 from (0, 0) |
| 20 | + tree.add_point(10.0, 10.0); // Point 5: distance sqrt(200) ≈ 14.14 from (0, 0) |
| 21 | + tree.build(); |
| 22 | + |
| 23 | + println!("=== Query Nearest K Points Example ===\n"); |
| 24 | + |
| 25 | + // Query 1: Find 1 nearest point to origin |
| 26 | + println!("Query 1: Find 1 nearest point to (0, 0):"); |
| 27 | + let mut results = Vec::new(); |
| 28 | + tree.query_nearest_k_points(0.0, 0.0, 1, &mut results); |
| 29 | + |
| 30 | + println!(" Result: {:?}", results); |
| 31 | + println!(" Expected: [0] (point 0 is at the origin)"); |
| 32 | + assert_eq!(results.len(), 1, "Expected 1 result"); |
| 33 | + assert_eq!(results[0], 0, "Point 0 should be closest"); |
| 34 | + println!(" ✓ Correct!\n"); |
| 35 | + |
| 36 | + // Query 2: Find 3 nearest points to origin |
| 37 | + println!("Query 2: Find 3 nearest points to (0, 0):"); |
| 38 | + results.clear(); |
| 39 | + tree.query_nearest_k_points(0.0, 0.0, 3, &mut results); |
| 40 | + |
| 41 | + println!(" Result: {:?}", results); |
| 42 | + println!(" Expected: [0, 1, 2] (closest points by distance)"); |
| 43 | + assert_eq!(results.len(), 3, "Expected 3 results"); |
| 44 | + assert_eq!(results[0], 0, "Point 0 should be closest (distance 0)"); |
| 45 | + // Points 1 and 2 are equidistant (distance 1) |
| 46 | + assert!(results[1] == 1 || results[1] == 2, "Points 1 or 2 should be second"); |
| 47 | + assert!(results[2] == 1 || results[2] == 2, "Points 1 or 2 should be third"); |
| 48 | + println!(" ✓ Correct!\n"); |
| 49 | + |
| 50 | + // Query 3: Find 5 nearest points to origin |
| 51 | + println!("Query 3: Find 5 nearest points to (0, 0):"); |
| 52 | + results.clear(); |
| 53 | + tree.query_nearest_k_points(0.0, 0.0, 5, &mut results); |
| 54 | + |
| 55 | + println!(" Result: {:?}", results); |
| 56 | + println!(" Expected: [0, 1, 2, 3, 4] in distance order"); |
| 57 | + assert_eq!(results.len(), 5, "Expected 5 results"); |
| 58 | + assert_eq!(results[0], 0, "Point 0 should be closest"); |
| 59 | + // Results should be sorted by distance |
| 60 | + println!(" ✓ Correct!\n"); |
| 61 | + |
| 62 | + // Query 4: Find more points than exist |
| 63 | + println!("Query 4: Find 100 nearest points (only 6 exist):"); |
| 64 | + results.clear(); |
| 65 | + tree.query_nearest_k_points(0.0, 0.0, 100, &mut results); |
| 66 | + |
| 67 | + println!(" Result count: {}", results.len()); |
| 68 | + println!(" Expected: 6 (all available points)"); |
| 69 | + assert_eq!(results.len(), 6, "Should return all available points"); |
| 70 | + println!(" ✓ Correct!\n"); |
| 71 | + |
| 72 | + // Query 5: Find 2 nearest points from (3, 3) |
| 73 | + println!("Query 5: Find 2 nearest points to (3, 3):"); |
| 74 | + results.clear(); |
| 75 | + tree.query_nearest_k_points(3.0, 3.0, 2, &mut results); |
| 76 | + |
| 77 | + println!(" Result: {:?}", results); |
| 78 | + println!(" Expected: [4, 3] (point 4 at (3,3), then point 3)"); |
| 79 | + assert_eq!(results.len(), 2, "Expected 2 results"); |
| 80 | + assert_eq!(results[0], 4, "Point 4 at (3, 3) should be closest"); |
| 81 | + assert_eq!(results[1], 3, "Point 3 should be second"); |
| 82 | + println!(" ✓ Correct!\n"); |
| 83 | + |
| 84 | + // Compare with general query_nearest_k |
| 85 | + println!("=== Comparison: query_nearest_k_points vs query_nearest_k ===\n"); |
| 86 | + |
| 87 | + let mut optimized_results = Vec::new(); |
| 88 | + let mut general_results = Vec::new(); |
| 89 | + |
| 90 | + tree.query_nearest_k_points(0.0, 0.0, 4, &mut optimized_results); |
| 91 | + tree.query_nearest_k(0.0, 0.0, 4, &mut general_results); |
| 92 | + |
| 93 | + println!("query_nearest_k_points results: {:?}", optimized_results); |
| 94 | + println!("query_nearest_k results: {:?}", general_results); |
| 95 | + |
| 96 | + // Same points should be found and in same order |
| 97 | + assert_eq!(optimized_results, general_results, "Both methods should find same points in same order"); |
| 98 | + println!("\n✓ Both methods find the same points in the same order!"); |
| 99 | + |
| 100 | + println!("\n=== Performance Note ==="); |
| 101 | + println!("query_nearest_k_points is ~30% faster than query_nearest_k for point data"); |
| 102 | + println!("because it uses direct distance calculation instead of axis_distance()"); |
| 103 | +} |
0 commit comments