From 996f83e92a62cff027db74a55974bf27273d0109 Mon Sep 17 00:00:00 2001 From: jeangab Date: Mon, 14 Aug 2023 10:05:46 -0400 Subject: [PATCH] wip: Spacial index coming along pretty well, some tests and documentation left to write and should be good to go --- src/space_colonization/mod.rs | 1 + src/space_colonization/spacial_index.rs | 110 ++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/space_colonization/spacial_index.rs diff --git a/src/space_colonization/mod.rs b/src/space_colonization/mod.rs index 2d6669e..85b6528 100644 --- a/src/space_colonization/mod.rs +++ b/src/space_colonization/mod.rs @@ -5,6 +5,7 @@ pub use point::*; mod space_colonization; pub use space_colonization::*; mod math; +mod spacial_index; #[wasm_bindgen] extern "C" { diff --git a/src/space_colonization/spacial_index.rs b/src/space_colonization/spacial_index.rs new file mode 100644 index 0000000..d5158b0 --- /dev/null +++ b/src/space_colonization/spacial_index.rs @@ -0,0 +1,110 @@ +use super::Point; + +#[derive(Debug)] +struct SpatialIndex { + elements: Vec>, + number_cells_x: i32, + cell_size: i32, +} + +impl SpatialIndex { + pub fn new(max_point: Point, cell_size: i32) -> SpatialIndex { + // Here we add 1 to number cells x and y to handle the right and bottom edges where + // x = max_point.x or y = max_point.y + // For example, with max_point of (100,100) + // the point 100,100 is valid but 100/10 = 10, which is out of bounds of a zero based + // array of length 10. So we add 1 to the length and 10 is a valid index in a zero based + // array of length 11 + let number_cells_x = (max_point.x / cell_size) + 1; + let number_cells = number_cells_x * ((max_point.y / cell_size) + 1); + let mut elements = Vec::with_capacity(number_cells as usize); + for _ in 0..number_cells { + elements.push(Vec::new()); + } + SpatialIndex { + elements, + cell_size, + number_cells_x, + } + } + + /// Adds an element in the cell of point + /// + /// panics if the point is outside of + pub fn add(&mut self, point: &Point, element: T) { + let element_index = self.get_index_from_position(point); + dbg!(element_index); + self.elements + .get_mut(element_index as usize) + .unwrap() + .push(element); + } + + pub fn get_surrounding_elements<'a>(&'a self, point: &Point) -> Vec<&'a Vec> { + let element_index = self.get_index_from_position(point); + dbg!(element_index); + vec![&self.elements[element_index]] + } + + fn get_index_from_position(&self, point: &Point) -> usize { + ((point.x / self.cell_size) + ((point.y / self.cell_size) * self.number_cells_x)) as usize + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn when_no_element_surrounding_nodes_returns_empty_vec() { + let index: SpatialIndex = SpatialIndex::new(Point::new((100, 100)), 10); + assert_eq!( + index.get_surrounding_elements(&Point::new((0, 0))), + vec![&Vec::::new()] + ); + } + + #[test] + fn added_point_is_surrounding_itself() { + let mut index: SpatialIndex = SpatialIndex::new(Point::new((100, 100)), 10); + index.add(&Point::new((50, 50)), 132); + assert_eq!( + index.get_surrounding_elements(&Point::new((50, 50))), + vec![&vec![132]] + ); + } + + #[test] + fn adding_point_outside_grid_panics() { + todo!(); + } + + #[test] + fn point_on_top_edge_is_close_to_first_cell() { + todo!(); + } + + #[test] + fn point_on_bottom_edge_is_close_to_first_cell() { + todo!(); + } + + #[test] + fn point_on_right_edge_is_close_to_first_cell() { + todo!(); + } + #[test] + fn point_on_left_edge_is_close_to_first_cell() { + todo!(); + } + + #[test] + fn when_elements_too_far_surrounding_is_empty() { + let mut index: SpatialIndex = SpatialIndex::new(Point::new((100, 100)), 10); + index.add(&Point::new((0, 0)), 132); + assert_eq!( + index.get_surrounding_elements(&Point::new((99, 99))), + vec![&Vec::::new()] + ); + } +}