From 498f1fc9ab6510abc19e0669b967ed791139fd4d Mon Sep 17 00:00:00 2001 From: radevgit Date: Sat, 1 Nov 2025 19:36:26 +0200 Subject: [PATCH] Opt 11 - find_endpoint_groups with spatial index --- CHANGELOG.md | 3 ++ Cargo.lock | 18 ++++------ benches/bench_offset_multiple1000.rs | 6 ++++ benches/bench_offset_multiple200.rs | 7 ++-- benches/bench_offset_multiple500.rs | 5 +++ src/graph/merge_ends.rs | 52 ++++++++++++++++++++-------- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eaab0d..c720c10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## [0.5.5] - 2025-11-01 +- Opt 11 - find_endpoint_groups with spatial index (20% - 40%) + ## [0.5.4] - 2025-11-01 - Opt 10 - using aabb presplit check (29%) diff --git a/Cargo.lock b/Cargo.lock index 08d749c..09b1b56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,15 +4,9 @@ version = 4 [[package]] name = "aabb" -version = "0.5.0" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6eeb4d4b50edab9f821fbb477956d836afce5960681d018f62da89a35a1caa" - -[[package]] -name = "aabb" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c76f0dd88ad867edce6959a5959048c1c4ffe0a16813f66494b6df25c39f50" +checksum = "747e38385aa4a3673f7281ba9ec6b5ee21aca6928c2c10f6897e99799c809c7f" [[package]] name = "cfg-if" @@ -42,7 +36,7 @@ checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" name = "offroad" version = "0.5.4" dependencies = [ - "aabb 0.6.5", + "aabb", "rand", "robust", "togo", @@ -129,11 +123,11 @@ dependencies = [ [[package]] name = "togo" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb095a83564da255fbf7516c02c974e358a5eff774aa6d2b1c60f4695712cf6" +checksum = "9fe3547d41885004350d619d6a462d822d387d0150418ec69c084c5abcd2c984" dependencies = [ - "aabb 0.5.0", + "aabb", "robust", ] diff --git a/benches/bench_offset_multiple1000.rs b/benches/bench_offset_multiple1000.rs index dc72a93..3502c8f 100644 --- a/benches/bench_offset_multiple1000.rs +++ b/benches/bench_offset_multiple1000.rs @@ -61,5 +61,11 @@ Total time for 50 offset operations: 3.936534119s Average time per operation: 78.730682ms Operations per second: 12.7 _________________________________________________________ +Opt 11 - find_endpoint_groups with spatial index (40%) +Total time for 50 offset operations: 2.359176736s +Average time per operation: 47.183534ms +Operations per second: 21.2 +_________________________________________________________ + */ diff --git a/benches/bench_offset_multiple200.rs b/benches/bench_offset_multiple200.rs index f9c8b9a..2f70d4c 100644 --- a/benches/bench_offset_multiple200.rs +++ b/benches/bench_offset_multiple200.rs @@ -76,6 +76,9 @@ Total time for 1980 offset operations: 8.593364565s Average time per operation: 4.340083ms Operations per second: 230.4 __________________________________________________________ - - +Opt 11 - find_endpoint_groups with spatial index (29%) +Total time for 1980 offset operations: 6.082281414s +Average time per operation: 3.071859ms +Operations per second: 325.5 +__________________________________________________________ */ diff --git a/benches/bench_offset_multiple500.rs b/benches/bench_offset_multiple500.rs index 0804cd9..3b86bb2 100644 --- a/benches/bench_offset_multiple500.rs +++ b/benches/bench_offset_multiple500.rs @@ -61,5 +61,10 @@ Total time for 198 offset operations: 3.054654626s Average time per operation: 15.427548ms Operations per second: 64.8 _______________________________________________________________ +Opt 11 - find_endpoint_groups with spatial index +Total time for 198 offset operations: 2.298718087s +Average time per operation: 11.609687ms +Operations per second: 86.1 +_______________________________________________________________ */ diff --git a/src/graph/merge_ends.rs b/src/graph/merge_ends.rs index fe6fb2d..c9c6c8a 100644 --- a/src/graph/merge_ends.rs +++ b/src/graph/merge_ends.rs @@ -63,6 +63,17 @@ fn find_endpoint_groups(arcs: &[Arc], tolerance: f64) -> Vec { all_endpoints.push((arc.b, arc_idx, EndpointType::End)); } + if all_endpoints.is_empty() { + return Vec::new(); + } + + // Build spatial index of all endpoints + let mut spatial_index = HilbertRTree::with_capacity(all_endpoints.len()); + for (point, _, _) in &all_endpoints { + spatial_index.add_point(point.x, point.y); + } + spatial_index.build(); + let mut groups = Vec::new(); let mut used = vec![false; all_endpoints.len()]; @@ -84,25 +95,38 @@ fn find_endpoint_groups(arcs: &[Arc], tolerance: f64) -> Vec { group.arc_indices.push((arc_i, end_type_i)); used[i] = true; - // Find all points within tolerance of any point in the current group - let mut changed = true; - while changed { - changed = false; - for j in 0..all_endpoints.len() { - if used[j] { + // Find all points within tolerance using spatial index (iterative expansion) + let mut queue = vec![point_i]; + + while !queue.is_empty() { + let current_point = queue.pop().unwrap(); + + // Query spatial index for points within tolerance of current_point + let mut nearby_indices = Vec::new(); + spatial_index.query_circle( + current_point.x, + current_point.y, + tolerance, + &mut nearby_indices, + ); + + // Process each nearby point + for idx in nearby_indices { + if used[idx] { continue; } - let (point_j, arc_j, end_type_j) = all_endpoints[j]; - - // Check if point_j is close to any point in the current group - for &group_point in &group.points { - if (point_j - group_point).norm() <= tolerance { + // Get the actual point data from spatial index + if let Some((x, y)) = spatial_index.get_point(idx) { + let point_j = Point::new(x, y); + let (_, arc_j, end_type_j) = all_endpoints[idx]; + + // Verify actual distance (spatial index may be approximate) + if (point_j - current_point).norm() <= tolerance { group.points.push(point_j); group.arc_indices.push((arc_j, end_type_j)); - used[j] = true; - changed = true; - break; + used[idx] = true; + queue.push(point_j); // Add to queue for further expansion } } }