fj_core/operations/insert/
insert_trait.rs

1use crate::{
2    objects::{
3        Curve, Cycle, Face, HalfEdge, Region, Shell, Sketch, Solid, Surface,
4        Vertex,
5    },
6    operations::build::{Polygon, TetrahedronShell},
7    storage::Handle,
8    Core,
9};
10
11use super::{IsInsertedNo, IsInsertedYes};
12
13/// Insert an object into its respective store
14///
15/// This is the only primitive operation that is directly understood by
16/// `Service<Objects>`. All other operations are built on top of it.
17pub trait Insert: Sized {
18    /// The type of `Self`, once it has been inserted
19    ///
20    /// Usually this is just `Handle<Self>`, but there are some more complex
21    /// cases where this type needs to be customized.
22    type Inserted;
23
24    /// Insert the object into its respective store
25    ///
26    /// Inserted objects will automatically be validated in the background. You
27    /// should not insert an invalid object into the stores, unless you have a
28    /// specific reason to do so, and you are handling validation errors in a
29    /// non-standard way.
30    #[must_use]
31    fn insert(self, core: &mut Core) -> Self::Inserted;
32}
33
34macro_rules! impl_insert {
35    ($($ty:ty, $store:ident;)*) => {
36        $(
37            impl Insert for $ty {
38                type Inserted = Handle<Self>;
39
40                fn insert(self, core: &mut Core) -> Self::Inserted {
41                    let handle = core.layers.objects.$store.reserve();
42                    let object = (handle.clone(), self).into();
43                    core.layers.objects.insert(
44                        object,
45                        &core.layers.geometry,
46                        &mut core.layers.validation,
47                    );
48                    handle
49                }
50            }
51        )*
52    };
53}
54
55impl_insert!(
56    Curve, curves;
57    Cycle, cycles;
58    Face, faces;
59    HalfEdge, half_edges;
60    Region, regions;
61    Shell, shells;
62    Sketch, sketches;
63    Solid, solids;
64    Surface, surfaces;
65    Vertex, vertices;
66);
67
68// Implement `Insert` for `Handle` as a no-op. This is useful for code that
69// needs a `Handle` in the end, but doesn't care if it gets that directly or
70// inserts a bare object itself.
71impl<T> Insert for Handle<T>
72where
73    T: Insert,
74{
75    type Inserted = Self;
76
77    fn insert(self, _: &mut Core) -> Self::Inserted {
78        self
79    }
80}
81
82impl<const D: usize> Insert for Polygon<D, IsInsertedNo> {
83    type Inserted = Polygon<D, IsInsertedYes>;
84
85    fn insert(self, core: &mut Core) -> Self::Inserted {
86        Polygon {
87            face: self.face.insert(core),
88            half_edges: self.half_edges,
89            vertices: self.vertices,
90        }
91    }
92}
93
94impl Insert for TetrahedronShell<IsInsertedNo> {
95    type Inserted = TetrahedronShell<IsInsertedYes>;
96
97    fn insert(self, core: &mut Core) -> Self::Inserted {
98        TetrahedronShell {
99            shell: self.shell.insert(core),
100            abc: self.abc,
101            bad: self.bad,
102            dac: self.dac,
103            cbd: self.cbd,
104        }
105    }
106}