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#[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] - ¢er).norm()
353 > (&coordinates[index] - ¢er).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 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 if balanced {
844 break;
845 }
846 }
847 balanced_already
848 }
849 fn boundaries(&mut self) {
850 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 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 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 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 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 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 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}