1#[cfg(feature = "profile")]
2use std::time::Instant;
3
4mod hex;
5mod tessellation;
6mod tri;
7
8pub use hex::HexesAndCoords;
9pub use tessellation::octree_from_surface;
10
11use super::{
12 Coordinate, Coordinates, NSD, Vector,
13 fem::{Blocks, FiniteElementMethods, HEX, HexahedralFiniteElements, hex::HexConnectivity},
14 voxel::{Nel, Remove, Scale, Translate, VoxelData, Voxels},
15};
16use conspire::math::{Tensor, TensorArray, TensorVec, tensor_rank_1};
17use ndarray::{Axis, parallel::prelude::*, s};
18use std::{
19 array::from_fn,
20 collections::HashMap,
21 iter::repeat_n,
22 ops::{Deref, DerefMut},
23};
24use tessellation::octree_from_bounding_cube;
25
26pub const PADDING: u8 = 255;
27
28const NUM_EDGES: usize = 8;
29const NUM_FACES: usize = 6;
30const NUM_OCTANTS: usize = 8;
31const NUM_NODES_CELL: usize = 8;
32const NUM_NODES_FACE: usize = 4;
33const NUM_SUBCELLS_FACE: usize = 4;
34const NUM_SUBSUBCELLS_FACE: usize = 16;
35
36type SubcellsOnFace = [usize; NUM_SUBCELLS_FACE];
37const SUBCELLS_ON_OWN_FACE_0: SubcellsOnFace = [0, 1, 4, 5];
38const SUBCELLS_ON_OWN_FACE_1: SubcellsOnFace = [1, 3, 5, 7];
39const SUBCELLS_ON_OWN_FACE_2: SubcellsOnFace = [2, 3, 6, 7];
40const SUBCELLS_ON_OWN_FACE_3: SubcellsOnFace = [0, 2, 4, 6];
41const SUBCELLS_ON_OWN_FACE_4: SubcellsOnFace = [0, 1, 2, 3];
42const SUBCELLS_ON_OWN_FACE_5: SubcellsOnFace = [4, 5, 6, 7];
43
44const fn face_direction(face_index: usize) -> Vector {
45 match face_index {
46 0 => tensor_rank_1([0.0, -1.0, 0.0]),
47 1 => tensor_rank_1([1.0, 0.0, 0.0]),
48 2 => tensor_rank_1([0.0, 1.0, 0.0]),
49 3 => tensor_rank_1([-1.0, 0.0, 0.0]),
50 4 => tensor_rank_1([0.0, 0.0, -1.0]),
51 5 => tensor_rank_1([0.0, 0.0, 1.0]),
52 _ => panic!(),
53 }
54}
55
56const fn mirror_face(face: usize) -> usize {
57 match face {
58 0 => 2,
59 1 => 3,
60 2 => 0,
61 3 => 1,
62 4 => 5,
63 5 => 4,
64 _ => {
65 panic!()
66 }
67 }
68}
69
70const fn subcells_on_own_face(face: usize) -> SubcellsOnFace {
71 match face {
72 0 => SUBCELLS_ON_OWN_FACE_0,
73 1 => SUBCELLS_ON_OWN_FACE_1,
74 2 => SUBCELLS_ON_OWN_FACE_2,
75 3 => SUBCELLS_ON_OWN_FACE_3,
76 4 => SUBCELLS_ON_OWN_FACE_4,
77 5 => SUBCELLS_ON_OWN_FACE_5,
78 _ => {
79 panic!()
80 }
81 }
82}
83
84const fn subcells_on_neighbor_face(face: usize) -> SubcellsOnFace {
85 match face {
86 0 => SUBCELLS_ON_OWN_FACE_2,
87 1 => SUBCELLS_ON_OWN_FACE_3,
88 2 => SUBCELLS_ON_OWN_FACE_0,
89 3 => SUBCELLS_ON_OWN_FACE_1,
90 4 => SUBCELLS_ON_OWN_FACE_5,
91 5 => SUBCELLS_ON_OWN_FACE_4,
92 _ => {
93 panic!()
94 }
95 }
96}
97
98const fn subcells_on_own_face_contains(face: usize, subcell: usize) -> bool {
99 match face {
100 0 => matches!(subcell, 0 | 1 | 4 | 5),
101 1 => matches!(subcell, 1 | 3 | 5 | 7),
102 2 => matches!(subcell, 2 | 3 | 6 | 7),
103 3 => matches!(subcell, 0 | 2 | 4 | 6),
104 4 => matches!(subcell, 0..=3),
105 5 => matches!(subcell, 4..=7),
106 _ => {
107 panic!()
108 }
109 }
110}
111
112type Cells = [Cell; NUM_OCTANTS];
113pub type Edge = [usize; 2];
114pub type Edges = Vec<Edge>;
115type Faces = [Option<usize>; NUM_FACES];
116type Indices = [usize; NUM_OCTANTS];
117type NodeMap = HashMap<[usize; NSD], usize>;
118type SubSubCellsFace = [usize; NUM_SUBSUBCELLS_FACE];
119
120#[derive(Debug)]
122pub struct Octree {
123 nel: Nel,
124 octree: Vec<Cell>,
125 remove: Remove,
126 scale: Scale,
127 translate: Translate,
128}
129
130impl Deref for Octree {
131 type Target = Vec<Cell>;
132 fn deref(&self) -> &Self::Target {
133 &self.octree
134 }
135}
136
137impl DerefMut for Octree {
138 fn deref_mut(&mut self) -> &mut Self::Target {
139 &mut self.octree
140 }
141}
142
143type Cluster = Vec<usize>;
144type Clusters = Vec<Cluster>;
145type Supercells = Vec<Option<[usize; 2]>>;
146
147#[derive(Clone, Copy, Debug)]
148pub struct Cell {
149 pub block: Option<u8>,
150 cells: Option<Indices>,
151 faces: Faces,
152 lngth: u16,
153 min_x: u16,
154 min_y: u16,
155 min_z: u16,
156}
157
158impl Cell {
159 pub fn any_samples_inside(&self, samples: &[Vec<Vec<bool>>]) -> bool {
160 let min_x = self.min_x as usize;
161 let min_y = self.min_y as usize;
162 let min_z = self.min_z as usize;
163 let max_x = (self.min_x + self.lngth) as usize;
164 let max_y = (self.min_y + self.lngth) as usize;
165 let max_z = (self.min_z + self.lngth) as usize;
166 (min_x..max_x).any(|i| (min_y..max_y).any(|j| (min_z..max_z).any(|k| samples[i][j][k])))
167 }
168 pub const fn get_block(&self) -> u8 {
169 if let Some(block) = self.block {
170 block
171 } else {
172 panic!("Called get_block() on a non-leaf cell.")
173 }
174 }
175 pub const fn get_cells(&self) -> &Option<Indices> {
176 &self.cells
177 }
178 pub const fn get_center(&self) -> [f64; 3] {
179 let half_length: f64 = 0.5 * self.lngth as f64;
180 [
181 self.min_x as f64 + half_length,
182 self.min_y as f64 + half_length,
183 self.min_z as f64 + half_length,
184 ]
185 }
186 pub const fn get_faces(&self) -> &Faces {
187 &self.faces
188 }
189 pub const fn get_lngth(&self) -> &u16 {
190 &self.lngth
191 }
192 pub const fn get_min_x(&self) -> &u16 {
193 &self.min_x
194 }
195 pub const fn get_min_y(&self) -> &u16 {
196 &self.min_y
197 }
198 pub const fn get_min_z(&self) -> &u16 {
199 &self.min_z
200 }
201 pub const fn get_max_x(&self) -> u16 {
202 self.min_x + self.lngth
203 }
204 pub const fn get_max_y(&self) -> u16 {
205 self.min_y + self.lngth
206 }
207 pub const fn get_max_z(&self) -> u16 {
208 self.min_z + self.lngth
209 }
210 pub const fn get_nodal_indices_cell(&self) -> [[usize; NSD]; NUM_NODES_CELL] {
211 [
212 [
213 *self.get_min_x() as usize,
214 *self.get_min_y() as usize,
215 *self.get_min_z() as usize,
216 ],
217 [
218 self.get_max_x() as usize,
219 *self.get_min_y() as usize,
220 *self.get_min_z() as usize,
221 ],
222 [
223 self.get_max_x() as usize,
224 self.get_max_y() as usize,
225 *self.get_min_z() as usize,
226 ],
227 [
228 *self.get_min_x() as usize,
229 self.get_max_y() as usize,
230 *self.get_min_z() as usize,
231 ],
232 [
233 *self.get_min_x() as usize,
234 *self.get_min_y() as usize,
235 self.get_max_z() as usize,
236 ],
237 [
238 self.get_max_x() as usize,
239 *self.get_min_y() as usize,
240 self.get_max_z() as usize,
241 ],
242 [
243 self.get_max_x() as usize,
244 self.get_max_y() as usize,
245 self.get_max_z() as usize,
246 ],
247 [
248 *self.get_min_x() as usize,
249 self.get_max_y() as usize,
250 self.get_max_z() as usize,
251 ],
252 ]
253 }
254 pub const fn get_nodal_indices_face(&self, face_index: &usize) -> [[u16; NSD]; NUM_NODES_FACE] {
255 match face_index {
256 0 => [
257 [*self.get_min_x(), *self.get_min_y(), *self.get_min_z()],
258 [self.get_max_x(), *self.get_min_y(), *self.get_min_z()],
259 [self.get_max_x(), *self.get_min_y(), self.get_max_z()],
260 [*self.get_min_x(), *self.get_min_y(), self.get_max_z()],
261 ],
262 1 => [
263 [self.get_max_x(), *self.get_min_y(), *self.get_min_z()],
264 [self.get_max_x(), self.get_max_y(), *self.get_min_z()],
265 [self.get_max_x(), self.get_max_y(), self.get_max_z()],
266 [self.get_max_x(), *self.get_min_y(), self.get_max_z()],
267 ],
268 2 => [
269 [self.get_max_x(), self.get_max_y(), *self.get_min_z()],
270 [*self.get_min_x(), self.get_max_y(), *self.get_min_z()],
271 [*self.get_min_x(), self.get_max_y(), self.get_max_z()],
272 [self.get_max_x(), self.get_max_y(), self.get_max_z()],
273 ],
274 3 => [
275 [*self.get_min_x(), self.get_max_y(), *self.get_min_z()],
276 [*self.get_min_x(), *self.get_min_y(), *self.get_min_z()],
277 [*self.get_min_x(), *self.get_min_y(), self.get_max_z()],
278 [*self.get_min_x(), self.get_max_y(), self.get_max_z()],
279 ],
280 4 => [
281 [*self.get_min_x(), *self.get_min_y(), *self.get_min_z()],
282 [*self.get_min_x(), self.get_max_y(), *self.get_min_z()],
283 [self.get_max_x(), self.get_max_y(), *self.get_min_z()],
284 [self.get_max_x(), *self.get_min_y(), *self.get_min_z()],
285 ],
286 5 => [
287 [*self.get_min_x(), *self.get_min_y(), self.get_max_z()],
288 [self.get_max_x(), *self.get_min_y(), self.get_max_z()],
289 [self.get_max_x(), self.get_max_y(), self.get_max_z()],
290 [*self.get_min_x(), self.get_max_y(), self.get_max_z()],
291 ],
292 _ => {
293 panic!()
294 }
295 }
296 }
297 pub fn homogeneous(&self, data: &VoxelData) -> Option<u8> {
298 let x_min = *self.get_min_x() as usize;
299 let y_min = *self.get_min_y() as usize;
300 let z_min = *self.get_min_z() as usize;
301 let x_max = self.get_max_x() as usize;
302 let y_max = self.get_max_y() as usize;
303 let z_max = self.get_max_z() as usize;
304 let contained = data.slice(s![x_min..x_max, y_min..y_max, z_min..z_max]);
305 let block_0 = contained[(0, 0, 0)];
306 if contained.iter().all(|&block| block == block_0) {
307 Some(block_0)
308 } else {
309 None
310 }
311 }
312 pub fn homogeneous_coordinates(
313 &self,
314 blocks: &Blocks,
315 coordinates: &Coordinates,
316 ) -> Option<u8> {
317 let x_min = *self.get_min_x() as f64;
318 let y_min = *self.get_min_y() as f64;
319 let z_min = *self.get_min_z() as f64;
320 let x_max = self.get_max_x() as f64;
321 let y_max = self.get_max_y() as f64;
322 let z_max = self.get_max_z() as f64;
323 let insides = coordinates
324 .iter()
325 .enumerate()
326 .filter(|(_, coordinate)| {
327 coordinate[0] >= x_min
328 && coordinate[0] < x_max
329 && coordinate[1] >= y_min
330 && coordinate[1] < y_max
331 && coordinate[2] >= z_min
332 && coordinate[2] < z_max
333 })
334 .map(|(index, _)| index)
335 .collect::<Vec<usize>>();
336 if insides.is_empty() {
337 Some(PADDING)
338 } else {
339 let block_0 = blocks[insides[0]];
340 if insides
341 .iter()
342 .map(|&index| blocks[index])
343 .all(|block| block == block_0)
344 {
345 Some(block_0)
346 } else if self.is_voxel() {
347 let center = Coordinate::new(self.get_center());
348 let min_index = insides
349 .into_iter()
350 .reduce(|min_index, index| {
351 if (&coordinates[min_index] - ¢er).norm()
352 > (&coordinates[index] - ¢er).norm()
353 {
354 index
355 } else {
356 min_index
357 }
358 })
359 .unwrap();
360 Some(blocks[min_index])
361 } else {
362 None
363 }
364 }
365 }
366 pub fn is_face_on_octree_boundary(&self, face_index: &usize, nel: Nel) -> bool {
367 match face_index {
368 0 => self.get_min_y() == &0,
369 1 => self.get_max_x() == *nel.x() as u16,
370 2 => self.get_max_y() == *nel.y() as u16,
371 3 => self.get_min_x() == &0,
372 4 => self.get_min_z() == &0,
373 5 => self.get_max_z() == *nel.z() as u16,
374 _ => panic!(),
375 }
376 }
377 pub const fn is_leaf(&self) -> bool {
378 self.get_cells().is_none()
379 }
380 pub const fn is_not_leaf(&self) -> bool {
381 self.get_cells().is_some()
382 }
383 pub const fn is_voxel(&self) -> bool {
384 self.lngth == 1
385 }
386 pub const fn is_not_voxel(&self) -> bool {
387 self.lngth != 1
388 }
389 pub fn subdivide(&mut self, indices: Indices) -> Cells {
390 self.cells = Some(indices);
391 let lngth = self.get_lngth() / 2;
392 let min_x = self.get_min_x();
393 let min_y = self.get_min_y();
394 let min_z = self.get_min_z();
395 let val_x = min_x + lngth;
396 let val_y = min_y + lngth;
397 let val_z = min_z + lngth;
398 [
399 Cell {
400 block: None,
401 cells: None,
402 faces: [
403 None,
404 Some(indices[1]),
405 Some(indices[2]),
406 None,
407 None,
408 Some(indices[4]),
409 ],
410 lngth,
411 min_x: *min_x,
412 min_y: *min_y,
413 min_z: *min_z,
414 },
415 Cell {
416 block: None,
417 cells: None,
418 faces: [
419 None,
420 None,
421 Some(indices[3]),
422 Some(indices[0]),
423 None,
424 Some(indices[5]),
425 ],
426 lngth,
427 min_x: val_x,
428 min_y: *min_y,
429 min_z: *min_z,
430 },
431 Cell {
432 block: None,
433 cells: None,
434 faces: [
435 Some(indices[0]),
436 Some(indices[3]),
437 None,
438 None,
439 None,
440 Some(indices[6]),
441 ],
442 lngth,
443 min_x: *min_x,
444 min_y: val_y,
445 min_z: *min_z,
446 },
447 Cell {
448 block: None,
449 cells: None,
450 faces: [
451 Some(indices[1]),
452 None,
453 None,
454 Some(indices[2]),
455 None,
456 Some(indices[7]),
457 ],
458 lngth,
459 min_x: val_x,
460 min_y: val_y,
461 min_z: *min_z,
462 },
463 Cell {
464 block: None,
465 cells: None,
466 faces: [
467 None,
468 Some(indices[5]),
469 Some(indices[6]),
470 None,
471 Some(indices[0]),
472 None,
473 ],
474 lngth,
475 min_x: *min_x,
476 min_y: *min_y,
477 min_z: val_z,
478 },
479 Cell {
480 block: None,
481 cells: None,
482 faces: [
483 None,
484 None,
485 Some(indices[7]),
486 Some(indices[4]),
487 Some(indices[1]),
488 None,
489 ],
490 lngth,
491 min_x: val_x,
492 min_y: *min_y,
493 min_z: val_z,
494 },
495 Cell {
496 block: None,
497 cells: None,
498 faces: [
499 Some(indices[4]),
500 Some(indices[7]),
501 None,
502 None,
503 Some(indices[2]),
504 None,
505 ],
506 lngth,
507 min_x: *min_x,
508 min_y: val_y,
509 min_z: val_z,
510 },
511 Cell {
512 block: None,
513 cells: None,
514 faces: [
515 Some(indices[5]),
516 None,
517 None,
518 Some(indices[6]),
519 Some(indices[3]),
520 None,
521 ],
522 lngth,
523 min_x: val_x,
524 min_y: val_y,
525 min_z: val_z,
526 },
527 ]
528 }
529}
530
531impl Octree {
532 pub fn balance_and_pair(&mut self, strong: bool) {
533 #[cfg(feature = "profile")]
534 let time = Instant::now();
535 let mut balanced = false;
536 let mut paired = false;
537 while !balanced || !paired {
538 balanced = self.balance(strong);
539 paired = self.pair();
540 }
541 #[cfg(feature = "profile")]
542 println!(
543 " \x1b[1;93mBalancing and pairing\x1b[0m {:?}",
544 time.elapsed()
545 );
546 }
547 pub fn balance(&mut self, strong: bool) -> bool {
548 let mut balanced;
549 let mut balanced_already = true;
550 let mut block;
551 let mut edges = [false; NUM_EDGES];
552 let mut index;
553 let mut subdivide;
554 let mut vertices = [false; 2];
555 #[allow(unused_variables)]
556 for iteration in 1.. {
557 balanced = true;
558 index = 0;
559 subdivide = false;
560 while index < self.len() {
563 if !self[index].is_voxel() && self[index].is_leaf() {
564 'faces: for (face, face_cell) in self[index].get_faces().iter().enumerate() {
565 if let Some(neighbor) = face_cell
566 && let Some(kids) = self[*neighbor].get_cells()
567 {
568 if strong {
569 edges = from_fn(|_| false);
570 vertices = from_fn(|_| false);
571 }
572 if match face {
573 0 => {
574 if strong {
575 if let Some(edge_cell) = self[kids[3]].get_faces()[1] {
576 edges[0] = self[edge_cell].is_not_leaf()
577 }
578 if let Some(edge_cell) = self[kids[7]].get_faces()[1] {
579 edges[1] = self[edge_cell].is_not_leaf()
580 }
581 if let Some(edge_cell) = self[kids[6]].get_faces()[5] {
582 if let Some(vertex_cell) =
583 self[edge_cell].get_faces()[3]
584 {
585 vertices[0] = self[vertex_cell].is_not_leaf()
586 }
587 edges[2] = self[edge_cell].is_not_leaf()
588 }
589 if let Some(edge_cell) = self[kids[7]].get_faces()[5] {
590 edges[3] = self[edge_cell].is_not_leaf()
591 }
592 if let Some(edge_cell) = self[kids[2]].get_faces()[3] {
593 edges[4] = self[edge_cell].is_not_leaf()
594 }
595 if let Some(edge_cell) = self[kids[6]].get_faces()[3] {
596 edges[5] = self[edge_cell].is_not_leaf()
597 }
598 if let Some(edge_cell) = self[kids[2]].get_faces()[4] {
599 if let Some(vertex_cell) =
600 self[edge_cell].get_faces()[3]
601 {
602 vertices[1] = self[vertex_cell].is_not_leaf()
603 }
604 edges[6] = self[edge_cell].is_not_leaf()
605 }
606 if let Some(edge_cell) = self[kids[3]].get_faces()[4] {
607 edges[7] = self[edge_cell].is_not_leaf()
608 }
609 }
610 self[kids[2]].is_not_leaf()
611 || self[kids[3]].is_not_leaf()
612 || self[kids[6]].is_not_leaf()
613 || self[kids[7]].is_not_leaf()
614 || edges.into_iter().any(|edge: bool| edge)
615 || vertices.into_iter().any(|vertex| vertex)
616 }
617 1 => {
618 if strong {
619 if let Some(edge_cell) = self[kids[2]].get_faces()[2] {
620 edges[0] = self[edge_cell].is_not_leaf()
621 }
622 if let Some(edge_cell) = self[kids[6]].get_faces()[2] {
623 edges[1] = self[edge_cell].is_not_leaf()
624 }
625 if let Some(edge_cell) = self[kids[4]].get_faces()[5] {
626 if let Some(vertex_cell) =
627 self[edge_cell].get_faces()[0]
628 {
629 vertices[0] = self[vertex_cell].is_not_leaf()
630 }
631 edges[2] = self[edge_cell].is_not_leaf()
632 }
633 if let Some(edge_cell) = self[kids[6]].get_faces()[5] {
634 edges[3] = self[edge_cell].is_not_leaf()
635 }
636 if let Some(edge_cell) = self[kids[0]].get_faces()[0] {
637 edges[4] = self[edge_cell].is_not_leaf()
638 }
639 if let Some(edge_cell) = self[kids[4]].get_faces()[0] {
640 edges[5] = self[edge_cell].is_not_leaf()
641 }
642 if let Some(edge_cell) = self[kids[0]].get_faces()[4] {
643 if let Some(vertex_cell) =
644 self[edge_cell].get_faces()[0]
645 {
646 vertices[1] = self[vertex_cell].is_not_leaf()
647 }
648 edges[6] = self[edge_cell].is_not_leaf()
649 }
650 if let Some(edge_cell) = self[kids[2]].get_faces()[4] {
651 edges[7] = self[edge_cell].is_not_leaf()
652 }
653 }
654 self[kids[0]].is_not_leaf()
655 || self[kids[2]].is_not_leaf()
656 || self[kids[4]].is_not_leaf()
657 || self[kids[6]].is_not_leaf()
658 || edges.into_iter().any(|edge| edge)
659 || vertices.into_iter().any(|vertex| vertex)
660 }
661 2 => {
662 if strong {
663 if let Some(edge_cell) = self[kids[0]].get_faces()[3] {
664 edges[0] = self[edge_cell].is_not_leaf()
665 }
666 if let Some(edge_cell) = self[kids[4]].get_faces()[3] {
667 edges[1] = self[edge_cell].is_not_leaf()
668 }
669 if let Some(edge_cell) = self[kids[4]].get_faces()[5] {
670 edges[2] = self[edge_cell].is_not_leaf()
671 }
672 if let Some(edge_cell) = self[kids[5]].get_faces()[5] {
673 if let Some(vertex_cell) =
674 self[edge_cell].get_faces()[1]
675 {
676 vertices[0] = self[vertex_cell].is_not_leaf()
677 }
678 edges[3] = self[edge_cell].is_not_leaf()
679 }
680 if let Some(edge_cell) = self[kids[1]].get_faces()[1] {
681 edges[4] = self[edge_cell].is_not_leaf()
682 }
683 if let Some(edge_cell) = self[kids[5]].get_faces()[1] {
684 edges[5] = self[edge_cell].is_not_leaf()
685 }
686 if let Some(edge_cell) = self[kids[0]].get_faces()[4] {
687 edges[6] = self[edge_cell].is_not_leaf()
688 }
689 if let Some(edge_cell) = self[kids[1]].get_faces()[4] {
690 if let Some(vertex_cell) =
691 self[edge_cell].get_faces()[1]
692 {
693 vertices[1] = self[vertex_cell].is_not_leaf()
694 }
695 edges[7] = self[edge_cell].is_not_leaf()
696 }
697 }
698 self[kids[0]].is_not_leaf()
699 || self[kids[1]].is_not_leaf()
700 || self[kids[4]].is_not_leaf()
701 || self[kids[5]].is_not_leaf()
702 || edges.into_iter().any(|edge| edge)
703 || vertices.into_iter().any(|vertex| vertex)
704 }
705 3 => {
706 if strong {
707 if let Some(edge_cell) = self[kids[1]].get_faces()[0] {
708 edges[0] = self[edge_cell].is_not_leaf()
709 }
710 if let Some(edge_cell) = self[kids[5]].get_faces()[0] {
711 edges[1] = self[edge_cell].is_not_leaf()
712 }
713 if let Some(edge_cell) = self[kids[5]].get_faces()[5] {
714 edges[2] = self[edge_cell].is_not_leaf()
715 }
716 if let Some(edge_cell) = self[kids[7]].get_faces()[5] {
717 if let Some(vertex_cell) =
718 self[edge_cell].get_faces()[2]
719 {
720 vertices[0] = self[vertex_cell].is_not_leaf()
721 }
722 edges[3] = self[edge_cell].is_not_leaf()
723 }
724 if let Some(edge_cell) = self[kids[3]].get_faces()[2] {
725 edges[4] = self[edge_cell].is_not_leaf()
726 }
727 if let Some(edge_cell) = self[kids[7]].get_faces()[2] {
728 edges[5] = self[edge_cell].is_not_leaf()
729 }
730 if let Some(edge_cell) = self[kids[1]].get_faces()[4] {
731 edges[6] = self[edge_cell].is_not_leaf()
732 }
733 if let Some(edge_cell) = self[kids[3]].get_faces()[4] {
734 if let Some(vertex_cell) =
735 self[edge_cell].get_faces()[2]
736 {
737 vertices[1] = self[vertex_cell].is_not_leaf()
738 }
739 edges[7] = self[edge_cell].is_not_leaf()
740 }
741 }
742 self[kids[1]].is_not_leaf()
743 || self[kids[3]].is_not_leaf()
744 || self[kids[5]].is_not_leaf()
745 || self[kids[7]].is_not_leaf()
746 || edges.into_iter().any(|edge| edge)
747 || vertices.into_iter().any(|vertex| vertex)
748 }
749 4 => {
750 if strong {
751 if let Some(edge_cell) = self[kids[5]].get_faces()[1] {
752 edges[0] = self[edge_cell].is_not_leaf()
753 }
754 if let Some(edge_cell) = self[kids[7]].get_faces()[1] {
755 edges[1] = self[edge_cell].is_not_leaf()
756 }
757 if let Some(edge_cell) = self[kids[6]].get_faces()[2] {
758 edges[2] = self[edge_cell].is_not_leaf()
759 }
760 if let Some(edge_cell) = self[kids[7]].get_faces()[2] {
761 edges[3] = self[edge_cell].is_not_leaf()
762 }
763 if let Some(edge_cell) = self[kids[4]].get_faces()[3] {
764 edges[4] = self[edge_cell].is_not_leaf()
765 }
766 if let Some(edge_cell) = self[kids[6]].get_faces()[3] {
767 edges[5] = self[edge_cell].is_not_leaf()
768 }
769 if let Some(edge_cell) = self[kids[4]].get_faces()[0] {
770 edges[6] = self[edge_cell].is_not_leaf()
771 }
772 if let Some(edge_cell) = self[kids[5]].get_faces()[0] {
773 edges[7] = self[edge_cell].is_not_leaf()
774 }
775 }
776 edges.into_iter().any(|edge| edge)
777 || self[kids[4]].is_not_leaf()
778 || self[kids[5]].is_not_leaf()
779 || self[kids[6]].is_not_leaf()
780 || self[kids[7]].is_not_leaf()
781 }
782 5 => {
783 if strong {
784 if let Some(edge_cell) = self[kids[1]].get_faces()[1] {
785 edges[0] = self[edge_cell].is_not_leaf()
786 }
787 if let Some(edge_cell) = self[kids[3]].get_faces()[1] {
788 edges[1] = self[edge_cell].is_not_leaf()
789 }
790 if let Some(edge_cell) = self[kids[2]].get_faces()[2] {
791 edges[2] = self[edge_cell].is_not_leaf()
792 }
793 if let Some(edge_cell) = self[kids[3]].get_faces()[2] {
794 edges[3] = self[edge_cell].is_not_leaf()
795 }
796 if let Some(edge_cell) = self[kids[0]].get_faces()[3] {
797 edges[4] = self[edge_cell].is_not_leaf()
798 }
799 if let Some(edge_cell) = self[kids[2]].get_faces()[3] {
800 edges[5] = self[edge_cell].is_not_leaf()
801 }
802 if let Some(edge_cell) = self[kids[0]].get_faces()[0] {
803 edges[6] = self[edge_cell].is_not_leaf()
804 }
805 if let Some(edge_cell) = self[kids[1]].get_faces()[0] {
806 edges[7] = self[edge_cell].is_not_leaf()
807 }
808 }
809 edges.into_iter().any(|edge| edge)
810 || self[kids[0]].is_not_leaf()
811 || self[kids[1]].is_not_leaf()
812 || self[kids[2]].is_not_leaf()
813 || self[kids[3]].is_not_leaf()
814 }
815 _ => panic!(),
816 } {
817 subdivide = true;
818 break 'faces;
819 }
820 }
821 }
822 if subdivide {
823 block = self[index].get_block();
824 self.subdivide(index);
825 self.iter_mut()
826 .rev()
827 .take(NUM_OCTANTS)
828 .for_each(|cell| cell.block = Some(block));
829 balanced = false;
830 balanced_already = false;
831 subdivide = false;
832 }
833 }
834 index += 1;
835 }
836 if balanced {
843 break;
844 }
845 }
846 balanced_already
847 }
848 fn boundaries(&mut self) {
849 let mut block;
854 let mut boundaries;
855 let mut cell;
856 let mut index;
857 #[allow(unused_variables)]
858 for iteration in 1.. {
859 boundaries = true;
860 index = 0;
861 #[cfg(feature = "profile")]
862 let time = Instant::now();
863 while index < self.len() {
864 cell = self[index];
865 if cell.get_lngth() > &1 && cell.is_leaf() {
866 block = cell.get_block();
867 if cell
868 .get_faces()
869 .iter()
870 .flatten()
871 .filter(|&face| self[*face].is_leaf())
872 .any(|face| self[*face].get_block() != block)
873 || cell
874 .get_faces()
875 .iter()
876 .enumerate()
877 .any(|(face, &face_cell_maybe)| {
878 if let Some(face_cell) = face_cell_maybe {
879 if let Some(subcells) = self[face_cell].get_cells() {
880 subcells_on_neighbor_face(face).iter().any(|&subcell| {
889 self[subcells[subcell]].get_block() != block
890 })
891 } else {
892 false
893 }
894 } else {
895 false
896 }
897 })
898 || cell
899 .get_faces()
900 .iter()
901 .enumerate()
902 .filter(|(_, face)| face.is_none())
903 .any(|(face_index, _)| {
904 cell.is_face_on_octree_boundary(&face_index, self.nel())
905 })
906 {
907 self.subdivide(index);
908 self.iter_mut()
909 .rev()
910 .take(NUM_OCTANTS)
911 .for_each(|cell| cell.block = Some(block));
912 boundaries = false;
913 }
914 }
915 index += 1;
916 }
917 #[cfg(feature = "profile")]
918 println!(
919 " \x1b[1;93mBoundaries iteration {}\x1b[0m {:?} ",
920 iteration,
921 time.elapsed()
922 );
923 if boundaries {
924 break;
925 }
926 }
927 self.balance(true);
928 }
929 fn clusters(&self, remove: Option<&Blocks>, supercells_opt: Option<&Supercells>) -> Clusters {
930 #[cfg(feature = "profile")]
931 let time = Instant::now();
932 let removed_data = remove.unwrap();
933 let supercells = if let Some(supercells) = supercells_opt {
934 supercells
935 } else {
936 &self.supercells()
937 };
938 let mut blocks: Blocks = self
939 .iter()
940 .filter(|cell| cell.is_leaf() && removed_data.binary_search(&cell.get_block()).is_err())
941 .map(|cell| cell.get_block())
942 .collect();
943 blocks.sort();
944 blocks.dedup();
945 let mut leaves: Vec<Vec<usize>> = blocks
946 .iter()
947 .map(|&block| {
948 self.iter()
949 .enumerate()
950 .filter_map(|(index, cell)| {
951 if cell.is_leaf() && cell.get_block() == block {
952 Some(index)
953 } else {
954 None
955 }
956 })
957 .collect()
958 })
959 .collect();
960 leaves
961 .iter_mut()
962 .for_each(|block_leaves| block_leaves.sort());
963 let clusters = blocks
964 .into_par_iter()
965 .zip(leaves.par_iter_mut())
966 .flat_map(|(block, block_leaves)| {
967 let mut clusters = vec![];
968 while let Some(starting_leaf) = block_leaves.pop() {
969 let mut cluster = vec![starting_leaf];
970 loop {
971 let mut index = 0;
972 let initial_cluster_len = cluster.len();
973 while index < cluster.len() {
974 self[cluster[index]]
975 .get_faces()
976 .iter()
977 .enumerate()
978 .for_each(|(face, &face_cell)| {
979 if let Some(cell) = face_cell {
980 if let Ok(spot) = block_leaves.binary_search(&cell) {
981 if self[cell].get_block() == block {
982 cluster.push(block_leaves.remove(spot));
983 }
984 } else if let Some(subcells) = self[cell].get_cells() {
985 subcells_on_neighbor_face(face).into_iter().for_each(
986 |subcell| {
987 if let Ok(spot) = block_leaves
988 .binary_search(&subcells[subcell])
989 && self[subcells[subcell]].get_block()
990 == block
991 {
992 cluster.push(block_leaves.remove(spot));
993 }
994 },
995 )
996 }
997 }
998 });
999 index += 1;
1000 }
1001 index = 0;
1002 while index < cluster.len() {
1003 if let Some([parent, subcell]) = supercells[cluster[index]] {
1004 self[parent].get_faces().iter().enumerate().for_each(
1005 |(face, &face_cell)| {
1006 if let Some(cell) = face_cell
1007 && subcells_on_own_face_contains(face, subcell)
1008 && let Ok(spot) = block_leaves.binary_search(&cell)
1009 && self[cell].get_block() == block
1010 {
1011 cluster.push(block_leaves.remove(spot));
1012 }
1013 },
1014 );
1015 }
1016 index += 1;
1017 }
1018 if cluster.len() == initial_cluster_len {
1019 break;
1020 }
1021 }
1022 clusters.push(cluster);
1023 }
1024 clusters
1025 })
1026 .collect();
1027 #[cfg(feature = "profile")]
1028 println!(
1029 " \x1b[1;93mClusters creation\x1b[0m {:?} ",
1030 time.elapsed()
1031 );
1032 clusters
1033 }
1034 fn cell_contains_leaves<'a>(&self, cell: &'a Cell) -> Option<(&'a Indices, &'a Faces)> {
1035 if let Some(cell_subcells) = cell.get_cells() {
1036 if self.just_leaves(cell_subcells) {
1037 Some((cell_subcells, cell.get_faces()))
1038 } else {
1039 None
1040 }
1041 } else {
1042 None
1043 }
1044 }
1045 fn cell_subcells_contain_cells(
1046 &self,
1047 cell: &Cell,
1048 face_index: usize,
1049 ) -> Option<SubSubCellsFace> {
1050 if let Some(cell_subcells) = cell.get_cells() {
1051 let subcell_indices = subcells_on_neighbor_face(face_index);
1052 if subcell_indices
1053 .iter()
1054 .all(|&subcell_index| self[cell_subcells[subcell_index]].is_not_leaf())
1055 {
1056 let subsubcells: SubSubCellsFace = subcell_indices
1057 .iter()
1058 .flat_map(|subcell_a| {
1059 subcell_indices.iter().map(|&subcell_b| {
1060 self[cell_subcells[*subcell_a]].get_cells().unwrap()[subcell_b]
1061 })
1062 })
1063 .collect::<Vec<usize>>()
1064 .try_into()
1065 .unwrap();
1066 Some(subsubcells)
1067 } else {
1068 None
1069 }
1070 } else {
1071 None
1072 }
1073 }
1074 fn cell_subcells_contain_leaves(
1075 &self,
1076 cell: &Cell,
1077 face_index: usize,
1078 ) -> Option<SubSubCellsFace> {
1079 self.cell_subcells_contain_cells(cell, face_index)
1080 .filter(|&subsubcells| {
1081 subsubcells
1082 .iter()
1083 .all(|&subsubcell| self[subsubcell].is_leaf())
1084 })
1085 }
1086 fn cell_subcell_contains_leaves(
1087 &self,
1088 cell: &Cell,
1089 face_index: usize,
1090 subsubcell_index: usize,
1091 ) -> Option<SubSubCellsFace> {
1092 self.cell_subcells_contain_cells(cell, face_index)
1093 .filter(|&subsubcells| self[subsubcells[subsubcell_index]].is_leaf())
1094 }
1095 pub fn defeature(&mut self, min_num_voxels: usize) {
1096 let mut block = 0;
1105 let mut blocks = vec![];
1106 let mut clusters;
1107 let mut counts: Vec<usize> = vec![];
1108 let mut defeatured;
1109 let mut face_block = 0;
1110 let mut neighbor_block = 0;
1111 let mut new_block = 0;
1112 let mut protruded;
1113 let mut unique_blocks = vec![];
1114 let mut volumes: Vec<usize>;
1115 let supercells = self.supercells();
1116 #[allow(unused_variables)]
1117 for iteration in 1.. {
1118 clusters = self.clusters(Some(&vec![PADDING]), Some(&supercells));
1119 #[cfg(feature = "profile")]
1120 let time = Instant::now();
1121 volumes = clusters
1122 .iter()
1123 .map(|cluster| {
1124 cluster
1125 .iter()
1126 .map(|&cell| self[cell].get_lngth().pow(NSD as u32) as usize)
1127 .sum()
1128 })
1129 .collect();
1130 defeatured = volumes.iter().all(|volume| volume >= &min_num_voxels);
1131 if !defeatured {
1132 clusters
1133 .iter()
1134 .zip(volumes)
1135 .filter(|(_, volume)| volume < &min_num_voxels)
1136 .for_each(|(cluster, _)| {
1137 block = self[cluster[0]].get_block();
1138 blocks = cluster
1139 .iter()
1140 .flat_map(|&cell| {
1141 self[cell]
1142 .get_faces()
1143 .iter()
1144 .enumerate()
1145 .filter_map(|(face, &face_cell)| {
1146 if let Some(neighbor) = face_cell {
1147 if let Some(subcells) = self[neighbor].get_cells() {
1148 Some(
1149 subcells_on_neighbor_face(face)
1150 .into_iter()
1151 .filter_map(|subcell| {
1152 face_block =
1153 self[subcells[subcell]].get_block();
1154 if face_block != block {
1155 Some(face_block)
1156 } else {
1157 None
1158 }
1159 })
1160 .collect(),
1161 )
1162 } else {
1163 face_block = self[neighbor].get_block();
1164 if face_block != block {
1165 Some(vec![face_block])
1166 } else {
1167 None
1168 }
1169 }
1170 } else {
1171 None
1172 }
1173 })
1174 .collect::<Vec<Blocks>>()
1175 })
1176 .chain(cluster.iter().filter_map(|&cell| {
1177 if let Some([parent, subcell]) = supercells[cell] {
1178 Some(
1179 self[parent]
1180 .get_faces()
1181 .iter()
1182 .enumerate()
1183 .filter_map(|(face, face_cell)| {
1184 if let Some(neighbor_cell) = face_cell {
1185 if self[*neighbor_cell].is_leaf()
1186 && subcells_on_own_face_contains(
1187 face, subcell,
1188 )
1189 {
1190 neighbor_block =
1191 self[*neighbor_cell].get_block();
1192 if neighbor_block != block {
1193 Some(neighbor_block)
1194 } else {
1195 None
1196 }
1197 } else {
1198 None
1199 }
1200 } else {
1201 None
1202 }
1203 })
1204 .collect(),
1205 )
1206 } else {
1207 None
1208 }
1209 }))
1210 .collect::<Vec<Blocks>>()
1211 .into_iter()
1212 .flatten()
1213 .collect();
1214 unique_blocks = blocks.to_vec();
1215 unique_blocks.sort();
1216 unique_blocks.dedup();
1217 counts = unique_blocks
1218 .iter()
1219 .map(|unique_block| {
1220 blocks.iter().filter(|&block| block == unique_block).count()
1221 })
1222 .collect();
1223 if !blocks.is_empty() {
1224 new_block = unique_blocks[counts
1225 .iter()
1226 .position(|count| {
1227 count == counts.iter().max().expect("maximum not found")
1228 })
1229 .expect("position of maximum not found")];
1230 cluster
1231 .iter()
1232 .for_each(|&cell| self[cell].block = Some(new_block));
1233 }
1234 });
1235 }
1236 #[cfg(feature = "profile")]
1237 println!(
1238 " \x1b[1;93mDefeaturing iteration {}\x1b[0m {:?} ",
1239 iteration,
1240 time.elapsed()
1241 );
1242 protruded = self.protrusions(&supercells);
1243 if defeatured && protruded {
1244 return;
1245 }
1246 }
1247 }
1248 pub fn from_finite_elements<const M: usize, const N: usize, T>(
1249 finite_elements: T,
1250 grid: usize,
1251 size: f64,
1252 ) -> Self
1253 where
1254 T: FiniteElementMethods<M, N>,
1255 {
1256 let mut blocks: Blocks = finite_elements
1257 .get_element_blocks()
1258 .iter()
1259 .flat_map(|&block| repeat_n(block, grid.pow(3)))
1260 .collect();
1261 let mut samples = finite_elements.interior_points(grid);
1262 let mut exterior_face_samples = finite_elements.exterior_faces_interior_points(grid);
1263 blocks.extend(vec![PADDING; exterior_face_samples.len()]);
1264 samples.append(&mut exterior_face_samples);
1265 let mut tree = octree_from_bounding_cube(&mut samples, size);
1266 let mut index = 0;
1267 while index < tree.len() {
1268 if let Some(block) = tree[index].homogeneous_coordinates(&blocks, &samples) {
1269 tree[index].block = Some(block);
1270 } else {
1271 tree.subdivide(index)
1272 }
1273 index += 1;
1274 }
1275 tree
1276 }
1277 fn just_leaves(&self, cells: &[usize]) -> bool {
1278 cells.iter().all(|&subcell| self[subcell].is_leaf())
1279 }
1280 pub const fn nel(&self) -> Nel {
1281 self.nel
1282 }
1283 pub fn octree_into_finite_elements(
1284 self,
1286 remove: Option<Blocks>,
1287 scale: Scale,
1288 translate: Translate,
1289 ) -> Result<HexahedralFiniteElements, String> {
1290 let mut x_min = 0.0;
1291 let mut y_min = 0.0;
1292 let mut z_min = 0.0;
1293 let mut x_val = 0.0;
1294 let mut y_val = 0.0;
1295 let mut z_val = 0.0;
1296 let mut removed_data = remove.unwrap_or_default();
1297 removed_data.sort();
1298 removed_data.dedup();
1299 let num_elements = self
1301 .iter()
1302 .filter(|cell| removed_data.binary_search(&cell.get_block()).is_err())
1303 .count();
1304 let mut element_blocks = vec![0; num_elements];
1305 let mut element_node_connectivity = vec![from_fn(|_| 0); num_elements];
1306 let mut nodal_coordinates: Coordinates = (0..num_elements * HEX)
1307 .map(|_| Coordinate::zero())
1308 .collect();
1309 let mut index = 0;
1310 self.iter()
1311 .filter(|cell| removed_data.binary_search(&cell.get_block()).is_err())
1312 .zip(
1313 element_blocks
1314 .iter_mut()
1315 .zip(element_node_connectivity.iter_mut()),
1316 )
1317 .for_each(|(cell, (block, connectivity))| {
1318 *block = cell.get_block();
1319 *connectivity = from_fn(|n| n + index);
1320 x_min = *cell.get_min_x() as f64 * scale.x() + translate.x();
1321 y_min = *cell.get_min_y() as f64 * scale.y() + translate.y();
1322 z_min = *cell.get_min_z() as f64 * scale.z() + translate.z();
1323 x_val = (cell.get_min_x() + cell.get_lngth()) as f64 * scale.x() + translate.x();
1324 y_val = (cell.get_min_y() + cell.get_lngth()) as f64 * scale.y() + translate.y();
1325 z_val = (cell.get_min_z() + cell.get_lngth()) as f64 * scale.z() + translate.z();
1326 nodal_coordinates[index] = Coordinate::new([x_min, y_min, z_min]);
1327 nodal_coordinates[index + 1] = Coordinate::new([x_val, y_min, z_min]);
1328 nodal_coordinates[index + 2] = Coordinate::new([x_val, y_val, z_min]);
1329 nodal_coordinates[index + 3] = Coordinate::new([x_min, y_val, z_min]);
1330 nodal_coordinates[index + 4] = Coordinate::new([x_min, y_min, z_val]);
1331 nodal_coordinates[index + 5] = Coordinate::new([x_val, y_min, z_val]);
1332 nodal_coordinates[index + 6] = Coordinate::new([x_val, y_val, z_val]);
1333 nodal_coordinates[index + 7] = Coordinate::new([x_min, y_val, z_val]);
1334 index += HEX;
1335 });
1336 Ok(HexahedralFiniteElements::from((
1337 element_blocks,
1338 element_node_connectivity,
1339 nodal_coordinates,
1340 )))
1341 }
1342 pub fn pair(&mut self) -> bool {
1343 let mut block = 0;
1346 let mut index = 0;
1347 let mut paired_already = true;
1348 let mut subsubcells: Vec<bool>;
1349 while index < self.len() {
1350 if let Some(subcells) = self[index].cells {
1351 subsubcells = subcells
1352 .into_iter()
1353 .map(|subcell| self[subcell].is_not_leaf())
1354 .collect();
1355 if subsubcells.iter().any(|&subsubcell| subsubcell)
1356 && !subsubcells.iter().all(|&subsubcell| subsubcell)
1357 {
1358 subcells
1359 .into_iter()
1360 .filter(|&subcell| self[subcell].cells.is_none())
1361 .collect::<Vec<usize>>()
1362 .into_iter()
1363 .for_each(|subcell| {
1364 block = self[subcell].get_block();
1365 paired_already = false;
1366 self.subdivide(subcell);
1367 self.iter_mut()
1368 .rev()
1369 .take(NUM_OCTANTS)
1370 .for_each(|cell| cell.block = Some(block))
1371 })
1372 }
1373 }
1374 index += 1;
1375 }
1376 paired_already
1382 }
1383 pub fn parameters(self) -> (Remove, Scale, Translate) {
1384 (self.remove, self.scale, self.translate)
1385 }
1386 fn protrusions(&mut self, supercells: &Supercells) -> bool {
1387 let mut blocks = vec![];
1388 let mut complete = true;
1389 let mut counts: Vec<usize> = vec![];
1390 let mut new_block = 0;
1391 let mut protrusions: Vec<(usize, Blocks)>;
1392 let mut unique_blocks = vec![];
1393 #[allow(unused_variables)]
1394 for iteration in 1.. {
1395 #[cfg(feature = "profile")]
1396 let time = Instant::now();
1397 protrusions = self
1398 .iter()
1399 .enumerate()
1400 .filter(|(_, cell)| cell.is_voxel())
1401 .flat_map(|(voxel_cell_index, voxel_cell)| {
1402 blocks = voxel_cell
1403 .get_faces()
1404 .iter()
1405 .enumerate()
1406 .flat_map(|(face_index, &face)| {
1407 if let Some(face_cell_index) = face {
1408 Some(self[face_cell_index].get_block())
1409 } else if let Some([parent, _]) = supercells[voxel_cell_index] {
1410 self[parent].get_faces()[face_index]
1411 .map(|neighbor| self[neighbor].get_block())
1412 } else {
1413 None
1414 }
1415 })
1416 .collect();
1417 if blocks
1418 .iter()
1419 .filter(|&&face_block| voxel_cell.get_block() != face_block)
1420 .count()
1421 >= 5
1422 {
1423 Some((voxel_cell_index, blocks.clone()))
1424 } else {
1425 None
1426 }
1427 })
1428 .collect();
1429 if !protrusions.is_empty() {
1430 complete = false;
1431 protrusions.iter().for_each(|(voxel_cell_index, blocks)| {
1432 unique_blocks = blocks.to_vec();
1433 unique_blocks.sort();
1434 unique_blocks.dedup();
1435 counts = unique_blocks
1436 .iter()
1437 .map(|unique_block| {
1438 blocks.iter().filter(|&block| block == unique_block).count()
1439 })
1440 .collect();
1441 new_block = unique_blocks[counts
1442 .iter()
1443 .position(|count| count == counts.iter().max().expect("maximum not found"))
1444 .expect("position of maximum not found")];
1445 self[*voxel_cell_index].block = Some(new_block)
1446 })
1447 }
1448 #[cfg(feature = "profile")]
1449 println!(
1450 " \x1b[1;93mProtrusions iteration {}\x1b[0m {:?} ",
1451 iteration,
1452 time.elapsed()
1453 );
1454 if protrusions.is_empty() {
1455 break;
1456 }
1457 }
1458 complete
1459 }
1460 pub fn prune(&mut self) {
1461 #[cfg(feature = "profile")]
1462 let time = Instant::now();
1463 self.retain(|cell| cell.is_leaf());
1464 #[cfg(feature = "profile")]
1465 println!(
1466 " \x1b[1;93mPruning octree\x1b[0m {:?} ",
1467 time.elapsed()
1468 );
1469 }
1470 pub fn remove(&self) -> &Remove {
1471 &self.remove
1472 }
1473 pub fn scale(&self) -> &Scale {
1474 &self.scale
1475 }
1476 fn subdivide(&mut self, index: usize) {
1477 assert!(self[index].is_leaf());
1478 let new_indices = from_fn(|n| self.len() + n);
1479 let mut new_cells = self[index].subdivide(new_indices);
1480 self[index]
1481 .get_faces()
1482 .clone()
1483 .iter()
1484 .enumerate()
1485 .for_each(|(face, &face_cell)| {
1486 if let Some(neighbor) = face_cell
1487 && let Some(kids) = self[neighbor].cells
1488 {
1489 subcells_on_own_face(face)
1490 .iter()
1491 .zip(subcells_on_neighbor_face(face).iter())
1492 .for_each(|(&subcell, &neighbor_subcell)| {
1493 new_cells[subcell].faces[face] = Some(kids[neighbor_subcell]);
1494 self[kids[neighbor_subcell]].faces[mirror_face(face)] =
1495 Some(new_indices[subcell]);
1496 });
1497 }
1498 });
1499 self.extend(new_cells);
1500 }
1501 fn supercells(&self) -> Supercells {
1502 let (max_leaf_id, _) = self
1503 .iter()
1504 .enumerate()
1505 .filter(|(_, cell)| cell.is_leaf())
1506 .next_back()
1507 .unwrap();
1508 let mut supercells = vec![None; max_leaf_id + 1];
1509 self.iter()
1510 .enumerate()
1511 .filter_map(|(parent_index, cell)| {
1512 cell.get_cells()
1513 .as_ref()
1514 .map(|subcells| (parent_index, subcells))
1515 })
1516 .for_each(|(parent_index, subcells)| {
1517 if subcells
1518 .iter()
1519 .filter(|&&subcell| self[subcell].get_cells().is_some())
1520 .count()
1521 == 0
1522 {
1523 subcells
1524 .iter()
1525 .enumerate()
1526 .for_each(|(subcell_index, &subcell)| {
1527 supercells[subcell] = Some([parent_index, subcell_index])
1528 })
1529 }
1530 });
1531 supercells
1532 }
1533 pub fn translate(&self) -> &Translate {
1534 &self.translate
1535 }
1536}
1537
1538impl From<Voxels> for Octree {
1539 fn from(voxels: Voxels) -> Octree {
1540 #[cfg(feature = "profile")]
1541 let time = Instant::now();
1542 let (data_voxels, remove, scale, translate) = voxels.data();
1543 let mut nel_i = 0;
1544 let nel_padded = data_voxels
1545 .shape()
1546 .iter()
1547 .map(|nel_0| {
1548 nel_i = *nel_0;
1549 while (nel_i & (nel_i - 1)) != 0 {
1550 nel_i += 1
1551 }
1552 nel_i
1553 })
1554 .max()
1555 .unwrap();
1556 let nel = Nel::from([nel_padded; NSD]);
1557 let mut data = VoxelData::from(nel);
1558 data.iter_mut().for_each(|entry| *entry = PADDING);
1559 if data_voxels.iter().any(|entry| entry == &PADDING) {
1560 panic!("Segmentation cannot use 255 as an ID with octree padding.")
1561 }
1562 data.axis_iter_mut(Axis(2))
1563 .zip(data_voxels.axis_iter(Axis(2)))
1564 .for_each(|(mut data_i, data_voxels_i)| {
1565 data_i
1566 .axis_iter_mut(Axis(1))
1567 .zip(data_voxels_i.axis_iter(Axis(1)))
1568 .for_each(|(mut data_ij, data_voxels_ij)| {
1569 data_ij
1570 .iter_mut()
1571 .zip(data_voxels_ij.iter())
1572 .for_each(|(data_ijk, data_voxels_ijk)| *data_ijk = *data_voxels_ijk)
1573 })
1574 });
1575 let nel_min = nel.iter().min().unwrap();
1576 let lngth = *nel_min as u16;
1577 let mut tree = Octree {
1578 nel,
1579 octree: vec![],
1580 remove,
1581 scale,
1582 translate,
1583 };
1584 (0..(nel.x() / nel_min)).for_each(|i| {
1585 (0..(nel.y() / nel_min)).for_each(|j| {
1586 (0..(nel.z() / nel_min)).for_each(|k| {
1587 tree.push(Cell {
1588 block: None,
1589 cells: None,
1590 faces: [None; NUM_FACES],
1591 lngth,
1592 min_x: lngth * i as u16,
1593 min_y: lngth * j as u16,
1594 min_z: lngth * k as u16,
1595 })
1596 })
1597 })
1598 });
1599 let mut index = 0;
1600 while index < tree.len() {
1601 if let Some(block) = tree[index].homogeneous(&data) {
1602 tree[index].block = Some(block)
1603 } else {
1604 tree.subdivide(index)
1605 }
1606 index += 1;
1607 }
1608 #[cfg(feature = "profile")]
1609 println!(
1610 " \x1b[1;93mOctree initialization\x1b[0m {:?} ",
1611 time.elapsed()
1612 );
1613 tree
1614 }
1615}