microcad_core/geo3d/
collection.rs1use std::rc::Rc;
7
8use derive_more::{Deref, DerefMut};
9
10use crate::{
11 geo3d::{CalcBounds3D, bounds::Bounds3D},
12 traits::{DistributeGrid, TotalMemory, VertexCount},
13 *,
14};
15
16#[derive(Debug, Clone, Default, Deref, DerefMut)]
18pub struct Geometries3D(Vec<Rc<Geometry3D>>);
19
20impl Geometries3D {
21 pub fn new(geometries: Vec<Geometry3D>) -> Self {
23 Self(geometries.into_iter().map(Rc::new).collect())
24 }
25
26 pub fn append(&mut self, mut geometries: Geometries3D) {
28 self.0.append(&mut geometries.0)
29 }
30
31 pub fn boolean_op(&self, op: &BooleanOp) -> Rc<Manifold> {
33 let manifold_list: Vec<_> = self
34 .0
35 .iter()
36 .filter_map(|geo| {
38 let manifold: Rc<Manifold> = geo.as_ref().clone().into();
39 if manifold.is_empty() {
40 None
41 } else {
42 Some(manifold)
43 }
44 })
45 .collect();
46
47 if manifold_list.is_empty() {
48 return Rc::new(Manifold::empty());
49 }
50
51 manifold_list[1..]
52 .iter()
53 .fold(manifold_list[0].clone(), |acc, other| {
54 Rc::new(acc.boolean_op(other, op.into()))
55 })
56 }
57}
58
59impl FromIterator<Rc<Geometry3D>> for Geometries3D {
60 fn from_iter<T: IntoIterator<Item = Rc<Geometry3D>>>(iter: T) -> Self {
61 Geometries3D(iter.into_iter().collect())
62 }
63}
64
65impl CalcBounds3D for Geometries3D {
66 fn calc_bounds_3d(&self) -> Bounds3D {
67 self.0.iter().fold(Bounds3D::default(), |bounds, geometry| {
68 bounds.extend(geometry.calc_bounds_3d())
69 })
70 }
71}
72
73impl Transformed3D for Geometries3D {
74 fn transformed_3d(&self, mat: &Mat4) -> Self {
75 Self(
76 self.iter()
77 .map(|geometry| Rc::new(geometry.transformed_3d(mat)))
78 .collect::<Vec<_>>(),
79 )
80 }
81}
82
83impl DistributeGrid for Geometries3D {
84 fn distribute_grid(&self, rect: Rect, rows: Integer, columns: Integer) -> Self {
85 Geometries3D(
86 GridCells::new(rect, rows, columns)
87 .zip(self.0.iter())
88 .map(|(cell, geo)| {
89 let bounds = geo.calc_bounds_3d();
90 let center = bounds.center();
91 let cell_center: Vec2 = cell.center().x_y().into();
92 let d = center - cell_center.extend(bounds.min.z + center.z);
93 Rc::new(geo.transformed_3d(&Mat4::from_translation(d)))
94 })
95 .collect(),
96 )
97 }
98}
99
100impl TotalMemory for Geometries3D {
101 fn heap_memory(&self) -> usize {
102 self.iter().map(|g| g.heap_memory()).sum()
103 }
104}
105
106impl VertexCount for Geometries3D {
107 fn vertex_count(&self) -> usize {
108 self.iter().map(|g| g.vertex_count()).sum()
109 }
110}