diff --git a/Cargo.lock b/Cargo.lock index 3531a1e..f8495ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ version = "0.30.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" dependencies = [ + "libm", "serde", ] @@ -17,6 +18,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "libm" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72" + [[package]] name = "memchr" version = "2.7.5" diff --git a/Cargo.toml b/Cargo.toml index 65905f4..5b12d9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,14 @@ repository = "https://github.com/benbaarber/quadtree" keywords = ["quadtree", "barnes-hut"] [features] +default = ["std"] + serde = ["dep:serde", "glam/serde"] +std = ["glam/std"] +libm = ["glam/libm"] [dependencies] -glam = "0.30.4" +glam = { version = "0.30.4", default-features = false, features = ["nostd-libm"] } serde = { version = "1.0.219", optional = true, features = ["derive"] } [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index 25dc830..dd2d321 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![no_std] + mod quadtree; pub mod shapes; mod util; diff --git a/src/quadtree/barnes_hut.rs b/src/quadtree/barnes_hut.rs index ed6eee2..d0ebae8 100644 --- a/src/quadtree/barnes_hut.rs +++ b/src/quadtree/barnes_hut.rs @@ -4,7 +4,10 @@ use crate::{ util::{Partition, bound_items}, }; use glam::Vec2; -use std::ops::Range; + +extern crate alloc; +use alloc::vec::Vec; +use core::ops::Range; /// A point with mass #[derive(Debug, Default, Clone, Copy, PartialEq)] diff --git a/src/quadtree/mod.rs b/src/quadtree/mod.rs index 2d00b1f..5b93a9f 100644 --- a/src/quadtree/mod.rs +++ b/src/quadtree/mod.rs @@ -1,6 +1,10 @@ pub mod barnes_hut; use glam::Vec2; + +extern crate alloc; +use alloc::{boxed::Box, vec, vec::Vec}; + #[cfg(feature = "serde")] use serde::{Serialize, Serializer, ser::SerializeSeq}; @@ -112,6 +116,11 @@ impl Quadtree { results } + /// Shrink to fit inserted items + pub fn shrink(&mut self) { + self.root = self.root.shrink(); + } + /// Delete items that are within a specified shape area /// /// **Returns** the number of items that were deleted @@ -229,7 +238,7 @@ impl Node { return true; } - let mut data = std::mem::take(data); + let mut data = core::mem::take(data); data.push(item.clone()); let children = self.subdivide(); *self = Self::Internal { bound, children }; @@ -487,6 +496,29 @@ impl Node { } } + fn shrink(&mut self) -> Self { + let default: Self = Node::Empty { + bound: Rect::new(Vec2::default(), Vec2::default()), + }; + + match self { + Self::Empty { .. } => core::mem::replace(self, default), + Self::External { .. } => core::mem::replace(self, default), + Self::Internal { children, .. } => { + let mut nonempty: Vec<&mut Box> = children + .into_iter() + .filter(|e| !matches!(***e, Node::Empty { .. })) + .collect(); + + if nonempty.len() == 1 { + nonempty[0].shrink() + } else { + core::mem::replace(self, default) + } + } + } + } + fn center(&self) -> Vec2 { self.bound().center() } diff --git a/src/util.rs b/src/util.rs index c478a14..b96587f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,8 @@ use glam::vec2; +extern crate alloc; +use alloc::vec::Vec; + use crate::{ Point, shapes::{Rect, Shape}, @@ -56,7 +59,7 @@ impl Partition for [T] { } pub(crate) fn group_by_quadrant(rect: Rect, items: Vec) -> [Vec; 5] { - let mut groups: [Vec; 5] = std::array::from_fn(|_| Vec::with_capacity(items.len())); + let mut groups: [Vec; 5] = core::array::from_fn(|_| Vec::with_capacity(items.len())); for item in items { match rect.quadrant(item.point()) { Some(q) => groups[q].push(item), @@ -68,7 +71,7 @@ pub(crate) fn group_by_quadrant(rect: Rect, items: Vec) -> [Vec; #[allow(unused)] pub(crate) fn group_by_quadrant_slice<'a, T: Point>(rect: Rect, items: &'a [T]) -> [Vec<&'a T>; 5] { - let mut groups: [Vec<&T>; 5] = std::array::from_fn(|_| Vec::with_capacity(items.len())); + let mut groups: [Vec<&T>; 5] = core::array::from_fn(|_| Vec::with_capacity(items.len())); for item in items { match rect.quadrant(item.point()) { Some(q) => groups[q].push(item),