automesh/tree/
mod.rs

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/// The octree type.
121#[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] - &center).norm()
352                            > (&coordinates[index] - &center).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            // #[cfg(feature = "profile")]
561            // let time = Instant::now();
562            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            // #[cfg(feature = "profile")]
837            // println!(
838            //     "             \x1b[1;93mBalancing iteration {}\x1b[0m {:?} ",
839            //     iteration,
840            //     time.elapsed()
841            // );
842            if balanced {
843                break;
844            }
845        }
846        balanced_already
847    }
848    fn boundaries(&mut self) {
849        //
850        // Consider having this skip blocks that will be removed.
851        // Also, for this and other places, should you always remove the padding?
852        //
853        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                                        //
881                                        // Since subdivision here can create unbalancing,
882                                        // balancing is called at the end,
883                                        // but balancing is still needed beforehand,
884                                        // otherwise a leaf can face grand kids here.
885                                        // Unknown whether unbalancing here can reintroduce that,
886                                        // which would require rebalancing for every subdivision.
887                                        //
888                                        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        //
1097        // Should cells of a reassigned cluster be reassigned one at a time instead?
1098        //
1099        // Do the clusters need to be updated each time another changes?
1100        // In case a cluster inherits the reassigned cluster and becomes large enough?
1101        //
1102        // Still may not understand why `blocks` could be empty below.
1103        //
1104        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        // will eventually delete this method
1285        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        // removed_data.push(PADDING);
1300        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        // #[cfg(feature = "profile")]
1344        // let time = Instant::now();
1345        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        // #[cfg(feature = "profile")]
1377        // println!(
1378        //     "           \x1b[1;93m  Pairing hanging nodes\x1b[0m {:?} ",
1379        //     time.elapsed()
1380        // );
1381        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}