From 219261b7042fba1a54ecd478b56e902d9ca8787b Mon Sep 17 00:00:00 2001 From: Charlotte Pabst Date: Thu, 7 Mar 2024 21:52:30 +0100 Subject: --- src/mevvlfs.rs | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/mevvlfs.rs (limited to 'src/mevvlfs.rs') diff --git a/src/mevvlfs.rs b/src/mevvlfs.rs new file mode 100644 index 0000000..370ad96 --- /dev/null +++ b/src/mevvlfs.rs @@ -0,0 +1,184 @@ +use crate::*; + +// Make Edge-Vertex-Vertex-Loop-Face-Shell + +pub struct Mevvlfs<'brand, 'arena, V> { + body: ptr!(Body), + data: [V; 2], +} + +impl<'brand, 'arena, V> Mevvlfs<'brand, 'arena, V> { + pub fn new(body: ptr!(Body), data: [V; 2]) -> Self { + Self { body, data } + } +} + +impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Mevvlfs<'brand, 'arena, V> { + type Inverse = Kevvlfs<'brand, 'arena, V>; + type Error = Infallible; + type Check = (); + + fn check(&self, _dcel: &Dcel<'brand, 'arena, V>) -> Result { + Ok(()) + } + + fn apply( + self, + dcel: &mut Dcel<'brand, 'arena, V>, + ) -> Result> { + try_check!(self, dcel); + + let Mevvlfs { + body, + data: [d1, d2], + } = self; + + let shell = body.add_new_shell(dcel); + let face = shell.add_new_face(dcel); + let (edge, [a, b]) = Edge::create(*shell, dcel); + let loop_ = Loop::new(dcel); + let v1 = shell.add_new_vertex(d1, dcel); + let v2 = shell.add_new_vertex(d2, dcel); + + loop_.set_face(*face, dcel); + face.set_outer_loop(*loop_, dcel); + + a.update_origin(*v1, dcel); + b.update_origin(*v2, dcel); + + loop_.add_half_edge(a, dcel); + loop_.add_half_edge(b, dcel); + + Ok(Kevvlfs { + body, + edge, + vertices: [v1, v2], + loop_, + face, + shell, + }) + } +} + +pub struct Kevvlfs<'brand, 'arena, V> { + pub body: ptr!(Body), + pub edge: own!(Edge), + pub vertices: [own!(Vertex); 2], + pub loop_: own!(Loop), + pub face: own!(Face), + pub shell: own!(Shell), +} + +#[derive(Debug, Error)] +pub enum KevvlfsError { + #[error("edge vertices do not equal vertices")] + EdgeVerticesMismatch, + #[error("half_edge loop does not equal loop")] + HalfEdgeLoopMismatch, + #[error("loop is not cycle between half edges")] + InvalidLoop, + #[error("face outer loop does not match loop")] + FaceOuterLoopMismatch, + #[error("face has inner loops")] + FaceHasInnerLoops, + #[error("shell has more than one face")] + ShellHasMoreThanOneFace, + #[error("shell face does not match face")] + ShellFaceMismatch, + #[error("shell body does not match body")] + ShellBodyMismatch, +} + +impl<'brand, 'arena, V> Kevvlfs<'brand, 'arena, V> { + pub fn new( + body: ptr!(Body), + edge: own!(Edge), + vertices: [own!(Vertex); 2], + loop_: own!(Loop), + face: own!(Face), + shell: own!(Shell), + ) -> Self { + Self { + body, + edge, + vertices, + loop_, + face, + shell, + } + } +} + +impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Kevvlfs<'brand, 'arena, V> { + type Inverse = Mevvlfs<'brand, 'arena, V>; + type Error = KevvlfsError; + type Check = (); + + fn check(&self, dcel: &Dcel<'brand, 'arena, V>) -> Result { + let Kevvlfs { + body, + edge, + vertices: [v1, v2], + loop_, + face, + shell, + } = self; + + mklens!(dcel, edge, loop_, face, shell, body, v1, v2); + + let [a, b] = edge.half_edges(); + let edge_verts = edge.vertices(); + + or_err( + edge_verts == [v1, v2] || edge_verts == [v2, v1], + KevvlfsError::EdgeVerticesMismatch, + )?; + + or_err(a.loop_() == loop_, KevvlfsError::HalfEdgeLoopMismatch)?; + or_err(a.next() == b, KevvlfsError::InvalidLoop)?; + or_err(b.next() == a, KevvlfsError::InvalidLoop)?; + + or_err( + face.outer_loop() == loop_, + KevvlfsError::FaceOuterLoopMismatch, + )?; + or_err( + face.maybe_inner_loops().is_none(), + KevvlfsError::FaceHasInnerLoops, + )?; + + or_err(face.next() == face, KevvlfsError::ShellHasMoreThanOneFace)?; + or_err(shell.faces() == face, KevvlfsError::ShellFaceMismatch)?; + or_err(shell.body() == body, KevvlfsError::ShellBodyMismatch)?; + + Ok(()) + } + + fn apply( + self, + dcel: &mut Dcel<'brand, 'arena, V>, + ) -> Result> { + try_check!(self, dcel); + + let Kevvlfs { + body, + edge, + vertices, + loop_, + face, + shell, + } = self; + + body.remove_shell(*shell, dcel); + + edge.destroy(dcel); + loop_.free(dcel); + face.free(dcel); + shell.free(dcel); + + Ok(Mevvlfs { + body, + data: vertices.map(|v| v.destroy(dcel)), + }) + } +} -- cgit v1.2.3