use crate::Vec2;
pub type CellIdx = (i32, i32);
pub(crate) fn cell_range((min_x, min_y): CellIdx, (max_x, max_y): CellIdx) -> XYRange {
if min_x > max_x || min_y > max_y {
return XYRange {
min_x: 0,
max_x: 0,
max_y: 0,
x: 1,
y: 1,
};
}
XYRange {
min_x,
max_x,
max_y,
x: min_x,
y: min_y,
}
}
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SparseStorage<T: Default> {
pub cell_size: i32,
pub cells: fnv::FnvHashMap<CellIdx, T>,
}
impl<T: Default> SparseStorage<T> {
pub fn new(cell_size: i32) -> Self {
assert!(
cell_size > 0,
"Cell size ({}) cannot be less than or equal to zero",
cell_size
);
Self {
cell_size,
cells: Default::default(),
}
}
pub fn cell_size(&self) -> i32 {
self.cell_size
}
pub fn modify(&mut self, mut f: impl FnMut(&mut T) -> bool) {
self.cells.retain(move |_, cell| !f(cell));
}
pub fn cell_mut<V2: Vec2>(&mut self, pos: V2) -> (CellIdx, &mut T) {
let id = self.cell_id(pos);
(id, self.cells.entry(id).or_default())
}
pub fn cell_mut_unchecked(&mut self, id: CellIdx) -> &mut T {
self.cells.entry(id).or_default()
}
pub fn cell(&self, id: CellIdx) -> Option<&T> {
self.cells.get(&id)
}
pub fn cell_id<V2: Vec2>(&self, pos: V2) -> CellIdx {
(
pos.x() as i32 / self.cell_size - if pos.x() < 0.0 { 1 } else { 0 },
pos.y() as i32 / self.cell_size - if pos.y() < 0.0 { 1 } else { 0 },
)
}
}
#[derive(Eq, PartialEq)]
pub struct XYRange {
min_x: i32,
max_x: i32,
max_y: i32,
x: i32,
y: i32,
}
impl Iterator for XYRange {
type Item = (i32, i32);
fn next(&mut self) -> Option<Self::Item> {
if self.y > self.max_y {
return None;
}
let v = (self.x, self.y);
self.x += 1;
if self.x > self.max_x {
self.x = self.min_x;
self.y += 1;
}
Some(v)
}
}