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