fj_kernel/operations/
insert.rs

1use crate::{
2    objects::{
3        Cycle, Face, GlobalEdge, HalfEdge, Shell, Sketch, Solid, Surface,
4        Vertex,
5    },
6    services::Services,
7    storage::Handle,
8};
9
10use super::{Polygon, TetrahedronShell};
11
12/// Insert an object into its respective store
13///
14/// This is the only primitive operation that is directly understood by
15/// `Service<Objects>`. All other operations are built on top of it.
16pub trait Insert: Sized {
17    /// The type of `Self`, once it has been inserted
18    ///
19    /// Usually this is just `Handle<Self>`, but there are some more complex
20    /// cases where this type needs to be customized.
21    type Inserted;
22
23    /// Insert the object into its respective store
24    fn insert(self, services: &mut Services) -> Self::Inserted;
25}
26
27macro_rules! impl_insert {
28    ($($ty:ty, $store:ident;)*) => {
29        $(
30            impl Insert for $ty {
31                type Inserted = Handle<Self>;
32
33                fn insert(self, services: &mut Services) -> Self::Inserted {
34                    let handle = services.objects.$store.reserve();
35                    let object = (handle.clone(), self).into();
36                    services.insert_object(object);
37                    handle
38                }
39            }
40        )*
41    };
42}
43
44impl_insert!(
45    Cycle, cycles;
46    Face, faces;
47    GlobalEdge, global_edges;
48    HalfEdge, half_edges;
49    Shell, shells;
50    Sketch, sketches;
51    Solid, solids;
52    Surface, surfaces;
53    Vertex, vertices;
54);
55
56/// Indicate whether an object has been inserted
57///
58/// Intended to be used as a type parameter bound for structs that need to track
59/// whether their contents have been inserted or not.
60pub trait IsInserted {
61    /// The type of the object for which the insertion status is tracked
62    type T<T>;
63}
64
65/// Indicate that an object has been inserted
66///
67/// See [`IsInserted`].
68pub struct IsInsertedYes;
69
70impl IsInserted for IsInsertedYes {
71    type T<T> = Handle<T>;
72}
73
74/// Indicate that an object has not been inserted
75///
76/// See [`IsInserted`].
77pub struct IsInsertedNo;
78
79impl IsInserted for IsInsertedNo {
80    type T<T> = T;
81}
82
83impl<const D: usize> Insert for Polygon<D, IsInsertedNo> {
84    type Inserted = Polygon<D, IsInsertedYes>;
85
86    fn insert(self, services: &mut Services) -> Self::Inserted {
87        Polygon {
88            face: self.face.insert(services),
89            edges: self.edges,
90            vertices: self.vertices,
91        }
92    }
93}
94
95impl Insert for TetrahedronShell<IsInsertedNo> {
96    type Inserted = TetrahedronShell<IsInsertedYes>;
97
98    fn insert(self, services: &mut Services) -> Self::Inserted {
99        TetrahedronShell {
100            shell: self.shell.insert(services),
101            abc: self.abc,
102            bad: self.bad,
103            dac: self.dac,
104            cbd: self.cbd,
105        }
106    }
107}