@@ -63,6 +63,17 @@ fn find_endpoint_groups(arcs: &[Arc], tolerance: f64) -> Vec<EndpointGroup> {
6363 all_endpoints. push ( ( arc. b , arc_idx, EndpointType :: End ) ) ;
6464 }
6565
66+ if all_endpoints. is_empty ( ) {
67+ return Vec :: new ( ) ;
68+ }
69+
70+ // Build spatial index of all endpoints
71+ let mut spatial_index = HilbertRTree :: with_capacity ( all_endpoints. len ( ) ) ;
72+ for ( point, _, _) in & all_endpoints {
73+ spatial_index. add_point ( point. x , point. y ) ;
74+ }
75+ spatial_index. build ( ) ;
76+
6677 let mut groups = Vec :: new ( ) ;
6778 let mut used = vec ! [ false ; all_endpoints. len( ) ] ;
6879
@@ -84,25 +95,38 @@ fn find_endpoint_groups(arcs: &[Arc], tolerance: f64) -> Vec<EndpointGroup> {
8495 group. arc_indices . push ( ( arc_i, end_type_i) ) ;
8596 used[ i] = true ;
8697
87- // Find all points within tolerance of any point in the current group
88- let mut changed = true ;
89- while changed {
90- changed = false ;
91- for j in 0 ..all_endpoints. len ( ) {
92- if used[ j] {
98+ // Find all points within tolerance using spatial index (iterative expansion)
99+ let mut queue = vec ! [ point_i] ;
100+
101+ while !queue. is_empty ( ) {
102+ let current_point = queue. pop ( ) . unwrap ( ) ;
103+
104+ // Query spatial index for points within tolerance of current_point
105+ let mut nearby_indices = Vec :: new ( ) ;
106+ spatial_index. query_circle (
107+ current_point. x ,
108+ current_point. y ,
109+ tolerance,
110+ & mut nearby_indices,
111+ ) ;
112+
113+ // Process each nearby point
114+ for idx in nearby_indices {
115+ if used[ idx] {
93116 continue ;
94117 }
95118
96- let ( point_j, arc_j, end_type_j) = all_endpoints[ j] ;
97-
98- // Check if point_j is close to any point in the current group
99- for & group_point in & group. points {
100- if ( point_j - group_point) . norm ( ) <= tolerance {
119+ // Get the actual point data from spatial index
120+ if let Some ( ( x, y) ) = spatial_index. get_point ( idx) {
121+ let point_j = Point :: new ( x, y) ;
122+ let ( _, arc_j, end_type_j) = all_endpoints[ idx] ;
123+
124+ // Verify actual distance (spatial index may be approximate)
125+ if ( point_j - current_point) . norm ( ) <= tolerance {
101126 group. points . push ( point_j) ;
102127 group. arc_indices . push ( ( arc_j, end_type_j) ) ;
103- used[ j] = true ;
104- changed = true ;
105- break ;
128+ used[ idx] = true ;
129+ queue. push ( point_j) ; // Add to queue for further expansion
106130 }
107131 }
108132 }
0 commit comments