microcad_core/geo3d/
collection.rs1use std::rc::Rc;
7
8use derive_more::{Deref, DerefMut};
9
10use crate::{
11 geo3d::{FetchBounds3D, 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, resolution: &RenderResolution, op: &BooleanOp) -> Rc<Manifold> {
32 let manifold_list: Vec<_> = self
33 .0
34 .iter()
35 .filter_map(|geo| {
37 let manifold = geo.render_to_manifold(resolution);
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 pub fn hull(&self, resolution: &RenderResolution) -> Manifold {
59 self.render_to_manifold(resolution).hull()
60 }
61}
62
63impl FromIterator<Rc<Geometry3D>> for Geometries3D {
64 fn from_iter<T: IntoIterator<Item = Rc<Geometry3D>>>(iter: T) -> Self {
65 Geometries3D(iter.into_iter().collect())
66 }
67}
68
69impl FetchBounds3D for Geometries3D {
70 fn fetch_bounds_3d(&self) -> Bounds3D {
71 self.0.iter().fold(Bounds3D::default(), |bounds, geometry| {
72 bounds.extend(geometry.fetch_bounds_3d())
73 })
74 }
75}
76
77impl Transformed3D for Geometries3D {
78 fn transformed_3d(&self, render_resolution: &RenderResolution, mat: &Mat4) -> Self {
79 Self(
80 self.iter()
81 .map(|geometry| Rc::new(geometry.transformed_3d(render_resolution, mat)))
82 .collect::<Vec<_>>(),
83 )
84 }
85}
86
87impl RenderToMesh for Geometries3D {
88 fn render_to_manifold(&self, resolution: &RenderResolution) -> std::rc::Rc<Manifold> {
89 self.boolean_op(resolution, &BooleanOp::Union)
90 }
91}