aboutsummaryrefslogtreecommitdiff
path: root/src/mve.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mve.rs')
-rw-r--r--src/mve.rs172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/mve.rs b/src/mve.rs
new file mode 100644
index 0000000..19785d9
--- /dev/null
+++ b/src/mve.rs
@@ -0,0 +1,172 @@
+use crate::*;
+
+// Make Vertex-Edge
+
+pub struct Mve<'brand, 'arena, V> {
+ pub edge: ptr!(Edge),
+ pub data: V,
+}
+
+impl<'brand, 'arena, V> Mve<'brand, 'arena, V> {
+ pub fn new(edge: ptr!(Edge), data: V) -> Self {
+ Self { edge, data }
+ }
+}
+
+impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Mve<'brand, 'arena, V> {
+ type Inverse = Kve<'brand, 'arena, V>;
+ type Error = Infallible;
+ type Check = ();
+
+ fn check(&self, _dcel: &Dcel<'brand, 'arena, V>) -> Result<Self::Check, Self::Error> {
+ Ok(())
+ }
+
+ fn apply(
+ self,
+ dcel: &mut Dcel<'brand, 'arena, V>,
+ ) -> Result<Self::Inverse, OperatorErr<Self, Self::Error>> {
+ // before:
+ //
+ // >
+ // / a3
+ // a1 ->
+ // v1 v2
+ // <- b1
+ // \ b3
+ // <
+ //
+ // after:
+ //
+ // >
+ // / a3
+ // a1 -> a2 ->
+ // v1 v v2
+ // <- b1 <- b2
+ // \ b3
+ // <
+
+ try_check!(self, dcel);
+
+ let Mve { edge, data } = self;
+
+ let shell = edge.lens(dcel).half_edges()[0].loop_().face().shell().item;
+
+ let (new_edge, [a2, b2]) = Edge::create(shell, dcel);
+ let v = shell.add_new_vertex(data, dcel);
+
+ let [a1, b1] = edge.half_edges(dcel);
+ let v2 = edge.vertices(dcel)[1];
+
+ let mut a3 = a1.next(dcel);
+ let mut b3 = b1.prev(dcel);
+
+ if a3.eq(b1, dcel) {
+ a3 = b2;
+ }
+ if b3.eq(a1, dcel) {
+ b3 = a2;
+ }
+
+ a2.update_origin(*v, dcel);
+ b1.update_origin(*v, dcel);
+ b2.update_origin(v2, dcel);
+
+ dcel.follow(a1, a2);
+ dcel.follow(a2, a3);
+ dcel.follow(b3, b2);
+ dcel.follow(b2, b1);
+
+ a2.set_loop_(a1.loop_(dcel), dcel);
+ b2.set_loop_(b1.loop_(dcel), dcel);
+
+ Ok(Kve {
+ edge: new_edge,
+ vertex: v,
+ })
+ }
+}
+
+pub struct Kve<'brand, 'arena, V> {
+ pub edge: own!(Edge),
+ pub vertex: own!(Vertex),
+}
+
+impl<'brand, 'arena, V> Kve<'brand, 'arena, V> {
+ pub fn new(edge: own!(Edge), vertex: own!(Vertex)) -> Self {
+ Self { edge, vertex }
+ }
+}
+
+#[derive(Debug, Error)]
+pub enum KveError {
+ #[error("vertex is not part of edge")]
+ VertexEdgeMismatch,
+ #[error("vertex has more than two outgoing edges")]
+ TooManyOutgoing,
+ #[error("vertex is turning point, use KEV")]
+ VertexTurningPoint,
+}
+
+impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Kve<'brand, 'arena, V> {
+ type Inverse = Mve<'brand, 'arena, V>;
+ type Error = KveError;
+ type Check = [ptr!(HalfEdge); 2];
+
+ fn check(&self, dcel: &Dcel<'brand, 'arena, V>) -> Result<Self::Check, Self::Error> {
+ use KveError::*;
+
+ let [mut a2, mut b2] = self.edge.lens(dcel).half_edges();
+ if b2.origin().eq(*self.vertex) {
+ [a2, b2] = [b2, a2];
+ }
+
+ or_err(a2.origin().eq(*self.vertex), VertexEdgeMismatch)?;
+ or_err(
+ self.vertex.iter_outgoing(dcel).count() == 2,
+ TooManyOutgoing,
+ )?;
+ or_err(b2.next() != a2, VertexTurningPoint)?;
+
+ Ok([a2.item, b2.item])
+ }
+
+ fn apply(
+ self,
+ dcel: &mut Dcel<'brand, 'arena, V>,
+ ) -> Result<Self::Inverse, OperatorErr<Self, Self::Error>> {
+ let [a2, b2] = try_check!(self, dcel);
+
+ let a1 = a2.prev(dcel);
+ let b1 = b2.next(dcel);
+
+ let v2 = b2.origin(dcel);
+
+ let mut a3 = a2.next(dcel);
+ if a3.eq(b2, dcel) {
+ a3 = b1;
+ }
+ let mut b3 = b2.prev(dcel);
+ if b3.eq(a2, dcel) {
+ b3 = a1;
+ }
+
+ dcel.follow(a1, a3);
+ dcel.follow(b3, b1);
+
+ b1.update_origin(v2, dcel);
+ a1.loop_(dcel).set_half_edges(a1, dcel);
+ b1.loop_(dcel).set_half_edges(b1, dcel);
+
+ let shell = a1.loop_(dcel).face(dcel).shell(dcel);
+ shell.remove_edge(*self.edge, dcel);
+ shell.remove_vertex(*self.vertex, dcel);
+
+ self.edge.destroy(dcel);
+
+ Ok(Mve {
+ edge: a1.edge(dcel),
+ data: self.vertex.destroy(dcel),
+ })
+ }
+}