microcad_core/geo3d/
geometry.rs

1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::*;
5
6use std::rc::Rc;
7use strum::IntoStaticStr;
8
9use crate::geo3d::*;
10
11/// 3D Geometry
12#[derive(IntoStaticStr, Clone)]
13pub enum Geometry3D {
14    /// Triangle mesh.
15    Mesh(TriangleMesh),
16    /// Manifold.
17    Manifold(Rc<Manifold>),
18    /// Cube.
19    Cube(Cube),
20    /// Sphere.
21    Sphere(Sphere),
22    /// Cylinder.
23    Cylinder(Cylinder),
24    /// Collection,
25    Collection(Geometries3D),
26}
27
28impl std::fmt::Debug for Geometry3D {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        let name: &'static str = self.into();
31        write!(f, "{name}")
32    }
33}
34
35impl Geometry3D {
36    /// Return name of geometry.
37    pub fn name(&self) -> &'static str {
38        self.into()
39    }
40
41    /// Execute boolean operation.
42    pub fn boolean_op(
43        &self,
44        resolution: &RenderResolution,
45        other: &Geometry3D,
46        op: &BooleanOp,
47    ) -> Option<Self> {
48        let op: manifold_rs::BooleanOp = op.into();
49        let a = self.clone().render_to_manifold(resolution);
50        let b = other.clone().render_to_manifold(resolution);
51
52        Some(Geometry3D::Manifold(Rc::new(a.boolean_op(&b, op))))
53    }
54
55    /// Convex hull for geometry.
56    pub fn hull(&self, resolution: &RenderResolution) -> Manifold {
57        self.render_to_manifold(resolution).hull()
58    }
59
60    /// Transform mesh geometry
61    pub fn transform(&self, transform: &crate::Mat4) -> Self {
62        match self {
63            Geometry3D::Mesh(mesh) => Geometry3D::Mesh(mesh.transform(transform)),
64
65            Geometry3D::Manifold(manifold) => {
66                // TODO: Implement transform for manifold instead of converting to mesh
67                let mesh = TriangleMesh::from(manifold.to_mesh()).transform(transform);
68                Geometry3D::Manifold(Rc::new(mesh.to_manifold()))
69            }
70            _ => todo!(),
71        }
72    }
73}
74
75impl FetchBounds3D for Rc<Manifold> {
76    fn fetch_bounds_3d(&self) -> Bounds3D {
77        todo!()
78    }
79}
80
81impl FetchBounds3D for Geometry3D {
82    fn fetch_bounds_3d(&self) -> Bounds3D {
83        match self {
84            Geometry3D::Mesh(triangle_mesh) => triangle_mesh.fetch_bounds_3d(),
85            Geometry3D::Manifold(manifold) => manifold.fetch_bounds_3d(),
86            Geometry3D::Cube(cube) => cube.fetch_bounds_3d(),
87            Geometry3D::Sphere(sphere) => sphere.fetch_bounds_3d(),
88            Geometry3D::Cylinder(cylinder) => cylinder.fetch_bounds_3d(),
89            Geometry3D::Collection(collection) => collection.fetch_bounds_3d(),
90        }
91    }
92}
93
94impl Transformed3D for Geometry3D {
95    fn transformed_3d(&self, render_resolution: &RenderResolution, mat: &Mat4) -> Self {
96        Self::Mesh(match self {
97            Geometry3D::Mesh(triangle_mesh) => triangle_mesh.transform(mat),
98            geometry => geometry
99                .clone()
100                .render_to_mesh(render_resolution)
101                .transform(mat),
102        })
103    }
104}
105
106impl RenderToMesh for Geometry3D {
107    fn render_to_manifold(&self, resolution: &RenderResolution) -> std::rc::Rc<Manifold> {
108        match self {
109            Geometry3D::Mesh(triangle_mesh) => std::rc::Rc::new(triangle_mesh.to_manifold()),
110            Geometry3D::Manifold(manifold) => manifold.clone(),
111            Geometry3D::Cube(cube) => cube.render_to_manifold(resolution),
112            Geometry3D::Sphere(sphere) => sphere.render_to_manifold(resolution),
113            Geometry3D::Cylinder(cylinder) => cylinder.render_to_manifold(resolution),
114            Geometry3D::Collection(collection) => collection.render_to_manifold(resolution),
115        }
116    }
117}
118
119impl From<TriangleMesh> for Geometry3D {
120    fn from(mesh: TriangleMesh) -> Self {
121        Geometry3D::Mesh(mesh)
122    }
123}