@@ -5,7 +5,7 @@ use std::{
5
5
collections:: BinaryHeap ,
6
6
} ;
7
7
8
- use crate :: { IndexableNum , AABB } ;
8
+ use crate :: { try_control , ControlFlow , IndexableNum , NeighborVisitor , QueryVisitor , AABB } ;
9
9
10
10
/// Error type for errors that may be returned in attempting to build the index.
11
11
#[ derive( Debug , PartialEq ) ]
@@ -98,10 +98,10 @@ where
98
98
/// assert_eq!(query_results, vec![1]);
99
99
/// // the query may also be done with a visiting function that can stop the query early
100
100
/// let mut visited_results: Vec<usize> = Vec::new();
101
- /// let mut visitor = |box_added_pos: usize| -> bool {
101
+ /// let mut visitor = |box_added_pos: usize| -> Control<()> {
102
102
/// visited_results.push(box_added_pos);
103
- /// // return true to continue visiting results, false to stop early
104
- /// true
103
+ /// // return continue to continue visiting results, break to stop early
104
+ /// Control::Continue
105
105
/// };
106
106
///
107
107
/// index.visit_query(-1.0, -1.0, -0.5, -0.5, &mut visitor);
@@ -180,9 +180,7 @@ where
180
180
181
181
let mut n = num_items;
182
182
let mut num_nodes = num_items;
183
- let mut level_bounds: Vec < usize > = Vec :: new ( ) ;
184
-
185
- level_bounds. push ( n) ;
183
+ let mut level_bounds: Vec < usize > = vec ! [ n] ;
186
184
187
185
// calculate the total number of nodes in the R-tree to allocate space for
188
186
// and the index of each tree level (level_bounds, used in search later)
@@ -851,7 +849,6 @@ where
851
849
let mut results = Vec :: new ( ) ;
852
850
let mut visitor = |i| {
853
851
results. push ( i) ;
854
- true
855
852
} ;
856
853
self . visit_query ( min_x, min_y, max_x, max_y, & mut visitor) ;
857
854
results
@@ -900,11 +897,12 @@ where
900
897
901
898
/// Same as [StaticAABB2DIndex::query] but instead of returning a collection of indexes a
902
899
/// `visitor` function is called for each index that would be returned. The `visitor` returns a
903
- /// bool indicating whether to continue visiting (true) or not (false) .
900
+ /// control flow indicating whether to continue visiting or break .
904
901
#[ inline]
905
- pub fn visit_query < F > ( & self , min_x : T , min_y : T , max_x : T , max_y : T , visitor : & mut F )
902
+ pub fn visit_query < V , C > ( & self , min_x : T , min_y : T , max_x : T , max_y : T , visitor : & mut V )
906
903
where
907
- F : FnMut ( usize ) -> bool ,
904
+ C : ControlFlow ,
905
+ V : QueryVisitor < T , C > ,
908
906
{
909
907
let mut stack: Vec < usize > = Vec :: with_capacity ( 16 ) ;
910
908
self . visit_query_with_stack ( min_x, min_y, max_x, max_y, visitor, & mut stack) ;
@@ -974,7 +972,6 @@ where
974
972
let mut results = Vec :: new ( ) ;
975
973
let mut visitor = |i| {
976
974
results. push ( i) ;
977
- true
978
975
} ;
979
976
self . visit_query_with_stack ( min_x, min_y, max_x, max_y, & mut visitor, stack) ;
980
977
results
@@ -983,23 +980,25 @@ where
983
980
/// Same as [StaticAABB2DIndex::visit_query] but accepts an existing [Vec] to be used as a stack
984
981
/// buffer when performing the query to avoid the need for allocation (this is for performance
985
982
/// benefit only).
986
- pub fn visit_query_with_stack < F > (
983
+ pub fn visit_query_with_stack < V , C > (
987
984
& self ,
988
985
min_x : T ,
989
986
min_y : T ,
990
987
max_x : T ,
991
988
max_y : T ,
992
- visitor : & mut F ,
989
+ visitor : & mut V ,
993
990
stack : & mut Vec < usize > ,
994
- ) where
995
- F : FnMut ( usize ) -> bool ,
991
+ ) -> C
992
+ where
993
+ C : ControlFlow ,
994
+ V : QueryVisitor < T , C > ,
996
995
{
997
996
let mut node_index = self . boxes . len ( ) - 1 ;
998
997
let mut level = self . level_bounds . len ( ) - 1 ;
999
998
// ensure the stack is empty for use
1000
999
stack. clear ( ) ;
1001
1000
1002
- ' search_loop : loop {
1001
+ loop {
1003
1002
let end = min (
1004
1003
node_index + self . node_size ,
1005
1004
* get_at_index ! ( self . level_bounds, level) ,
@@ -1014,9 +1013,7 @@ where
1014
1013
1015
1014
let index = * get_at_index ! ( self . indices, pos) ;
1016
1015
if node_index < self . num_items {
1017
- if !visitor ( index) {
1018
- break ' search_loop;
1019
- }
1016
+ try_control ! ( visitor. visit( index) )
1020
1017
} else {
1021
1018
stack. push ( index) ;
1022
1019
stack. push ( level - 1 ) ;
@@ -1027,17 +1024,16 @@ where
1027
1024
level = stack. pop ( ) . unwrap ( ) ;
1028
1025
node_index = stack. pop ( ) . unwrap ( ) ;
1029
1026
} else {
1030
- break ' search_loop ;
1027
+ return C :: continuing ( ) ;
1031
1028
}
1032
1029
}
1033
1030
}
1034
1031
1035
1032
/// Visit all neighboring items in order of minimum euclidean distance to the point defined by
1036
- /// `x` and `y` until `visitor` returns false .
1033
+ /// `x` and `y` until `visitor` breaks or all items have been visited .
1037
1034
///
1038
1035
/// ## Notes
1039
- /// * The visitor function must return false to stop visiting items or all items will be
1040
- /// visited.
1036
+ /// * The visitor function must break to stop visiting items or all items will be visited.
1041
1037
/// * The visitor function receives the index of the item being visited and the squared
1042
1038
/// euclidean distance to that item from the point given.
1043
1039
/// * Because distances are squared (`dx * dx + dy * dy`) be cautious of smaller numeric types
@@ -1046,24 +1042,27 @@ where
1046
1042
/// * If repeatedly calling this method then [StaticAABB2DIndex::visit_neighbors_with_queue] can
1047
1043
/// be used to avoid repeated allocations for the priority queue used internally.
1048
1044
#[ inline]
1049
- pub fn visit_neighbors < F > ( & self , x : T , y : T , visitor : & mut F )
1045
+ pub fn visit_neighbors < V , C > ( & self , x : T , y : T , visitor : & mut V )
1050
1046
where
1051
- F : FnMut ( usize , T ) -> bool ,
1047
+ C : ControlFlow ,
1048
+ V : NeighborVisitor < T , C > ,
1052
1049
{
1053
1050
let mut queue = NeighborPriorityQueue :: new ( ) ;
1054
1051
self . visit_neighbors_with_queue ( x, y, visitor, & mut queue) ;
1055
1052
}
1056
1053
1057
1054
/// Works the same as [StaticAABB2DIndex::visit_neighbors] but accepts an existing binary heap
1058
1055
/// to be used as a priority queue to avoid allocations.
1059
- pub fn visit_neighbors_with_queue < F > (
1056
+ pub fn visit_neighbors_with_queue < V , C > (
1060
1057
& self ,
1061
1058
x : T ,
1062
1059
y : T ,
1063
- visitor : & mut F ,
1060
+ visitor : & mut V ,
1064
1061
queue : & mut NeighborPriorityQueue < T > ,
1065
- ) where
1066
- F : FnMut ( usize , T ) -> bool ,
1062
+ ) -> C
1063
+ where
1064
+ C : ControlFlow ,
1065
+ V : NeighborVisitor < T , C > ,
1067
1066
{
1068
1067
// small helper function to compute axis distance between point and bounding box axis
1069
1068
fn axis_dist < U > ( k : U , min : U , max : U ) -> U
@@ -1082,7 +1081,7 @@ where
1082
1081
let mut node_index = self . boxes . len ( ) - 1 ;
1083
1082
queue. clear ( ) ;
1084
1083
1085
- ' search_loop : loop {
1084
+ loop {
1086
1085
let upper_bound_level_index = match self . level_bounds . binary_search ( & node_index) {
1087
1086
// level bound found, add one to get upper bound
1088
1087
Ok ( i) => i + 1 ,
@@ -1113,10 +1112,7 @@ where
1113
1112
while let Some ( state) = queue. pop ( ) {
1114
1113
if state. is_leaf_node {
1115
1114
// visit leaf node
1116
- if !visitor ( state. index , state. dist ) {
1117
- // stop visiting if visitor returns false
1118
- break ' search_loop;
1119
- }
1115
+ try_control ! ( visitor. visit( state. index, state. dist) )
1120
1116
} else {
1121
1117
// update node index for next iteration
1122
1118
node_index = state. index ;
@@ -1127,7 +1123,7 @@ where
1127
1123
}
1128
1124
1129
1125
if !continue_search {
1130
- break ' search_loop ;
1126
+ return C :: continuing ( ) ;
1131
1127
}
1132
1128
}
1133
1129
}
0 commit comments