1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct OctAabb {
10 pub min: [f32; 3],
11 pub max: [f32; 3],
12}
13
14impl OctAabb {
15 pub fn new(min: [f32; 3], max: [f32; 3]) -> Self {
16 OctAabb { min, max }
17 }
18
19 pub fn center(&self) -> [f32; 3] {
20 [
21 (self.min[0] + self.max[0]) * 0.5,
22 (self.min[1] + self.max[1]) * 0.5,
23 (self.min[2] + self.max[2]) * 0.5,
24 ]
25 }
26
27 pub fn contains_point(&self, p: &[f32; 3]) -> bool {
28 (0..3).all(|i| p[i] >= self.min[i] && p[i] <= self.max[i])
29 }
30
31 pub fn intersects(&self, other: &OctAabb) -> bool {
32 (0..3).all(|i| self.min[i] <= other.max[i] && self.max[i] >= other.min[i])
33 }
34
35 fn octant(&self, p: &[f32; 3]) -> usize {
36 let c = self.center();
37 let x = if p[0] >= c[0] { 1 } else { 0 };
38 let y = if p[1] >= c[1] { 2 } else { 0 };
39 let z = if p[2] >= c[2] { 4 } else { 0 };
40 x | y | z
41 }
42
43 fn child_aabb(&self, octant: usize) -> OctAabb {
44 let c = self.center();
45 let min_x = if octant & 1 != 0 { c[0] } else { self.min[0] };
46 let max_x = if octant & 1 != 0 { self.max[0] } else { c[0] };
47 let min_y = if octant & 2 != 0 { c[1] } else { self.min[1] };
48 let max_y = if octant & 2 != 0 { self.max[1] } else { c[1] };
49 let min_z = if octant & 4 != 0 { c[2] } else { self.min[2] };
50 let max_z = if octant & 4 != 0 { self.max[2] } else { c[2] };
51 OctAabb {
52 min: [min_x, min_y, min_z],
53 max: [max_x, max_y, max_z],
54 }
55 }
56}
57
58const MAX_POINTS_PER_LEAF: usize = 8;
59const MAX_DEPTH: usize = 8;
60
61pub enum SimpleOctreeNode {
63 Leaf {
64 points: Vec<(usize, [f32; 3])>,
65 bounds: OctAabb,
66 },
67 Internal {
68 bounds: OctAabb,
69 children: Box<[Option<SimpleOctreeNode>; 8]>,
70 },
71}
72
73impl SimpleOctreeNode {
74 fn new_leaf(bounds: OctAabb) -> Self {
75 SimpleOctreeNode::Leaf {
76 points: Vec::new(),
77 bounds,
78 }
79 }
80
81 fn bounds(&self) -> &OctAabb {
82 match self {
83 SimpleOctreeNode::Leaf { bounds, .. } => bounds,
84 SimpleOctreeNode::Internal { bounds, .. } => bounds,
85 }
86 }
87
88 fn insert(&mut self, id: usize, p: [f32; 3], depth: usize) {
89 match self {
90 SimpleOctreeNode::Leaf { points, bounds } => {
91 points.push((id, p));
92 if points.len() > MAX_POINTS_PER_LEAF && depth < MAX_DEPTH {
93 let old_pts = std::mem::take(points);
94 let old_bounds = *bounds;
95 let mut children: [Option<SimpleOctreeNode>; 8] = Default::default();
96 #[allow(clippy::needless_range_loop)]
97 for oct in 0..8 {
98 children[oct] =
99 Some(SimpleOctreeNode::new_leaf(old_bounds.child_aabb(oct)));
100 }
101 let mut new_self = SimpleOctreeNode::Internal {
102 bounds: old_bounds,
103 children: Box::new(children),
104 };
105 for (oid, op) in old_pts {
106 new_self.insert(oid, op, depth + 1);
107 }
108 *self = new_self;
109 }
110 }
111 SimpleOctreeNode::Internal { bounds, children } => {
112 let oct = bounds.octant(&p);
113 if let Some(child) = &mut children[oct] {
114 child.insert(id, p, depth + 1);
115 }
116 }
117 }
118 }
119
120 fn query_aabb(&self, query: &OctAabb, result: &mut Vec<usize>) {
121 if !self.bounds().intersects(query) {
122 return;
123 }
124 match self {
125 SimpleOctreeNode::Leaf { points, .. } => {
126 for (id, p) in points {
127 if query.contains_point(p) {
128 result.push(*id);
129 }
130 }
131 }
132 SimpleOctreeNode::Internal { children, .. } => {
133 for child in children.iter().flatten() {
134 child.query_aabb(query, result);
135 }
136 }
137 }
138 }
139
140 fn count(&self) -> usize {
141 match self {
142 SimpleOctreeNode::Leaf { points, .. } => points.len(),
143 SimpleOctreeNode::Internal { children, .. } => {
144 children.iter().flatten().map(|c| c.count()).sum()
145 }
146 }
147 }
148}
149
150pub struct SimpleOctree {
152 root: Option<SimpleOctreeNode>,
153 bounds: OctAabb,
154 count: usize,
155}
156
157impl SimpleOctree {
158 pub fn new(bounds: OctAabb) -> Self {
160 SimpleOctree {
161 root: Some(SimpleOctreeNode::new_leaf(bounds)),
162 bounds,
163 count: 0,
164 }
165 }
166
167 pub fn insert(&mut self, id: usize, p: [f32; 3]) {
169 if !self.bounds.contains_point(&p) {
170 return;
171 }
172 if let Some(root) = &mut self.root {
173 root.insert(id, p, 0);
174 self.count += 1;
175 }
176 }
177
178 pub fn query_aabb(&self, query: &OctAabb) -> Vec<usize> {
180 let mut result = Vec::new();
181 if let Some(root) = &self.root {
182 root.query_aabb(query, &mut result);
183 }
184 result
185 }
186
187 pub fn query_sphere(&self, center: &[f32; 3], r: f32) -> Vec<usize> {
189 let aabb = OctAabb {
190 min: [center[0] - r, center[1] - r, center[2] - r],
191 max: [center[0] + r, center[1] + r, center[2] + r],
192 };
193 self.query_aabb(&aabb)
194 }
195
196 pub fn len(&self) -> usize {
198 self.count
199 }
200
201 pub fn is_empty(&self) -> bool {
203 self.count == 0
204 }
205}
206
207pub struct SimpleOctree3 {
209 bounds: OctAabb,
210 root: Option<SimpleOctreeNode>,
211 points: Vec<[f32; 3]>,
212}
213
214impl SimpleOctree3 {
215 pub fn new(bounds: OctAabb) -> Self {
216 SimpleOctree3 {
217 root: Some(SimpleOctreeNode::new_leaf(bounds)),
218 bounds,
219 points: Vec::new(),
220 }
221 }
222
223 pub fn insert(&mut self, p: [f32; 3]) -> usize {
224 let id = self.points.len();
225 self.points.push(p);
226 if self.bounds.contains_point(&p) {
227 if let Some(root) = &mut self.root {
228 root.insert(id, p, 0);
229 }
230 }
231 id
232 }
233
234 pub fn query_aabb(&self, query: &OctAabb) -> Vec<usize> {
235 let mut result = Vec::new();
236 if let Some(root) = &self.root {
237 root.query_aabb(query, &mut result);
238 }
239 result
240 }
241
242 pub fn query_sphere(&self, center: &[f32; 3], r: f32) -> Vec<usize> {
243 let aabb = OctAabb {
244 min: [center[0] - r, center[1] - r, center[2] - r],
245 max: [center[0] + r, center[1] + r, center[2] + r],
246 };
247 let r_sq = r * r;
248 let candidates = self.query_aabb(&aabb);
249 candidates
250 .into_iter()
251 .filter(|&id| {
252 let p = &self.points[id];
253 (0..3).map(|i| (p[i] - center[i]).powi(2)).sum::<f32>() <= r_sq
254 })
255 .collect()
256 }
257
258 pub fn len(&self) -> usize {
259 self.points.len()
260 }
261
262 pub fn is_empty(&self) -> bool {
263 self.points.is_empty()
264 }
265
266 pub fn clear(&mut self) {
267 self.root = Some(SimpleOctreeNode::new_leaf(self.bounds));
268 self.points.clear();
269 }
270
271 pub fn bounds(&self) -> &OctAabb {
272 &self.bounds
273 }
274}
275
276pub fn new_simple_octree(half_size: f32) -> SimpleOctree3 {
278 let h = half_size.abs().max(1.0);
279 SimpleOctree3::new(OctAabb {
280 min: [-h, -h, -h],
281 max: [h, h, h],
282 })
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288
289 #[test]
290 fn test_insert_and_query_aabb() {
291 let mut tree = new_simple_octree(100.0);
292 let id = tree.insert([1.0, 2.0, 3.0]);
293 let found = tree.query_aabb(&OctAabb::new([0.0, 0.0, 0.0], [5.0, 5.0, 5.0]));
294 assert!(found.contains(&id));
295 }
296
297 #[test]
298 fn test_query_sphere() {
299 let mut tree = new_simple_octree(100.0);
300 let id = tree.insert([0.0, 0.0, 0.0]);
301 tree.insert([50.0, 50.0, 50.0]);
302 let found = tree.query_sphere(&[0.0, 0.0, 0.0], 1.0);
303 assert!(found.contains(&id));
304 assert_eq!(found.len(), 1);
305 }
306
307 #[test]
308 fn test_empty() {
309 let tree = new_simple_octree(10.0);
310 assert!(tree.is_empty());
311 assert_eq!(tree.len(), 0);
312 }
313
314 #[test]
315 fn test_len() {
316 let mut tree = new_simple_octree(100.0);
317 tree.insert([1.0, 0.0, 0.0]);
318 tree.insert([2.0, 0.0, 0.0]);
319 assert_eq!(tree.len(), 2);
320 }
321
322 #[test]
323 fn test_clear() {
324 let mut tree = new_simple_octree(100.0);
325 tree.insert([1.0, 1.0, 1.0]);
326 tree.clear();
327 assert!(tree.is_empty());
328 }
329
330 #[test]
331 fn test_out_of_bounds_ignored() {
332 let mut tree = new_simple_octree(10.0);
333 tree.insert([1000.0, 0.0, 0.0]);
334 let found = tree.query_aabb(&OctAabb::new([-10.0, -10.0, -10.0], [10.0, 10.0, 10.0]));
336 assert!(found.is_empty());
337 }
338
339 #[test]
340 fn test_many_points() {
341 let mut tree = new_simple_octree(100.0);
342 for i in 0..50 {
343 tree.insert([i as f32, 0.0, 0.0]);
344 }
345 assert_eq!(tree.len(), 50);
346 let found = tree.query_sphere(&[25.0, 0.0, 0.0], 3.0);
347 assert!(found.len() >= 5);
348 }
349
350 #[test]
351 fn test_aabb_intersects() {
352 let a = OctAabb::new([0.0, 0.0, 0.0], [1.0, 1.0, 1.0]);
353 let b = OctAabb::new([0.5, 0.5, 0.5], [2.0, 2.0, 2.0]);
354 let c = OctAabb::new([5.0, 5.0, 5.0], [6.0, 6.0, 6.0]);
355 assert!(a.intersects(&b));
356 assert!(!a.intersects(&c));
357 }
358}