1#![warn(rust_2018_idioms)]
3#![deny(clippy::all)]
4#![warn(clippy::pedantic, clippy::nursery)]
5#![allow(clippy::module_name_repetitions)]
6
7#[cfg(test)]
8#[macro_use]
9extern crate approx;
10
11mod managed_octree;
12
13pub use managed_octree::{
14 ManagedHashMapOctree,
15 ManagedOctree,
16 ManagedOctreeData,
17 ManagedVecOctree,
18};
19use std::{
20 borrow::{Borrow, BorrowMut},
21 convert::{AsMut, AsRef},
22};
23
24#[derive(Default)]
28pub struct Octree<D>
29where
30 D: Default,
31{
32 children: [Option<Box<Octree<D>>>; 8],
33 data: D,
34}
35
36#[derive(Debug)]
37pub enum AddChildError {
38 AlreadyAdded,
39 OutOfBoundsIdx,
40}
41
42impl<D> Octree<D>
43where
44 D: Default,
45{
46 #[must_use]
47 pub fn new() -> Self { Self::default() }
48
49 #[must_use]
50 pub fn new_with_data(data: D) -> Self {
51 Self {
52 data,
53 ..Self::default()
54 }
55 }
56
57 pub fn add_child(
63 &mut self,
64 idx: usize,
65 child: Self,
66 ) -> Result<&mut Self, AddChildError> {
67 if idx >= self.children.len() {
68 Err(AddChildError::OutOfBoundsIdx)
69 } else if self.children[idx].is_some() {
70 Err(AddChildError::AlreadyAdded)
71 } else {
72 self.children[idx] = Some(Box::new(child));
73 self.get_child_mut(idx).ok_or(AddChildError::OutOfBoundsIdx)
74 }
75 }
76
77 pub fn add_child_at_pos(
88 &mut self,
89 pos_x: bool,
90 pos_y: bool,
91 pos_z: bool,
92 child: Self,
93 ) -> Result<&mut Self, AddChildError> {
94 self.add_child(Self::get_child_idx_at_pos(pos_x, pos_y, pos_z), child)
95 }
96
97 pub fn remove_child(&mut self, idx: usize) -> Option<Self> {
99 if self.children.get(idx).is_none() {
100 None
101 } else {
102 self.children[idx].take().map(|c| *c)
103 }
104 }
105
106 pub fn remove_child_at_pos(
115 &mut self,
116 pos_x: bool,
117 pos_y: bool,
118 pos_z: bool,
119 ) -> Option<Self> {
120 self.remove_child(Self::get_child_idx_at_pos(pos_x, pos_y, pos_z))
121 }
122
123 #[must_use]
125 pub fn get_child(&self, idx: usize) -> Option<&Self> {
126 if idx >= self.children.len() {
127 None
128 } else {
129 self.children[idx].as_ref().map(AsRef::as_ref)
130 }
131 }
132
133 #[must_use]
135 pub fn get_child_mut(&mut self, idx: usize) -> Option<&mut Self> {
136 if idx >= self.children.len() {
137 None
138 } else {
139 self.children[idx].as_mut().map(AsMut::as_mut)
140 }
141 }
142
143 fn get_child_idx_at_pos(pos_x: bool, pos_y: bool, pos_z: bool) -> usize {
151 match (pos_x, pos_y, pos_z) {
152 (false, false, false) => 0,
153 (false, false, true) => 1,
154 (false, true, false) => 2,
155 (false, true, true) => 3,
156 (true, false, false) => 4,
157 (true, false, true) => 5,
158 (true, true, false) => 6,
159 (true, true, true) => 7,
160 }
161 }
162
163 fn get_child_pos_at_idx(idx: usize) -> (bool, bool, bool) {
165 match idx {
166 0 => (false, false, false),
167 1 => (false, false, true),
168 2 => (false, true, false),
169 3 => (false, true, true),
170 4 => (true, false, false),
171 5 => (true, false, true),
172 6 => (true, true, false),
173 7 => (true, true, true),
174 _ => panic!("idx > 7"),
175 }
176 }
177
178 #[must_use]
186 pub fn get_child_at_pos(
187 &self,
188 pos_x: bool,
189 pos_y: bool,
190 pos_z: bool,
191 ) -> Option<&Self> {
192 self.get_child(Self::get_child_idx_at_pos(pos_x, pos_y, pos_z))
193 }
194
195 #[must_use]
203 pub fn get_child_mut_at_pos(
204 &mut self,
205 pos_x: bool,
206 pos_y: bool,
207 pos_z: bool,
208 ) -> Option<&mut Self> {
209 self.get_child_mut(Self::get_child_idx_at_pos(pos_x, pos_y, pos_z))
210 }
211
212 #[must_use]
214 pub fn get_data(&self) -> &D { self.data.borrow() }
215
216 #[must_use]
218 pub fn get_data_mut(&mut self) -> &mut D { self.data.borrow_mut() }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::Octree;
224
225 #[test]
226 fn test_get_child_out_of_bounds_initial() {
227 let o = Octree::<Vec<(f32, f32, f32)>>::new();
228 assert!(o.get_child(999).is_none());
229 }
230
231 #[test]
232 fn test_get_child_initial() {
233 let o = Octree::<Vec<(f32, f32, f32)>>::new();
234 assert!(o.get_child(0).is_none());
235 }
236
237 #[test]
238 fn test_get_child_pos_initial() {
239 let o = Octree::<Vec<(f32, f32, f32)>>::new();
240 assert!(o.get_child_at_pos(false, false, false).is_none());
241 }
242
243 #[test]
244 fn test_add_child() {
245 let mut o = Octree::<Vec<(f32, f32, f32)>>::new();
246 let result = o.add_child(0, Octree::new());
247 assert!(result.is_ok());
248 }
249
250 #[test]
251 fn test_add_child_at_pos() {
252 let mut o = Octree::<Vec<(f32, f32, f32)>>::new();
253 let result = o.add_child_at_pos(false, false, false, Octree::new());
254 assert!(result.is_ok());
255 }
256
257 #[test]
258 fn test_remove_child() {
259 let mut o = Octree::<Vec<(f32, f32, f32)>>::new();
260 o.add_child(0, Octree::new()).unwrap();
261 let result = o.remove_child(0);
262 assert!(result.is_some());
263 assert!(o.get_child(0).is_none());
264 }
265
266 #[test]
267 fn test_remove_child_at_pos() {
268 let mut o = Octree::<Vec<(f32, f32, f32)>>::new();
269 o.add_child_at_pos(false, false, false, Octree::new())
270 .unwrap();
271 let result = o.remove_child_at_pos(false, false, false);
272 assert!(result.is_some());
273 assert!(o.get_child_at_pos(false, false, false).is_none());
274 }
275}