Skip to main content

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::{Samples, 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};
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 => Vector::const_from([0.0, -1.0, 0.0]),
47        1 => Vector::const_from([1.0, 0.0, 0.0]),
48        2 => Vector::const_from([0.0, 1.0, 0.0]),
49        3 => Vector::const_from([-1.0, 0.0, 0.0]),
50        4 => Vector::const_from([0.0, 0.0, -1.0]),
51        5 => Vector::const_from([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<u8>>]) -> 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)
167            .any(|i| (min_y..max_y).any(|j| (min_z..max_z).any(|k| samples[i][j][k] == 1)))
168    }
169    pub const fn get_block(&self) -> u8 {
170        if let Some(block) = self.block {
171            block
172        } else {
173            panic!("Called get_block() on a non-leaf cell.")
174        }
175    }
176    pub const fn get_cells(&self) -> &Option<Indices> {
177        &self.cells
178    }
179    pub const fn get_center(&self) -> [f64; 3] {
180        let half_length: f64 = 0.5 * self.lngth as f64;
181        [
182            self.min_x as f64 + half_length,
183            self.min_y as f64 + half_length,
184            self.min_z as f64 + half_length,
185        ]
186    }
187    pub const fn get_faces(&self) -> &Faces {
188        &self.faces
189    }
190    pub const fn get_lngth(&self) -> &u16 {
191        &self.lngth
192    }
193    pub const fn get_min_x(&self) -> &u16 {
194        &self.min_x
195    }
196    pub const fn get_min_y(&self) -> &u16 {
197        &self.min_y
198    }
199    pub const fn get_min_z(&self) -> &u16 {
200        &self.min_z
201    }
202    pub const fn get_max_x(&self) -> u16 {
203        self.min_x + self.lngth
204    }
205    pub const fn get_max_y(&self) -> u16 {
206        self.min_y + self.lngth
207    }
208    pub const fn get_max_z(&self) -> u16 {
209        self.min_z + self.lngth
210    }
211    pub const fn get_nodal_indices_cell(&self) -> [[usize; NSD]; NUM_NODES_CELL] {
212        [
213            [
214                *self.get_min_x() as usize,
215                *self.get_min_y() as usize,
216                *self.get_min_z() as usize,
217            ],
218            [
219                self.get_max_x() as usize,
220                *self.get_min_y() as usize,
221                *self.get_min_z() as usize,
222            ],
223            [
224                self.get_max_x() as usize,
225                self.get_max_y() as usize,
226                *self.get_min_z() as usize,
227            ],
228            [
229                *self.get_min_x() as usize,
230                self.get_max_y() as usize,
231                *self.get_min_z() as usize,
232            ],
233            [
234                *self.get_min_x() as usize,
235                *self.get_min_y() as usize,
236                self.get_max_z() as usize,
237            ],
238            [
239                self.get_max_x() as usize,
240                *self.get_min_y() as usize,
241                self.get_max_z() as usize,
242            ],
243            [
244                self.get_max_x() as usize,
245                self.get_max_y() as usize,
246                self.get_max_z() as usize,
247            ],
248            [
249                *self.get_min_x() as usize,
250                self.get_max_y() as usize,
251                self.get_max_z() as usize,
252            ],
253        ]
254    }
255    pub const fn get_nodal_indices_face(&self, face_index: &usize) -> [[u16; NSD]; NUM_NODES_FACE] {
256        match face_index {
257            0 => [
258                [*self.get_min_x(), *self.get_min_y(), *self.get_min_z()],
259                [self.get_max_x(), *self.get_min_y(), *self.get_min_z()],
260                [self.get_max_x(), *self.get_min_y(), self.get_max_z()],
261                [*self.get_min_x(), *self.get_min_y(), self.get_max_z()],
262            ],
263            1 => [
264                [self.get_max_x(), *self.get_min_y(), *self.get_min_z()],
265                [self.get_max_x(), self.get_max_y(), *self.get_min_z()],
266                [self.get_max_x(), self.get_max_y(), self.get_max_z()],
267                [self.get_max_x(), *self.get_min_y(), self.get_max_z()],
268            ],
269            2 => [
270                [self.get_max_x(), self.get_max_y(), *self.get_min_z()],
271                [*self.get_min_x(), self.get_max_y(), *self.get_min_z()],
272                [*self.get_min_x(), self.get_max_y(), self.get_max_z()],
273                [self.get_max_x(), self.get_max_y(), self.get_max_z()],
274            ],
275            3 => [
276                [*self.get_min_x(), self.get_max_y(), *self.get_min_z()],
277                [*self.get_min_x(), *self.get_min_y(), *self.get_min_z()],
278                [*self.get_min_x(), *self.get_min_y(), self.get_max_z()],
279                [*self.get_min_x(), self.get_max_y(), self.get_max_z()],
280            ],
281            4 => [
282                [*self.get_min_x(), *self.get_min_y(), *self.get_min_z()],
283                [*self.get_min_x(), self.get_max_y(), *self.get_min_z()],
284                [self.get_max_x(), self.get_max_y(), *self.get_min_z()],
285                [self.get_max_x(), *self.get_min_y(), *self.get_min_z()],
286            ],
287            5 => [
288                [*self.get_min_x(), *self.get_min_y(), self.get_max_z()],
289                [self.get_max_x(), *self.get_min_y(), self.get_max_z()],
290                [self.get_max_x(), self.get_max_y(), self.get_max_z()],
291                [*self.get_min_x(), self.get_max_y(), self.get_max_z()],
292            ],
293            _ => {
294                panic!()
295            }
296        }
297    }
298    pub fn homogeneous(&self, data: &VoxelData) -> Option<u8> {
299        let x_min = *self.get_min_x() as usize;
300        let y_min = *self.get_min_y() as usize;
301        let z_min = *self.get_min_z() as usize;
302        let x_max = self.get_max_x() as usize;
303        let y_max = self.get_max_y() as usize;
304        let z_max = self.get_max_z() as usize;
305        let contained = data.slice(s![x_min..x_max, y_min..y_max, z_min..z_max]);
306        let block_0 = contained[(0, 0, 0)];
307        if contained.iter().all(|&block| block == block_0) {
308            Some(block_0)
309        } else {
310            None
311        }
312    }
313    pub fn homogeneous_coordinates(
314        &self,
315        blocks: &Blocks,
316        coordinates: &Coordinates,
317    ) -> Option<u8> {
318        let x_min = *self.get_min_x() as f64;
319        let y_min = *self.get_min_y() as f64;
320        let z_min = *self.get_min_z() as f64;
321        let x_max = self.get_max_x() as f64;
322        let y_max = self.get_max_y() as f64;
323        let z_max = self.get_max_z() as f64;
324        let insides = coordinates
325            .iter()
326            .enumerate()
327            .filter(|(_, coordinate)| {
328                coordinate[0] >= x_min
329                    && coordinate[0] < x_max
330                    && coordinate[1] >= y_min
331                    && coordinate[1] < y_max
332                    && coordinate[2] >= z_min
333                    && coordinate[2] < z_max
334            })
335            .map(|(index, _)| index)
336            .collect::<Vec<usize>>();
337        if insides.is_empty() {
338            Some(PADDING)
339        } else {
340            let block_0 = blocks[insides[0]];
341            if insides
342                .iter()
343                .map(|&index| blocks[index])
344                .all(|block| block == block_0)
345            {
346                Some(block_0)
347            } else if self.is_voxel() {
348                let center = self.get_center().into();
349                let min_index = insides
350                    .into_iter()
351                    .reduce(|min_index, index| {
352                        if (&coordinates[min_index] - &center).norm()
353                            > (&coordinates[index] - &center).norm()
354                        {
355                            index
356                        } else {
357                            min_index
358                        }
359                    })
360                    .unwrap();
361                Some(blocks[min_index])
362            } else {
363                None
364            }
365        }
366    }
367    pub fn is_face_on_octree_boundary(&self, face_index: &usize, nel: Nel) -> bool {
368        match face_index {
369            0 => self.get_min_y() == &0,
370            1 => self.get_max_x() == *nel.x() as u16,
371            2 => self.get_max_y() == *nel.y() as u16,
372            3 => self.get_min_x() == &0,
373            4 => self.get_min_z() == &0,
374            5 => self.get_max_z() == *nel.z() as u16,
375            _ => panic!(),
376        }
377    }
378    pub const fn is_leaf(&self) -> bool {
379        self.get_cells().is_none()
380    }
381    pub const fn is_not_leaf(&self) -> bool {
382        self.get_cells().is_some()
383    }
384    pub const fn is_voxel(&self) -> bool {
385        self.lngth == 1
386    }
387    pub const fn is_not_voxel(&self) -> bool {
388        self.lngth != 1
389    }
390    pub fn subdivide(&mut self, indices: Indices) -> Cells {
391        self.cells = Some(indices);
392        let lngth = self.get_lngth() / 2;
393        let min_x = self.get_min_x();
394        let min_y = self.get_min_y();
395        let min_z = self.get_min_z();
396        let val_x = min_x + lngth;
397        let val_y = min_y + lngth;
398        let val_z = min_z + lngth;
399        [
400            Cell {
401                block: None,
402                cells: None,
403                faces: [
404                    None,
405                    Some(indices[1]),
406                    Some(indices[2]),
407                    None,
408                    None,
409                    Some(indices[4]),
410                ],
411                lngth,
412                min_x: *min_x,
413                min_y: *min_y,
414                min_z: *min_z,
415            },
416            Cell {
417                block: None,
418                cells: None,
419                faces: [
420                    None,
421                    None,
422                    Some(indices[3]),
423                    Some(indices[0]),
424                    None,
425                    Some(indices[5]),
426                ],
427                lngth,
428                min_x: val_x,
429                min_y: *min_y,
430                min_z: *min_z,
431            },
432            Cell {
433                block: None,
434                cells: None,
435                faces: [
436                    Some(indices[0]),
437                    Some(indices[3]),
438                    None,
439                    None,
440                    None,
441                    Some(indices[6]),
442                ],
443                lngth,
444                min_x: *min_x,
445                min_y: val_y,
446                min_z: *min_z,
447            },
448            Cell {
449                block: None,
450                cells: None,
451                faces: [
452                    Some(indices[1]),
453                    None,
454                    None,
455                    Some(indices[2]),
456                    None,
457                    Some(indices[7]),
458                ],
459                lngth,
460                min_x: val_x,
461                min_y: val_y,
462                min_z: *min_z,
463            },
464            Cell {
465                block: None,
466                cells: None,
467                faces: [
468                    None,
469                    Some(indices[5]),
470                    Some(indices[6]),
471                    None,
472                    Some(indices[0]),
473                    None,
474                ],
475                lngth,
476                min_x: *min_x,
477                min_y: *min_y,
478                min_z: val_z,
479            },
480            Cell {
481                block: None,
482                cells: None,
483                faces: [
484                    None,
485                    None,
486                    Some(indices[7]),
487                    Some(indices[4]),
488                    Some(indices[1]),
489                    None,
490                ],
491                lngth,
492                min_x: val_x,
493                min_y: *min_y,
494                min_z: val_z,
495            },
496            Cell {
497                block: None,
498                cells: None,
499                faces: [
500                    Some(indices[4]),
501                    Some(indices[7]),
502                    None,
503                    None,
504                    Some(indices[2]),
505                    None,
506                ],
507                lngth,
508                min_x: *min_x,
509                min_y: val_y,
510                min_z: val_z,
511            },
512            Cell {
513                block: None,
514                cells: None,
515                faces: [
516                    Some(indices[5]),
517                    None,
518                    None,
519                    Some(indices[6]),
520                    Some(indices[3]),
521                    None,
522                ],
523                lngth,
524                min_x: val_x,
525                min_y: val_y,
526                min_z: val_z,
527            },
528        ]
529    }
530}
531
532impl Octree {
533    pub fn balance_and_pair(&mut self, strong: bool) {
534        #[cfg(feature = "profile")]
535        let time = Instant::now();
536        let mut balanced = false;
537        let mut paired = false;
538        while !balanced || !paired {
539            balanced = self.balance(strong);
540            paired = self.pair();
541        }
542        #[cfg(feature = "profile")]
543        println!(
544            "             \x1b[1;93mBalancing and pairing\x1b[0m {:?}",
545            time.elapsed()
546        );
547    }
548    pub fn balance(&mut self, strong: bool) -> bool {
549        let mut balanced;
550        let mut balanced_already = true;
551        let mut block;
552        let mut edges = [false; NUM_EDGES];
553        let mut index;
554        let mut subdivide;
555        let mut vertices = [false; 2];
556        #[allow(unused_variables)]
557        for iteration in 1.. {
558            balanced = true;
559            index = 0;
560            subdivide = false;
561            // #[cfg(feature = "profile")]
562            // let time = Instant::now();
563            while index < self.len() {
564                if !self[index].is_voxel() && self[index].is_leaf() {
565                    'faces: for (face, face_cell) in self[index].get_faces().iter().enumerate() {
566                        if let Some(neighbor) = face_cell
567                            && let Some(kids) = self[*neighbor].get_cells()
568                        {
569                            if strong {
570                                edges = from_fn(|_| false);
571                                vertices = from_fn(|_| false);
572                            }
573                            if match face {
574                                0 => {
575                                    if strong {
576                                        if let Some(edge_cell) = self[kids[3]].get_faces()[1] {
577                                            edges[0] = self[edge_cell].is_not_leaf()
578                                        }
579                                        if let Some(edge_cell) = self[kids[7]].get_faces()[1] {
580                                            edges[1] = self[edge_cell].is_not_leaf()
581                                        }
582                                        if let Some(edge_cell) = self[kids[6]].get_faces()[5] {
583                                            if let Some(vertex_cell) =
584                                                self[edge_cell].get_faces()[3]
585                                            {
586                                                vertices[0] = self[vertex_cell].is_not_leaf()
587                                            }
588                                            edges[2] = self[edge_cell].is_not_leaf()
589                                        }
590                                        if let Some(edge_cell) = self[kids[7]].get_faces()[5] {
591                                            edges[3] = self[edge_cell].is_not_leaf()
592                                        }
593                                        if let Some(edge_cell) = self[kids[2]].get_faces()[3] {
594                                            edges[4] = self[edge_cell].is_not_leaf()
595                                        }
596                                        if let Some(edge_cell) = self[kids[6]].get_faces()[3] {
597                                            edges[5] = self[edge_cell].is_not_leaf()
598                                        }
599                                        if let Some(edge_cell) = self[kids[2]].get_faces()[4] {
600                                            if let Some(vertex_cell) =
601                                                self[edge_cell].get_faces()[3]
602                                            {
603                                                vertices[1] = self[vertex_cell].is_not_leaf()
604                                            }
605                                            edges[6] = self[edge_cell].is_not_leaf()
606                                        }
607                                        if let Some(edge_cell) = self[kids[3]].get_faces()[4] {
608                                            edges[7] = self[edge_cell].is_not_leaf()
609                                        }
610                                    }
611                                    self[kids[2]].is_not_leaf()
612                                        || self[kids[3]].is_not_leaf()
613                                        || self[kids[6]].is_not_leaf()
614                                        || self[kids[7]].is_not_leaf()
615                                        || edges.into_iter().any(|edge: bool| edge)
616                                        || vertices.into_iter().any(|vertex| vertex)
617                                }
618                                1 => {
619                                    if strong {
620                                        if let Some(edge_cell) = self[kids[2]].get_faces()[2] {
621                                            edges[0] = self[edge_cell].is_not_leaf()
622                                        }
623                                        if let Some(edge_cell) = self[kids[6]].get_faces()[2] {
624                                            edges[1] = self[edge_cell].is_not_leaf()
625                                        }
626                                        if let Some(edge_cell) = self[kids[4]].get_faces()[5] {
627                                            if let Some(vertex_cell) =
628                                                self[edge_cell].get_faces()[0]
629                                            {
630                                                vertices[0] = self[vertex_cell].is_not_leaf()
631                                            }
632                                            edges[2] = self[edge_cell].is_not_leaf()
633                                        }
634                                        if let Some(edge_cell) = self[kids[6]].get_faces()[5] {
635                                            edges[3] = self[edge_cell].is_not_leaf()
636                                        }
637                                        if let Some(edge_cell) = self[kids[0]].get_faces()[0] {
638                                            edges[4] = self[edge_cell].is_not_leaf()
639                                        }
640                                        if let Some(edge_cell) = self[kids[4]].get_faces()[0] {
641                                            edges[5] = self[edge_cell].is_not_leaf()
642                                        }
643                                        if let Some(edge_cell) = self[kids[0]].get_faces()[4] {
644                                            if let Some(vertex_cell) =
645                                                self[edge_cell].get_faces()[0]
646                                            {
647                                                vertices[1] = self[vertex_cell].is_not_leaf()
648                                            }
649                                            edges[6] = self[edge_cell].is_not_leaf()
650                                        }
651                                        if let Some(edge_cell) = self[kids[2]].get_faces()[4] {
652                                            edges[7] = self[edge_cell].is_not_leaf()
653                                        }
654                                    }
655                                    self[kids[0]].is_not_leaf()
656                                        || self[kids[2]].is_not_leaf()
657                                        || self[kids[4]].is_not_leaf()
658                                        || self[kids[6]].is_not_leaf()
659                                        || edges.into_iter().any(|edge| edge)
660                                        || vertices.into_iter().any(|vertex| vertex)
661                                }
662                                2 => {
663                                    if strong {
664                                        if let Some(edge_cell) = self[kids[0]].get_faces()[3] {
665                                            edges[0] = self[edge_cell].is_not_leaf()
666                                        }
667                                        if let Some(edge_cell) = self[kids[4]].get_faces()[3] {
668                                            edges[1] = self[edge_cell].is_not_leaf()
669                                        }
670                                        if let Some(edge_cell) = self[kids[4]].get_faces()[5] {
671                                            edges[2] = self[edge_cell].is_not_leaf()
672                                        }
673                                        if let Some(edge_cell) = self[kids[5]].get_faces()[5] {
674                                            if let Some(vertex_cell) =
675                                                self[edge_cell].get_faces()[1]
676                                            {
677                                                vertices[0] = self[vertex_cell].is_not_leaf()
678                                            }
679                                            edges[3] = self[edge_cell].is_not_leaf()
680                                        }
681                                        if let Some(edge_cell) = self[kids[1]].get_faces()[1] {
682                                            edges[4] = self[edge_cell].is_not_leaf()
683                                        }
684                                        if let Some(edge_cell) = self[kids[5]].get_faces()[1] {
685                                            edges[5] = self[edge_cell].is_not_leaf()
686                                        }
687                                        if let Some(edge_cell) = self[kids[0]].get_faces()[4] {
688                                            edges[6] = self[edge_cell].is_not_leaf()
689                                        }
690                                        if let Some(edge_cell) = self[kids[1]].get_faces()[4] {
691                                            if let Some(vertex_cell) =
692                                                self[edge_cell].get_faces()[1]
693                                            {
694                                                vertices[1] = self[vertex_cell].is_not_leaf()
695                                            }
696                                            edges[7] = self[edge_cell].is_not_leaf()
697                                        }
698                                    }
699                                    self[kids[0]].is_not_leaf()
700                                        || self[kids[1]].is_not_leaf()
701                                        || self[kids[4]].is_not_leaf()
702                                        || self[kids[5]].is_not_leaf()
703                                        || edges.into_iter().any(|edge| edge)
704                                        || vertices.into_iter().any(|vertex| vertex)
705                                }
706                                3 => {
707                                    if strong {
708                                        if let Some(edge_cell) = self[kids[1]].get_faces()[0] {
709                                            edges[0] = self[edge_cell].is_not_leaf()
710                                        }
711                                        if let Some(edge_cell) = self[kids[5]].get_faces()[0] {
712                                            edges[1] = self[edge_cell].is_not_leaf()
713                                        }
714                                        if let Some(edge_cell) = self[kids[5]].get_faces()[5] {
715                                            edges[2] = self[edge_cell].is_not_leaf()
716                                        }
717                                        if let Some(edge_cell) = self[kids[7]].get_faces()[5] {
718                                            if let Some(vertex_cell) =
719                                                self[edge_cell].get_faces()[2]
720                                            {
721                                                vertices[0] = self[vertex_cell].is_not_leaf()
722                                            }
723                                            edges[3] = self[edge_cell].is_not_leaf()
724                                        }
725                                        if let Some(edge_cell) = self[kids[3]].get_faces()[2] {
726                                            edges[4] = self[edge_cell].is_not_leaf()
727                                        }
728                                        if let Some(edge_cell) = self[kids[7]].get_faces()[2] {
729                                            edges[5] = self[edge_cell].is_not_leaf()
730                                        }
731                                        if let Some(edge_cell) = self[kids[1]].get_faces()[4] {
732                                            edges[6] = self[edge_cell].is_not_leaf()
733                                        }
734                                        if let Some(edge_cell) = self[kids[3]].get_faces()[4] {
735                                            if let Some(vertex_cell) =
736                                                self[edge_cell].get_faces()[2]
737                                            {
738                                                vertices[1] = self[vertex_cell].is_not_leaf()
739                                            }
740                                            edges[7] = self[edge_cell].is_not_leaf()
741                                        }
742                                    }
743                                    self[kids[1]].is_not_leaf()
744                                        || self[kids[3]].is_not_leaf()
745                                        || self[kids[5]].is_not_leaf()
746                                        || self[kids[7]].is_not_leaf()
747                                        || edges.into_iter().any(|edge| edge)
748                                        || vertices.into_iter().any(|vertex| vertex)
749                                }
750                                4 => {
751                                    if strong {
752                                        if let Some(edge_cell) = self[kids[5]].get_faces()[1] {
753                                            edges[0] = self[edge_cell].is_not_leaf()
754                                        }
755                                        if let Some(edge_cell) = self[kids[7]].get_faces()[1] {
756                                            edges[1] = self[edge_cell].is_not_leaf()
757                                        }
758                                        if let Some(edge_cell) = self[kids[6]].get_faces()[2] {
759                                            edges[2] = self[edge_cell].is_not_leaf()
760                                        }
761                                        if let Some(edge_cell) = self[kids[7]].get_faces()[2] {
762                                            edges[3] = self[edge_cell].is_not_leaf()
763                                        }
764                                        if let Some(edge_cell) = self[kids[4]].get_faces()[3] {
765                                            edges[4] = self[edge_cell].is_not_leaf()
766                                        }
767                                        if let Some(edge_cell) = self[kids[6]].get_faces()[3] {
768                                            edges[5] = self[edge_cell].is_not_leaf()
769                                        }
770                                        if let Some(edge_cell) = self[kids[4]].get_faces()[0] {
771                                            edges[6] = self[edge_cell].is_not_leaf()
772                                        }
773                                        if let Some(edge_cell) = self[kids[5]].get_faces()[0] {
774                                            edges[7] = self[edge_cell].is_not_leaf()
775                                        }
776                                    }
777                                    edges.into_iter().any(|edge| edge)
778                                        || self[kids[4]].is_not_leaf()
779                                        || self[kids[5]].is_not_leaf()
780                                        || self[kids[6]].is_not_leaf()
781                                        || self[kids[7]].is_not_leaf()
782                                }
783                                5 => {
784                                    if strong {
785                                        if let Some(edge_cell) = self[kids[1]].get_faces()[1] {
786                                            edges[0] = self[edge_cell].is_not_leaf()
787                                        }
788                                        if let Some(edge_cell) = self[kids[3]].get_faces()[1] {
789                                            edges[1] = self[edge_cell].is_not_leaf()
790                                        }
791                                        if let Some(edge_cell) = self[kids[2]].get_faces()[2] {
792                                            edges[2] = self[edge_cell].is_not_leaf()
793                                        }
794                                        if let Some(edge_cell) = self[kids[3]].get_faces()[2] {
795                                            edges[3] = self[edge_cell].is_not_leaf()
796                                        }
797                                        if let Some(edge_cell) = self[kids[0]].get_faces()[3] {
798                                            edges[4] = self[edge_cell].is_not_leaf()
799                                        }
800                                        if let Some(edge_cell) = self[kids[2]].get_faces()[3] {
801                                            edges[5] = self[edge_cell].is_not_leaf()
802                                        }
803                                        if let Some(edge_cell) = self[kids[0]].get_faces()[0] {
804                                            edges[6] = self[edge_cell].is_not_leaf()
805                                        }
806                                        if let Some(edge_cell) = self[kids[1]].get_faces()[0] {
807                                            edges[7] = self[edge_cell].is_not_leaf()
808                                        }
809                                    }
810                                    edges.into_iter().any(|edge| edge)
811                                        || self[kids[0]].is_not_leaf()
812                                        || self[kids[1]].is_not_leaf()
813                                        || self[kids[2]].is_not_leaf()
814                                        || self[kids[3]].is_not_leaf()
815                                }
816                                _ => panic!(),
817                            } {
818                                subdivide = true;
819                                break 'faces;
820                            }
821                        }
822                    }
823                    if subdivide {
824                        block = self[index].get_block();
825                        self.subdivide(index);
826                        self.iter_mut()
827                            .rev()
828                            .take(NUM_OCTANTS)
829                            .for_each(|cell| cell.block = Some(block));
830                        balanced = false;
831                        balanced_already = false;
832                        subdivide = false;
833                    }
834                }
835                index += 1;
836            }
837            // #[cfg(feature = "profile")]
838            // println!(
839            //     "             \x1b[1;93mBalancing iteration {}\x1b[0m {:?} ",
840            //     iteration,
841            //     time.elapsed()
842            // );
843            if balanced {
844                break;
845            }
846        }
847        balanced_already
848    }
849    fn boundaries(&mut self) {
850        //
851        // Consider having this skip blocks that will be removed.
852        // Also, for this and other places, should you always remove the padding?
853        //
854        let mut block;
855        let mut boundaries;
856        let mut cell;
857        let mut index;
858        #[allow(unused_variables)]
859        for iteration in 1.. {
860            boundaries = true;
861            index = 0;
862            #[cfg(feature = "profile")]
863            let time = Instant::now();
864            while index < self.len() {
865                cell = self[index];
866                if cell.get_lngth() > &1 && cell.is_leaf() {
867                    block = cell.get_block();
868                    if cell
869                        .get_faces()
870                        .iter()
871                        .flatten()
872                        .filter(|&face| self[*face].is_leaf())
873                        .any(|face| self[*face].get_block() != block)
874                        || cell
875                            .get_faces()
876                            .iter()
877                            .enumerate()
878                            .any(|(face, &face_cell_maybe)| {
879                                if let Some(face_cell) = face_cell_maybe {
880                                    if let Some(subcells) = self[face_cell].get_cells() {
881                                        //
882                                        // Since subdivision here can create unbalancing,
883                                        // balancing is called at the end,
884                                        // but balancing is still needed beforehand,
885                                        // otherwise a leaf can face grand kids here.
886                                        // Unknown whether unbalancing here can reintroduce that,
887                                        // which would require rebalancing for every subdivision.
888                                        //
889                                        subcells_on_neighbor_face(face).iter().any(|&subcell| {
890                                            self[subcells[subcell]].get_block() != block
891                                        })
892                                    } else {
893                                        false
894                                    }
895                                } else {
896                                    false
897                                }
898                            })
899                        || cell
900                            .get_faces()
901                            .iter()
902                            .enumerate()
903                            .filter(|(_, face)| face.is_none())
904                            .any(|(face_index, _)| {
905                                cell.is_face_on_octree_boundary(&face_index, self.nel())
906                            })
907                    {
908                        self.subdivide(index);
909                        self.iter_mut()
910                            .rev()
911                            .take(NUM_OCTANTS)
912                            .for_each(|cell| cell.block = Some(block));
913                        boundaries = false;
914                    }
915                }
916                index += 1;
917            }
918            #[cfg(feature = "profile")]
919            println!(
920                "             \x1b[1;93mBoundaries iteration {}\x1b[0m {:?} ",
921                iteration,
922                time.elapsed()
923            );
924            if boundaries {
925                break;
926            }
927        }
928        self.balance(true);
929    }
930    fn clusters(&self, remove: Option<&Blocks>, supercells_opt: Option<&Supercells>) -> Clusters {
931        #[cfg(feature = "profile")]
932        let time = Instant::now();
933        let removed_data = remove.unwrap();
934        let supercells = if let Some(supercells) = supercells_opt {
935            supercells
936        } else {
937            &self.supercells()
938        };
939        let mut blocks: Blocks = self
940            .iter()
941            .filter(|cell| cell.is_leaf() && removed_data.binary_search(&cell.get_block()).is_err())
942            .map(|cell| cell.get_block())
943            .collect();
944        blocks.sort();
945        blocks.dedup();
946        let mut leaves: Vec<Vec<usize>> = blocks
947            .iter()
948            .map(|&block| {
949                self.iter()
950                    .enumerate()
951                    .filter_map(|(index, cell)| {
952                        if cell.is_leaf() && cell.get_block() == block {
953                            Some(index)
954                        } else {
955                            None
956                        }
957                    })
958                    .collect()
959            })
960            .collect();
961        leaves
962            .iter_mut()
963            .for_each(|block_leaves| block_leaves.sort());
964        let clusters = blocks
965            .into_par_iter()
966            .zip(leaves.par_iter_mut())
967            .flat_map(|(block, block_leaves)| {
968                let mut clusters = vec![];
969                while let Some(starting_leaf) = block_leaves.pop() {
970                    let mut cluster = vec![starting_leaf];
971                    loop {
972                        let mut index = 0;
973                        let initial_cluster_len = cluster.len();
974                        while index < cluster.len() {
975                            self[cluster[index]]
976                                .get_faces()
977                                .iter()
978                                .enumerate()
979                                .for_each(|(face, &face_cell)| {
980                                    if let Some(cell) = face_cell {
981                                        if let Ok(spot) = block_leaves.binary_search(&cell) {
982                                            if self[cell].get_block() == block {
983                                                cluster.push(block_leaves.remove(spot));
984                                            }
985                                        } else if let Some(subcells) = self[cell].get_cells() {
986                                            subcells_on_neighbor_face(face).into_iter().for_each(
987                                                |subcell| {
988                                                    if let Ok(spot) = block_leaves
989                                                        .binary_search(&subcells[subcell])
990                                                        && self[subcells[subcell]].get_block()
991                                                            == block
992                                                    {
993                                                        cluster.push(block_leaves.remove(spot));
994                                                    }
995                                                },
996                                            )
997                                        }
998                                    }
999                                });
1000                            index += 1;
1001                        }
1002                        index = 0;
1003                        while index < cluster.len() {
1004                            if let Some([parent, subcell]) = supercells[cluster[index]] {
1005                                self[parent].get_faces().iter().enumerate().for_each(
1006                                    |(face, &face_cell)| {
1007                                        if let Some(cell) = face_cell
1008                                            && subcells_on_own_face_contains(face, subcell)
1009                                            && let Ok(spot) = block_leaves.binary_search(&cell)
1010                                            && self[cell].get_block() == block
1011                                        {
1012                                            cluster.push(block_leaves.remove(spot));
1013                                        }
1014                                    },
1015                                );
1016                            }
1017                            index += 1;
1018                        }
1019                        if cluster.len() == initial_cluster_len {
1020                            break;
1021                        }
1022                    }
1023                    clusters.push(cluster);
1024                }
1025                clusters
1026            })
1027            .collect();
1028        #[cfg(feature = "profile")]
1029        println!(
1030            "             \x1b[1;93mClusters creation\x1b[0m {:?} ",
1031            time.elapsed()
1032        );
1033        clusters
1034    }
1035    fn cell_contains_leaves<'a>(&self, cell: &'a Cell) -> Option<(&'a Indices, &'a Faces)> {
1036        if let Some(cell_subcells) = cell.get_cells() {
1037            if self.just_leaves(cell_subcells) {
1038                Some((cell_subcells, cell.get_faces()))
1039            } else {
1040                None
1041            }
1042        } else {
1043            None
1044        }
1045    }
1046    fn cell_subcells_contain_cells(
1047        &self,
1048        cell: &Cell,
1049        face_index: usize,
1050    ) -> Option<SubSubCellsFace> {
1051        if let Some(cell_subcells) = cell.get_cells() {
1052            let subcell_indices = subcells_on_neighbor_face(face_index);
1053            if subcell_indices
1054                .iter()
1055                .all(|&subcell_index| self[cell_subcells[subcell_index]].is_not_leaf())
1056            {
1057                let subsubcells: SubSubCellsFace = subcell_indices
1058                    .iter()
1059                    .flat_map(|subcell_a| {
1060                        subcell_indices.iter().map(|&subcell_b| {
1061                            self[cell_subcells[*subcell_a]].get_cells().unwrap()[subcell_b]
1062                        })
1063                    })
1064                    .collect::<Vec<usize>>()
1065                    .try_into()
1066                    .unwrap();
1067                Some(subsubcells)
1068            } else {
1069                None
1070            }
1071        } else {
1072            None
1073        }
1074    }
1075    fn cell_subcells_contain_leaves(
1076        &self,
1077        cell: &Cell,
1078        face_index: usize,
1079    ) -> Option<SubSubCellsFace> {
1080        self.cell_subcells_contain_cells(cell, face_index)
1081            .filter(|&subsubcells| {
1082                subsubcells
1083                    .iter()
1084                    .all(|&subsubcell| self[subsubcell].is_leaf())
1085            })
1086    }
1087    fn cell_subcell_contains_leaves(
1088        &self,
1089        cell: &Cell,
1090        face_index: usize,
1091        subsubcell_index: usize,
1092    ) -> Option<SubSubCellsFace> {
1093        self.cell_subcells_contain_cells(cell, face_index)
1094            .filter(|&subsubcells| self[subsubcells[subsubcell_index]].is_leaf())
1095    }
1096    pub fn defeature(&mut self, min_num_voxels: usize) {
1097        //
1098        // Should cells of a reassigned cluster be reassigned one at a time instead?
1099        //
1100        // Do the clusters need to be updated each time another changes?
1101        // In case a cluster inherits the reassigned cluster and becomes large enough?
1102        //
1103        // Still may not understand why `blocks` could be empty below.
1104        //
1105        let mut block = 0;
1106        let mut blocks = vec![];
1107        let mut clusters;
1108        let mut counts: Vec<usize> = vec![];
1109        let mut defeatured;
1110        let mut face_block = 0;
1111        let mut neighbor_block = 0;
1112        let mut new_block = 0;
1113        let mut protruded;
1114        let mut unique_blocks = vec![];
1115        let mut volumes: Vec<usize>;
1116        let supercells = self.supercells();
1117        #[allow(unused_variables)]
1118        for iteration in 1.. {
1119            clusters = self.clusters(Some(&vec![PADDING]), Some(&supercells));
1120            #[cfg(feature = "profile")]
1121            let time = Instant::now();
1122            volumes = clusters
1123                .iter()
1124                .map(|cluster| {
1125                    cluster
1126                        .iter()
1127                        .map(|&cell| self[cell].get_lngth().pow(NSD as u32) as usize)
1128                        .sum()
1129                })
1130                .collect();
1131            defeatured = volumes.iter().all(|volume| volume >= &min_num_voxels);
1132            if !defeatured {
1133                clusters
1134                    .iter()
1135                    .zip(volumes)
1136                    .filter(|(_, volume)| volume < &min_num_voxels)
1137                    .for_each(|(cluster, _)| {
1138                        block = self[cluster[0]].get_block();
1139                        blocks = cluster
1140                            .iter()
1141                            .flat_map(|&cell| {
1142                                self[cell]
1143                                    .get_faces()
1144                                    .iter()
1145                                    .enumerate()
1146                                    .filter_map(|(face, &face_cell)| {
1147                                        if let Some(neighbor) = face_cell {
1148                                            if let Some(subcells) = self[neighbor].get_cells() {
1149                                                Some(
1150                                                    subcells_on_neighbor_face(face)
1151                                                        .into_iter()
1152                                                        .filter_map(|subcell| {
1153                                                            face_block =
1154                                                                self[subcells[subcell]].get_block();
1155                                                            if face_block != block {
1156                                                                Some(face_block)
1157                                                            } else {
1158                                                                None
1159                                                            }
1160                                                        })
1161                                                        .collect(),
1162                                                )
1163                                            } else {
1164                                                face_block = self[neighbor].get_block();
1165                                                if face_block != block {
1166                                                    Some(vec![face_block])
1167                                                } else {
1168                                                    None
1169                                                }
1170                                            }
1171                                        } else {
1172                                            None
1173                                        }
1174                                    })
1175                                    .collect::<Vec<Blocks>>()
1176                            })
1177                            .chain(cluster.iter().filter_map(|&cell| {
1178                                if let Some([parent, subcell]) = supercells[cell] {
1179                                    Some(
1180                                        self[parent]
1181                                            .get_faces()
1182                                            .iter()
1183                                            .enumerate()
1184                                            .filter_map(|(face, face_cell)| {
1185                                                if let Some(neighbor_cell) = face_cell {
1186                                                    if self[*neighbor_cell].is_leaf()
1187                                                        && subcells_on_own_face_contains(
1188                                                            face, subcell,
1189                                                        )
1190                                                    {
1191                                                        neighbor_block =
1192                                                            self[*neighbor_cell].get_block();
1193                                                        if neighbor_block != block {
1194                                                            Some(neighbor_block)
1195                                                        } else {
1196                                                            None
1197                                                        }
1198                                                    } else {
1199                                                        None
1200                                                    }
1201                                                } else {
1202                                                    None
1203                                                }
1204                                            })
1205                                            .collect(),
1206                                    )
1207                                } else {
1208                                    None
1209                                }
1210                            }))
1211                            .collect::<Vec<Blocks>>()
1212                            .into_iter()
1213                            .flatten()
1214                            .collect();
1215                        unique_blocks = blocks.to_vec();
1216                        unique_blocks.sort();
1217                        unique_blocks.dedup();
1218                        counts = unique_blocks
1219                            .iter()
1220                            .map(|unique_block| {
1221                                blocks.iter().filter(|&block| block == unique_block).count()
1222                            })
1223                            .collect();
1224                        if !blocks.is_empty() {
1225                            new_block = unique_blocks[counts
1226                                .iter()
1227                                .position(|count| {
1228                                    count == counts.iter().max().expect("maximum not found")
1229                                })
1230                                .expect("position of maximum not found")];
1231                            cluster
1232                                .iter()
1233                                .for_each(|&cell| self[cell].block = Some(new_block));
1234                        }
1235                    });
1236            }
1237            #[cfg(feature = "profile")]
1238            println!(
1239                "             \x1b[1;93mDefeaturing iteration {}\x1b[0m {:?} ",
1240                iteration,
1241                time.elapsed()
1242            );
1243            protruded = self.protrusions(&supercells);
1244            if defeatured && protruded {
1245                return;
1246            }
1247        }
1248    }
1249    pub fn from_finite_elements<const M: usize, const N: usize, const O: usize, T>(
1250        finite_elements: T,
1251        grid: usize,
1252        size: f64,
1253    ) -> Self
1254    where
1255        T: FiniteElementMethods<M, N, O>,
1256    {
1257        let mut blocks: Blocks = finite_elements
1258            .get_element_blocks()
1259            .iter()
1260            .flat_map(|&block| repeat_n(block, grid.pow(3)))
1261            .collect();
1262        let mut samples = finite_elements.interior_points(grid);
1263        let mut exterior_face_samples = finite_elements.exterior_faces_interior_points(grid);
1264        blocks.extend(vec![PADDING; exterior_face_samples.len()]);
1265        samples.append(&mut exterior_face_samples);
1266        let mut tree = octree_from_bounding_cube(&mut samples, size);
1267        let mut index = 0;
1268        while index < tree.len() {
1269            if let Some(block) = tree[index].homogeneous_coordinates(&blocks, &samples) {
1270                tree[index].block = Some(block);
1271            } else {
1272                tree.subdivide(index)
1273            }
1274            index += 1;
1275        }
1276        tree
1277    }
1278    fn just_leaves(&self, cells: &[usize]) -> bool {
1279        cells.iter().all(|&subcell| self[subcell].is_leaf())
1280    }
1281    pub const fn nel(&self) -> Nel {
1282        self.nel
1283    }
1284    pub fn octree_into_finite_elements(
1285        // will eventually delete this method
1286        self,
1287        remove: Option<Blocks>,
1288        scale: Scale,
1289        translate: Translate,
1290    ) -> Result<HexahedralFiniteElements, String> {
1291        let mut x_min = 0.0;
1292        let mut y_min = 0.0;
1293        let mut z_min = 0.0;
1294        let mut x_val = 0.0;
1295        let mut y_val = 0.0;
1296        let mut z_val = 0.0;
1297        let mut removed_data = remove.unwrap_or_default();
1298        removed_data.sort();
1299        removed_data.dedup();
1300        // removed_data.push(PADDING);
1301        let num_elements = self
1302            .iter()
1303            .filter(|cell| removed_data.binary_search(&cell.get_block()).is_err())
1304            .count();
1305        let mut element_blocks = vec![0; num_elements];
1306        let mut element_node_connectivity = vec![from_fn(|_| 0); num_elements];
1307        let mut nodal_coordinates: Coordinates = (0..num_elements * HEX)
1308            .map(|_| Coordinate::zero())
1309            .collect();
1310        let mut index = 0;
1311        self.iter()
1312            .filter(|cell| removed_data.binary_search(&cell.get_block()).is_err())
1313            .zip(
1314                element_blocks
1315                    .iter_mut()
1316                    .zip(element_node_connectivity.iter_mut()),
1317            )
1318            .for_each(|(cell, (block, connectivity))| {
1319                *block = cell.get_block();
1320                *connectivity = from_fn(|n| n + index);
1321                x_min = *cell.get_min_x() as f64 * scale.x() + translate.x();
1322                y_min = *cell.get_min_y() as f64 * scale.y() + translate.y();
1323                z_min = *cell.get_min_z() as f64 * scale.z() + translate.z();
1324                x_val = (cell.get_min_x() + cell.get_lngth()) as f64 * scale.x() + translate.x();
1325                y_val = (cell.get_min_y() + cell.get_lngth()) as f64 * scale.y() + translate.y();
1326                z_val = (cell.get_min_z() + cell.get_lngth()) as f64 * scale.z() + translate.z();
1327                nodal_coordinates[index] = [x_min, y_min, z_min].into();
1328                nodal_coordinates[index + 1] = [x_val, y_min, z_min].into();
1329                nodal_coordinates[index + 2] = [x_val, y_val, z_min].into();
1330                nodal_coordinates[index + 3] = [x_min, y_val, z_min].into();
1331                nodal_coordinates[index + 4] = [x_min, y_min, z_val].into();
1332                nodal_coordinates[index + 5] = [x_val, y_min, z_val].into();
1333                nodal_coordinates[index + 6] = [x_val, y_val, z_val].into();
1334                nodal_coordinates[index + 7] = [x_min, y_val, z_val].into();
1335                index += HEX;
1336            });
1337        Ok(HexahedralFiniteElements::from((
1338            element_blocks,
1339            element_node_connectivity,
1340            nodal_coordinates,
1341        )))
1342    }
1343    pub fn pair(&mut self) -> bool {
1344        // #[cfg(feature = "profile")]
1345        // let time = Instant::now();
1346        let mut block = 0;
1347        let mut index = 0;
1348        let mut paired_already = true;
1349        let mut subsubcells: Vec<bool>;
1350        while index < self.len() {
1351            if let Some(subcells) = self[index].cells {
1352                subsubcells = subcells
1353                    .into_iter()
1354                    .map(|subcell| self[subcell].is_not_leaf())
1355                    .collect();
1356                if subsubcells.iter().any(|&subsubcell| subsubcell)
1357                    && !subsubcells.iter().all(|&subsubcell| subsubcell)
1358                {
1359                    subcells
1360                        .into_iter()
1361                        .filter(|&subcell| self[subcell].cells.is_none())
1362                        .collect::<Vec<usize>>()
1363                        .into_iter()
1364                        .for_each(|subcell| {
1365                            block = self[subcell].get_block();
1366                            paired_already = false;
1367                            self.subdivide(subcell);
1368                            self.iter_mut()
1369                                .rev()
1370                                .take(NUM_OCTANTS)
1371                                .for_each(|cell| cell.block = Some(block))
1372                        })
1373                }
1374            }
1375            index += 1;
1376        }
1377        // #[cfg(feature = "profile")]
1378        // println!(
1379        //     "           \x1b[1;93m  Pairing hanging nodes\x1b[0m {:?} ",
1380        //     time.elapsed()
1381        // );
1382        paired_already
1383    }
1384    pub fn parameters(self) -> (Remove, Scale, Translate) {
1385        (self.remove, self.scale, self.translate)
1386    }
1387    fn protrusions(&mut self, supercells: &Supercells) -> bool {
1388        let mut blocks = vec![];
1389        let mut complete = true;
1390        let mut counts: Vec<usize> = vec![];
1391        let mut new_block = 0;
1392        let mut protrusions: Vec<(usize, Blocks)>;
1393        let mut unique_blocks = vec![];
1394        #[allow(unused_variables)]
1395        for iteration in 1.. {
1396            #[cfg(feature = "profile")]
1397            let time = Instant::now();
1398            protrusions = self
1399                .iter()
1400                .enumerate()
1401                .filter(|(_, cell)| cell.is_voxel())
1402                .flat_map(|(voxel_cell_index, voxel_cell)| {
1403                    blocks = voxel_cell
1404                        .get_faces()
1405                        .iter()
1406                        .enumerate()
1407                        .flat_map(|(face_index, &face)| {
1408                            if let Some(face_cell_index) = face {
1409                                Some(self[face_cell_index].get_block())
1410                            } else if let Some([parent, _]) = supercells[voxel_cell_index] {
1411                                self[parent].get_faces()[face_index]
1412                                    .map(|neighbor| self[neighbor].get_block())
1413                            } else {
1414                                None
1415                            }
1416                        })
1417                        .collect();
1418                    if blocks
1419                        .iter()
1420                        .filter(|&&face_block| voxel_cell.get_block() != face_block)
1421                        .count()
1422                        >= 5
1423                    {
1424                        Some((voxel_cell_index, blocks.clone()))
1425                    } else {
1426                        None
1427                    }
1428                })
1429                .collect();
1430            if !protrusions.is_empty() {
1431                complete = false;
1432                protrusions.iter().for_each(|(voxel_cell_index, blocks)| {
1433                    unique_blocks = blocks.to_vec();
1434                    unique_blocks.sort();
1435                    unique_blocks.dedup();
1436                    counts = unique_blocks
1437                        .iter()
1438                        .map(|unique_block| {
1439                            blocks.iter().filter(|&block| block == unique_block).count()
1440                        })
1441                        .collect();
1442                    new_block = unique_blocks[counts
1443                        .iter()
1444                        .position(|count| count == counts.iter().max().expect("maximum not found"))
1445                        .expect("position of maximum not found")];
1446                    self[*voxel_cell_index].block = Some(new_block)
1447                })
1448            }
1449            #[cfg(feature = "profile")]
1450            println!(
1451                "             \x1b[1;93mProtrusions iteration {}\x1b[0m {:?} ",
1452                iteration,
1453                time.elapsed()
1454            );
1455            if protrusions.is_empty() {
1456                break;
1457            }
1458        }
1459        complete
1460    }
1461    pub fn prune(&mut self) {
1462        #[cfg(feature = "profile")]
1463        let time = Instant::now();
1464        self.retain(|cell| cell.is_leaf());
1465        #[cfg(feature = "profile")]
1466        println!(
1467            "             \x1b[1;93mPruning octree\x1b[0m {:?} ",
1468            time.elapsed()
1469        );
1470    }
1471    pub fn remove(&self) -> &Remove {
1472        &self.remove
1473    }
1474    pub fn scale(&self) -> &Scale {
1475        &self.scale
1476    }
1477    fn subdivide(&mut self, index: usize) {
1478        assert!(self[index].is_leaf());
1479        let new_indices = from_fn(|n| self.len() + n);
1480        let mut new_cells = self[index].subdivide(new_indices);
1481        self[index]
1482            .get_faces()
1483            .clone()
1484            .iter()
1485            .enumerate()
1486            .for_each(|(face, &face_cell)| {
1487                if let Some(neighbor) = face_cell
1488                    && let Some(kids) = self[neighbor].cells
1489                {
1490                    subcells_on_own_face(face)
1491                        .iter()
1492                        .zip(subcells_on_neighbor_face(face).iter())
1493                        .for_each(|(&subcell, &neighbor_subcell)| {
1494                            new_cells[subcell].faces[face] = Some(kids[neighbor_subcell]);
1495                            self[kids[neighbor_subcell]].faces[mirror_face(face)] =
1496                                Some(new_indices[subcell]);
1497                        });
1498                }
1499            });
1500        self.extend(new_cells);
1501    }
1502    fn supercells(&self) -> Supercells {
1503        let (max_leaf_id, _) = self
1504            .iter()
1505            .enumerate()
1506            .rfind(|(_, cell)| cell.is_leaf())
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}