microcad_core/geo3d/
collection.rs1use std::rc::Rc;
7
8use derive_more::{Deref, DerefMut};
9
10use crate::{
11 geo3d::{CalcBounds3D, bounds::Bounds3D},
12 *,
13};
14
15#[derive(Debug, Clone, Default, Deref, DerefMut)]
17pub struct Geometries3D(Vec<Rc<Geometry3D>>);
18
19impl Geometries3D {
20 pub fn new(geometries: Vec<Geometry3D>) -> Self {
22 Self(geometries.into_iter().map(Rc::new).collect())
23 }
24
25 pub fn append(&mut self, mut geometries: Geometries3D) {
27 self.0.append(&mut geometries.0)
28 }
29
30 pub fn boolean_op(&self, op: &BooleanOp) -> Rc<Manifold> {
32 let manifold_list: Vec<_> = self
33 .0
34 .iter()
35 .filter_map(|geo| {
37 let manifold: Rc<Manifold> = geo.as_ref().clone().into();
38 if manifold.is_empty() {
39 None
40 } else {
41 Some(manifold)
42 }
43 })
44 .collect();
45
46 if manifold_list.is_empty() {
47 return Rc::new(Manifold::empty());
48 }
49
50 manifold_list[1..]
51 .iter()
52 .fold(manifold_list[0].clone(), |acc, other| {
53 Rc::new(acc.boolean_op(other, op.into()))
54 })
55 }
56}
57
58impl FromIterator<Rc<Geometry3D>> for Geometries3D {
59 fn from_iter<T: IntoIterator<Item = Rc<Geometry3D>>>(iter: T) -> Self {
60 Geometries3D(iter.into_iter().collect())
61 }
62}
63
64impl CalcBounds3D for Geometries3D {
65 fn calc_bounds_3d(&self) -> Bounds3D {
66 self.0.iter().fold(Bounds3D::default(), |bounds, geometry| {
67 bounds.extend(geometry.calc_bounds_3d())
68 })
69 }
70}
71
72impl Transformed3D for Geometries3D {
73 fn transformed_3d(&self, mat: &Mat4) -> Self {
74 Self(
75 self.iter()
76 .map(|geometry| Rc::new(geometry.transformed_3d(mat)))
77 .collect::<Vec<_>>(),
78 )
79 }
80}