fj_operations/
lib.rs

1//! # Fornjot CAD Operations
2//!
3//! This library is part of the [Fornjot] ecosystem. Fornjot is an open-source,
4//! code-first CAD application; and collection of libraries that make up the CAD
5//! application, but can be used independently.
6//!
7//! This library is an internal component of Fornjot. It is not relevant to end
8//! users that just want to create CAD models.
9//!
10//! Fornjot models use the [`fj`] crate to define a shape. This crate provides
11//! the connection between [`fj`] and the Fornjot kernel. It translates those
12//! operations into terms the kernel can understand.
13//!
14//! [Fornjot]: https://www.fornjot.app/
15//! [`fj`]: https://crates.io/crates/fj
16
17#![warn(missing_docs)]
18
19pub mod shape_processor;
20
21mod difference_2d;
22mod group;
23mod sketch;
24mod sweep;
25mod transform;
26
27use fj_interop::debug::DebugInfo;
28use fj_kernel::{
29    objects::{FaceSet, Sketch},
30    services::Services,
31};
32use fj_math::Aabb;
33
34/// Implemented for all operations from the [`fj`] crate
35pub trait Shape {
36    /// The type that is used for the shape's boundary representation
37    type Brep;
38
39    /// Compute the boundary representation of the shape
40    fn compute_brep(
41        &self,
42        services: &mut Services,
43        debug_info: &mut DebugInfo,
44    ) -> Self::Brep;
45
46    /// Access the axis-aligned bounding box of a shape
47    ///
48    /// If a shape is empty, its [`Aabb`]'s `min` and `max` points must be equal
49    /// (but are otherwise not specified).
50    fn bounding_volume(&self) -> Aabb<3>;
51}
52
53impl Shape for fj::Shape {
54    type Brep = FaceSet;
55
56    fn compute_brep(
57        &self,
58        services: &mut Services,
59        debug_info: &mut DebugInfo,
60    ) -> Self::Brep {
61        match self {
62            Self::Shape2d(shape) => {
63                shape.compute_brep(services, debug_info).faces().clone()
64            }
65            Self::Group(shape) => shape.compute_brep(services, debug_info),
66            Self::Sweep(shape) => shape
67                .compute_brep(services, debug_info)
68                .shells()
69                .map(|shell| shell.faces().clone())
70                .reduce(|mut a, b| {
71                    a.extend(b);
72                    a
73                })
74                .unwrap_or_default(),
75            Self::Transform(shape) => shape.compute_brep(services, debug_info),
76        }
77    }
78
79    fn bounding_volume(&self) -> Aabb<3> {
80        match self {
81            Self::Shape2d(shape) => shape.bounding_volume(),
82            Self::Group(shape) => shape.bounding_volume(),
83            Self::Sweep(shape) => shape.bounding_volume(),
84            Self::Transform(shape) => shape.bounding_volume(),
85        }
86    }
87}
88
89impl Shape for fj::Shape2d {
90    type Brep = Sketch;
91
92    fn compute_brep(
93        &self,
94        services: &mut Services,
95        debug_info: &mut DebugInfo,
96    ) -> Self::Brep {
97        match self {
98            Self::Difference(shape) => shape.compute_brep(services, debug_info),
99            Self::Sketch(shape) => shape.compute_brep(services, debug_info),
100        }
101    }
102
103    fn bounding_volume(&self) -> Aabb<3> {
104        match self {
105            Self::Difference(shape) => shape.bounding_volume(),
106            Self::Sketch(shape) => shape.bounding_volume(),
107        }
108    }
109}