Skip to content

Commit 4812515

Browse files
committed
Breaking renaming change, minor code cleanup, and improve doc comments
1 parent e577de0 commit 4812515

File tree

4 files changed

+79
-61
lines changed

4 files changed

+79
-61
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to the static_aabb2d_index crate will be documented in this
44

55
## Unreleased
66

7+
### Added ⭐
8+
9+
- Added `item_indices` method to get a slice over the indices for all item boxes added.
10+
711
### Changed 🔧
812

913
- ⚠️ BREAKING: Index now supports being empty (no longer errors when building the index if item
@@ -14,6 +18,9 @@ All notable changes to the static_aabb2d_index crate will be documented in this
1418
`visit_query_with_stack` function.
1519
- ⚠️ BREAKING: fixed inconsistency in `visit_neighbors` function to return break result the same as
1620
the `visit_neighbors_with_queue` function.
21+
- ⚠️ BREAKING: renamed `map_all_boxes_index` function to `all_box_indices` and changed signature to
22+
return a slice rather than indexing into a slice internally.
23+
- Improved doc comments
1724

1825
## 0.7.1 - 2023-02-22
1926

examples/index_tree_structure.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,21 @@ fn main() {
5858
// dbg!(index.indices_map().len());
5959
// dbg!(index.indices_map()[125]);
6060

61-
// in order to access the actual tree node relations the map_all_boxes_index method can be used
61+
// in order to access the actual tree node relations the all_box_indices method can be used
6262
// the indices_map will return the start index of the children for a given node index
6363
// or map back to the added item index in the case that the node has no children
6464

6565
// going from all_boxes index to the index the item was originally added
6666
for i in 0..index.count() {
67-
let added_item_index = index.map_all_boxes_index(i);
67+
let added_item_index = index.all_box_indices()[i];
6868
assert_eq!(input_boxes[added_item_index], all_boxes[i]);
6969
}
7070

7171
// finding children node start index for a node
7272
// note: accessing index past the item count so it must be a node with children
7373
let parent_node_index = index.count() + 5;
74-
let children_start_index = index.map_all_boxes_index(parent_node_index);
75-
let children_end_index = index.map_all_boxes_index(parent_node_index + 1);
74+
let children_start_index = index.all_box_indices()[parent_node_index];
75+
let children_end_index = index.all_box_indices()[parent_node_index + 1];
7676

7777
let child_indices: Vec<usize> = (children_start_index..children_end_index).collect();
7878
// all child boxes should be contained by their parent
@@ -85,12 +85,12 @@ fn main() {
8585
// here we loop through all the parent nodes and check that their child boxes are within
8686
// the parent nodes extents and handle the case of the root node
8787
for parent_node_index in index.count()..all_boxes.len() - 1 {
88-
let children_start_index = index.map_all_boxes_index(parent_node_index);
88+
let children_start_index = index.all_box_indices()[parent_node_index];
8989
let children_end_index = if parent_node_index == all_boxes.len() - 1 {
9090
// root node, all_boxes length is the end
9191
all_boxes.len()
9292
} else {
93-
index.map_all_boxes_index(parent_node_index + 1)
93+
index.all_box_indices()[parent_node_index + 1]
9494
};
9595

9696
// all child boxes should be contained by their parent

src/static_aabb2d_index.rs

Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use fmt::Debug;
22
use std::fmt;
3-
use std::{
4-
cmp::{max, min},
5-
collections::BinaryHeap,
6-
};
3+
use std::{cmp::min, collections::BinaryHeap};
74

85
use crate::{try_control, ControlFlow, IndexableNum, NeighborVisitor, QueryVisitor, AABB};
96

@@ -62,7 +59,7 @@ where
6259
/// Static/fixed size indexing data structure for two dimensional axis aligned bounding boxes.
6360
///
6461
/// The index allows for fast construction and fast querying but cannot be modified after creation.
65-
/// This type is constructed from a [StaticAABB2DIndexBuilder].
62+
/// This type is constructed from a [`StaticAABB2DIndexBuilder`].
6663
///
6764
/// 2D axis aligned bounding boxes are represented by two extent points (four values):
6865
/// (min_x, min_y), (max_x, max_y).
@@ -157,7 +154,7 @@ where
157154
};
158155
}
159156

160-
let node_size = min(max(node_size, 2), 65535);
157+
let node_size = node_size.clamp(2, 65535);
161158

162159
let mut n = num_items;
163160
let mut num_nodes = num_items;
@@ -186,19 +183,19 @@ where
186183
}
187184
}
188185

189-
/// Construct a new [StaticAABB2DIndexBuilder] to fit exactly the specified `count` number of
186+
/// Construct a new [`StaticAABB2DIndexBuilder`] to fit exactly the specified `count` number of
190187
/// items.
191188
#[inline]
192189
pub fn new(count: usize) -> Self {
193190
StaticAABB2DIndexBuilder::init(count, 16)
194191
}
195192

196-
/// Construct a new [StaticAABB2DIndexBuilder] to fit exactly the specified `count` number of
193+
/// Construct a new [`StaticAABB2DIndexBuilder`] to fit exactly the specified `count` number of
197194
/// items and use `node_size` for the index tree shape.
198195
///
199196
/// Each node in the index tree has a maximum size which may be adjusted by `node_size` for
200197
/// performance reasons, however the default value of 16 when calling
201-
/// `StaticAABB2DIndexBuilder::new` is tested to be optimal in most cases.
198+
/// [`StaticAABB2DIndexBuilder::new`] is tested to be optimal in most cases.
202199
///
203200
/// If `node_size` is less than 2 then 2 is used, if `node_size` is greater than 65535 then
204201
/// 65535 is used.
@@ -212,7 +209,8 @@ where
212209
///
213210
/// For performance reasons the sanity checks of `min_x <= max_x` and `min_y <= max_y` are only
214211
/// debug asserted. If an invalid box is added it may lead to a panic or unexpected behavior
215-
/// from the constructed [StaticAABB2DIndex].
212+
/// from the constructed [`StaticAABB2DIndex`].
213+
#[inline]
216214
pub fn add(&mut self, min_x: T, min_y: T, max_x: T, max_y: T) -> &mut Self {
217215
// catch adding past num_items (error will be returned when build is called)
218216
if self.pos >= self.num_items {
@@ -231,13 +229,13 @@ where
231229
self
232230
}
233231

234-
/// Build the [StaticAABB2DIndex] with the boxes that have been added.
232+
/// Build the [`StaticAABB2DIndex`] with the boxes that have been added.
235233
///
236234
/// If the number of added items does not match the count given at the time the builder was
237-
/// created then a [StaticAABB2DIndexBuildError::ItemCountError] will be returned.
235+
/// created then a [`StaticAABB2DIndexBuildError::ItemCountError`] will be returned.
238236
///
239237
/// If the numeric type T fails to cast to/from a u16 for any reason then a
240-
/// [StaticAABB2DIndexBuildError::NumericCastError] will be returned.
238+
/// [`StaticAABB2DIndexBuildError::NumericCastError`] will be returned.
241239
pub fn build(mut self) -> Result<StaticAABB2DIndex<T>, StaticAABB2DIndexBuildError> {
242240
if self.pos != self.num_items {
243241
return Err(StaticAABB2DIndexBuildError::ItemCountError {
@@ -379,7 +377,7 @@ where
379377
/// Maps 2d space to 1d hilbert curve space.
380378
///
381379
/// 2d space is `x: [0 -> n-1]` and `y: [0 -> n-1]`, 1d hilbert curve value space is
382-
/// `d: [0 -> n^2 - 1]`, where n = 2^16, so `x` and `y` must be between 0 and [u16::MAX]
380+
/// `d: [0 -> n^2 - 1]`, where n = 2^16, so `x` and `y` must be between 0 and [`u16::MAX`]
383381
/// (65535 or 2^16 - 1).
384382
pub fn hilbert_xy_to_index(x: u16, y: u16) -> u32 {
385383
let x = x as u32;
@@ -762,13 +760,15 @@ where
762760

763761
/// Type alias for priority queue used for nearest neighbor searches.
764762
///
765-
/// See: [StaticAABB2DIndex::visit_neighbors_with_queue].
763+
/// See: [`StaticAABB2DIndex::visit_neighbors_with_queue`].
766764
pub type NeighborPriorityQueue<T> = BinaryHeap<NeighborsState<T>>;
767765

768766
/// Holds state for priority queue used in nearest neighbors query.
769767
///
770768
/// Note this type is public for use in passing in an existing priority queue but
771769
/// all fields and constructor are private for internal use only.
770+
///
771+
/// See also: [`StaticAABB2DIndex::visit_neighbors_with_queue`].
772772
#[derive(Debug, Copy, Clone, PartialEq)]
773773
pub struct NeighborsState<T>
774774
where
@@ -828,18 +828,18 @@ where
828828
self.boxes.last().copied()
829829
}
830830

831-
/// Gets the total count of items that were added to the index.
831+
/// Gets the total count of items that were added to the index during construction.
832832
#[inline]
833833
pub fn count(&self) -> usize {
834834
self.num_items
835835
}
836836

837-
/// Queries the index, returning a collection of indexes to items that overlap with the bounding
837+
/// Queries the index, returning a collection of indices to items that overlap with the bounding
838838
/// box given.
839839
///
840840
/// `min_x`, `min_y`, `max_x`, and `max_y` represent the bounding box to use for the query.
841841
/// Indexes returned match with the order items were added to the index using
842-
/// [StaticAABB2DIndexBuilder::add].
842+
/// [`StaticAABB2DIndexBuilder::add`].
843843
#[inline]
844844
pub fn query(&self, min_x: T, min_y: T, max_x: T, max_y: T) -> Vec<usize> {
845845
let mut results = Vec::new();
@@ -850,8 +850,8 @@ where
850850
results
851851
}
852852

853-
/// The same as [StaticAABB2DIndex::query] but instead of returning a [Vec] of results a lazy
854-
/// iterator is returned which yields the results.
853+
/// The same as [`StaticAABB2DIndex::query`] but instead of returning a [`Vec`] of results a
854+
/// iterator is returned which yields the results by lazily querying the index.
855855
///
856856
/// # Examples
857857
/// ```
@@ -877,8 +877,9 @@ where
877877
QueryIterator::<'a, T>::new(self, min_x, min_y, max_x, max_y)
878878
}
879879

880-
/// The same as [StaticAABB2DIndex::query_iter] but allows using an existing buffer for stack
881-
/// traversal.
880+
/// The same as [`StaticAABB2DIndex::query_iter`] but allows using an existing buffer for stack
881+
/// traversal. This is useful for performance when many queries will be done repeatedly to avoid
882+
/// allocating a new stack for each query (this is for performance benefit only).
882883
#[inline]
883884
pub fn query_iter_with_stack<'a>(
884885
&'a self,
@@ -891,9 +892,13 @@ where
891892
QueryIteratorStackRef::<'a, T>::new(self, stack, min_x, min_y, max_x, max_y)
892893
}
893894

894-
/// Same as [StaticAABB2DIndex::query] but instead of returning a collection of indexes a
895+
/// Same as [`StaticAABB2DIndex::query`] but instead of returning a collection of indices a
895896
/// `visitor` function is called for each index that would be returned. The `visitor` returns a
896897
/// control flow indicating whether to continue visiting or break.
898+
///
899+
/// The [`ControlFlow`] and [`QueryVisitor`] traits are implemented to allow passing in a
900+
/// function [`FnMut`] visitor that returns no value (all results will be visited ) or a
901+
/// [`ControlFlow`] to break early.
897902
#[inline]
898903
pub fn visit_query<V, C>(&self, min_x: T, min_y: T, max_x: T, max_y: T, visitor: &mut V) -> C
899904
where
@@ -908,16 +913,24 @@ where
908913
self.visit_query_with_stack_impl(min_x, min_y, max_x, max_y, visitor, &mut stack)
909914
}
910915

911-
/// Returns all the item [AABB] that were added to the index by [StaticAABB2DIndexBuilder::add].
916+
/// Returns all the item [`AABB`] that were added to the index by
917+
/// [`StaticAABB2DIndexBuilder::add`] during construction.
912918
///
913-
/// Use [StaticAABB2DIndex::map_all_boxes_index] to map a box back to the original index
914-
/// position it was added.
919+
/// Use [`StaticAABB2DIndex::item_indices`] or [`StaticAABB2DIndex::all_box_indices`] to map a
920+
/// box's positional index to the original index position the item was added.
915921
#[inline]
916922
pub fn item_boxes(&self) -> &[AABB<T>] {
917923
&self.boxes[0..self.num_items]
918924
}
919925

920-
/// Gets the node size used for the [StaticAABB2DIndex].
926+
/// Used to map an item box index position from [`StaticAABB2DIndex::item_boxes`] back to the
927+
/// original index position the item was added.
928+
#[inline]
929+
pub fn item_indices(&self) -> &[usize] {
930+
&self.indices[0..self.num_items]
931+
}
932+
933+
/// Gets the node size used for the index.
921934
///
922935
/// The node size is the maximum number of boxes stored as children of each node in the index
923936
/// tree.
@@ -926,40 +939,38 @@ where
926939
self.node_size
927940
}
928941

929-
/// Gets the level bounds for all the boxes in the [StaticAABB2DIndex].
942+
/// Gets the level bounds for all the boxes in the index.
930943
///
931-
/// The level bounds are the index positions in [StaticAABB2DIndex::all_boxes] where a change in
932-
/// the level of the index tree occurs.
944+
/// The level bounds are the index positions in [`StaticAABB2DIndex::all_boxes`] where a change
945+
/// in the level of the index tree occurs.
933946
#[inline]
934947
pub fn level_bounds(&self) -> &[usize] {
935948
&self.level_bounds
936949
}
937950

938-
/// Gets all the bounding boxes for the [StaticAABB2DIndex].
951+
/// Gets all the bounding boxes for the index.
939952
///
940953
/// The boxes are ordered from the bottom of the tree up, so from 0 to
941-
/// [StaticAABB2DIndex::count] are all the item bounding boxes. Use
942-
/// [StaticAABB2DIndex::map_all_boxes_index] to map a box back to the original index position it
954+
/// [`StaticAABB2DIndex::count`] are all the item bounding boxes. Use
955+
/// [`StaticAABB2DIndex::all_box_indices`] to map a box back to the original index position it
943956
/// was added or find the start position for the children of a node box.
944957
#[inline]
945958
pub fn all_boxes(&self) -> &[AABB<T>] {
946959
&self.boxes
947960
}
948961

949-
/// Gets the original item index position (from the time it was added) from a
950-
/// [StaticAABB2DIndex::all_boxes] slice index position.
951-
///
952-
/// If `all_boxes_index` is greater than [StaticAABB2DIndex::count] then it will return the
953-
/// [StaticAABB2DIndex::all_boxes] starting index of the node's children boxes.
954-
/// See the index_tree_structure.rs example for more information.
962+
/// Used to map an item box index position from [`StaticAABB2DIndex::all_boxes`] back to the
963+
/// original index position the item was added. Or if indexing past [`StaticAABB2DIndex::count`]
964+
/// it will yield the [`StaticAABB2DIndex::all_boxes`] starting index of the node's children
965+
/// boxes. See the `index_tree_structure.rs` example for more information.
955966
#[inline]
956-
pub fn map_all_boxes_index(&self, all_boxes_index: usize) -> usize {
957-
self.indices[all_boxes_index]
967+
pub fn all_box_indices(&self) -> &[usize] {
968+
&self.indices
958969
}
959970

960-
/// Same as [StaticAABB2DIndex::query] but accepts an existing [Vec] to be used as a stack
961-
/// buffer when performing the query to avoid the need for allocation (this is for performance
962-
/// benefit only).
971+
/// Same as [`StaticAABB2DIndex::query`] but allows using an existing buffer for stack
972+
/// traversal. This is useful for performance when many queries will be done repeatedly to avoid
973+
/// allocating a new stack for each query (this is for performance benefit only).
963974
#[inline]
964975
pub fn query_with_stack(
965976
&self,
@@ -977,9 +988,9 @@ where
977988
results
978989
}
979990

980-
/// Same as [StaticAABB2DIndex::visit_query] but accepts an existing [Vec] to be used as a stack
981-
/// buffer when performing the query to avoid the need for allocation (this is for performance
982-
/// benefit only).
991+
/// Same as [`StaticAABB2DIndex::visit_query`] but allows using an existing buffer for stack
992+
/// traversal. This is useful for performance when many queries will be done repeatedly to avoid
993+
/// allocating a new stack for each query (this is for performance benefit only).
983994
#[inline]
984995
pub fn visit_query_with_stack<V, C>(
985996
&self,
@@ -1062,8 +1073,8 @@ where
10621073
/// * Because distances are squared (`dx * dx + dy * dy`) be cautious of smaller numeric types
10631074
/// overflowing (e.g. it's easy to overflow an i32 with squared distances).
10641075
/// * If the point is inside of an item's bounding box then the euclidean distance is 0.
1065-
/// * If repeatedly calling this method then [StaticAABB2DIndex::visit_neighbors_with_queue] can
1066-
/// be used to avoid repeated allocations for the priority queue used internally.
1076+
/// * If repeatedly calling this method then [`StaticAABB2DIndex::visit_neighbors_with_queue`]
1077+
/// can be used to avoid repeated allocations for the priority queue used internally.
10671078
#[inline]
10681079
pub fn visit_neighbors<V, C>(&self, x: T, y: T, visitor: &mut V) -> C
10691080
where
@@ -1078,7 +1089,7 @@ where
10781089
self.visit_neighbors_with_queue_impl(x, y, visitor, &mut queue)
10791090
}
10801091

1081-
/// Works the same as [StaticAABB2DIndex::visit_neighbors] but accepts an existing binary heap
1092+
/// Works the same as [`StaticAABB2DIndex::visit_neighbors`] but accepts an existing binary heap
10821093
/// to be used as a priority queue to avoid allocations.
10831094
#[inline]
10841095
pub fn visit_neighbors_with_queue<V, C>(

tests/test.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,19 +212,19 @@ fn many_tree_levels() {
212212

213213
let all_boxes = index.all_boxes();
214214

215-
// map_all_boxes_index should map back to original aabb index
215+
// all_box_indices should map back to original aabb index
216216
for (i, curr_box) in all_boxes.iter().enumerate().take(index.count()) {
217-
let added_item_index = index.map_all_boxes_index(i);
217+
let added_item_index = index.all_box_indices()[i];
218218
assert_eq!(&input_boxes[added_item_index], curr_box);
219219
}
220220

221-
// map_all_boxes_index should get child start index
221+
// all_box_indices should get child start index
222222
for parent_node_index in index.count()..all_boxes.len() - 1 {
223-
let children_start_index = index.map_all_boxes_index(parent_node_index);
223+
let children_start_index = index.all_box_indices()[parent_node_index];
224224
let children_end_index = if parent_node_index == all_boxes.len() - 1 {
225225
all_boxes.len()
226226
} else {
227-
index.map_all_boxes_index(parent_node_index + 1)
227+
index.all_box_indices()[parent_node_index + 1]
228228
};
229229

230230
// all child boxes should be contained by their parent

0 commit comments

Comments
 (0)