aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlotte Pabst <charlotte.pabst@stud.tu-darmstadt.de>2024-03-14 21:55:49 +0100
committerCharlotte Pabst <charlotte.pabst@stud.tu-darmstadt.de>2024-03-24 17:20:05 +0100
commit0a922773a37f6a6a0d73ee0c1fa884e90e5f0f1d (patch)
tree58c745136e4cda545a28437816ad495c1be5ae7f
parent6a7d3ec46347d06d70e08577f688ec5b534e2c08 (diff)
downloaddcel-0a922773a37f6a6a0d73ee0c1fa884e90e5f0f1d.tar.xz
-rw-r--r--src/depth_search_iterator.rs83
-rw-r--r--src/main.rs160
-rw-r--r--src/melf.rs174
-rw-r--r--src/mev.rs4
-rw-r--r--src/msev.rs3
-rw-r--r--src/mve.rs172
-rw-r--r--src/tests.rs89
7 files changed, 460 insertions, 225 deletions
diff --git a/src/depth_search_iterator.rs b/src/depth_search_iterator.rs
deleted file mode 100644
index cc10df8..0000000
--- a/src/depth_search_iterator.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-use crate::*;
-
-pub(crate) struct DepthSearchIterator<'tok, 'brand, 'arena, V> {
- token: &'tok GhostToken<'brand>,
- seen_vertices: Option<HashMap<usize, ptr!(Vertex)>>,
- seen_edges: HashMap<usize, ptr!(Edge)>,
- seen_faces: HashMap<usize, ptr!(Face)>,
- edge_stack: Vec<ptr!(Edge)>,
- face_stack: Vec<ptr!(Face)>,
-}
-
-impl<'tok, 'brand, 'arena, V> DepthSearchIterator<'tok, 'brand, 'arena, V> {
- pub(crate) fn new(
- edge: ptr!(Edge),
- collect_vertices: bool,
- token: &'tok impl ReflAsRef<GhostToken<'brand>>,
- ) -> Self {
- Self {
- token: token.as_ref(),
- seen_vertices: collect_vertices.then(|| HashMap::new()),
- seen_edges: HashMap::from([(edge.id(token), edge)]),
- seen_faces: HashMap::new(),
- edge_stack: Vec::from([edge]),
- face_stack: Vec::new(),
- }
- }
-
- fn add_edge(&mut self, edge: ptr!(Edge)) {
- if self.seen_edges.insert(edge.id(self.token), edge).is_none() {
- self.edge_stack.push(edge);
- }
- }
-
- pub(crate) fn collect_seen(
- edge: ptr!(Edge),
- token: &'tok impl ReflAsRef<GhostToken<'brand>>,
- ) -> (
- HashMap<usize, ptr!(Vertex)>,
- HashMap<usize, ptr!(Edge)>,
- HashMap<usize, ptr!(Face)>,
- )
- where
- 'brand: 'tok,
- {
- let mut x = Self::new(edge, true, token);
- for _ in &mut x {}
- (x.seen_vertices.unwrap(), x.seen_edges, x.seen_faces)
- }
-}
-
-impl<'tok, 'brand, 'arena, V> Iterator for DepthSearchIterator<'tok, 'brand, 'arena, V> {
- type Item = ptr!(Edge);
-
- fn next(&mut self) -> Option<Self::Item> {
- let Some(edge) = self.edge_stack.pop() else {
- let face = self.face_stack.pop()?;
-
- for loop_ in std::iter::once(face.lens(self.token).outer_loop())
- .chain(face.iter_inner_loops(self.token))
- {
- self.add_edge(loop_.half_edges().edge().item);
- }
-
- return self.next();
- };
-
- for h in edge.half_edges(self.token) {
- let face = h.loop_(self.token).face(self.token);
- if self.seen_faces.insert(face.id(self.token), face).is_none() {
- self.face_stack.push(face);
- }
-
- let origin = h.origin(self.token);
- if let Some(seen_vertices) = self.seen_vertices.as_mut() {
- seen_vertices.insert(origin.id(self.token), origin);
- }
-
- self.add_edge(h.next(self.token).edge(self.token));
- }
-
- Some(edge)
- }
-}
diff --git a/src/main.rs b/src/main.rs
index 4a308aa..c3a3f4f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -40,11 +40,11 @@ pub use mevvlfs::*;
mod mev;
pub use mev::*;
-// mod mve;
-// pub use mve::*;
+mod mve;
+pub use mve::*;
-// mod melf;
-// pub use melf::*;
+mod melf;
+pub use melf::*;
mod mekh;
pub use mekh::*;
@@ -626,22 +626,6 @@ impl<'brand, 'arena, T: Entity<'brand, 'arena>> Allocator<'brand, 'arena, T> {
}
}
-pub struct Melf<'brand, 'arena, V> {
- pub shell: ptr!(Shell),
- pub vertices: [ptr!(Vertex); 2],
- pub old_loop: ptr!(Loop),
- pub new_loop: own!(Loop),
- pub edge: own!(Edge),
- pub face: own!(Face),
-}
-
-pub struct Mve<'brand, 'arena, V> {
- pub shell: ptr!(Shell),
- pub old_edge: ptr!(Edge),
- pub new_edge: own!(Edge),
- pub vertex: own!(Vertex),
-}
-
pub struct OperatorErr<T, E> {
pub op: T,
pub err: E,
@@ -817,121 +801,35 @@ impl<'brand, 'arena, V> Dcel<'brand, 'arena, V> {
pub fn melf(
&mut self,
- shell: ptr!(Shell),
vertices: [ptr!(Vertex); 2],
- old_loop: ptr!(Loop),
- ) -> Melf<'brand, 'arena, V> {
- // before:
- // > >
- // a0 \ / a2
- // v1 v2
- // b0 / \ b2
- // < <
- //
- // after:
- // > >
- // a0 \ a1 -> / a2
- // v1 v2
- // b0 / <- b1 \ b2
- // < <
- //
-
- let (edge, [a1, b1]) = Edge::create(shell, self);
- let face = shell.add_new_face(self);
- let new_loop = Loop::new(self); // face.add_new_outer_loop(self);
-
- let [v1, v2] = vertices;
- let [b0, a2] = vertices.map(|v| v.find_outgoing(old_loop, self).unwrap());
-
- let a0 = b0.prev(self);
- let b2 = a2.prev(self);
-
- new_loop.set_face(*face, self);
- face.set_outer_loop(*new_loop, self);
-
- a1.update_origin(v1, self);
- self.follow(a0, a1);
- self.follow(a1, a2);
- old_loop.set_half_edges(a1, self);
- a1.set_loop_(old_loop, self);
-
- b1.update_origin(v2, self);
- self.follow(b2, b1);
- self.follow(b1, b0);
- new_loop.set_half_edges(b1, self);
- new_loop.update_connectivity(self);
- // new_loop.iter_mut_half_edges(self, |x, dcel| x.set_loop_(*new_loop, dcel));
-
- Melf {
- shell,
- vertices,
- old_loop,
- new_loop,
- edge,
- face,
- }
+ loop_: ptr!(Loop),
+ ) -> Result<Kelf<'brand, 'arena, V>, OperatorErr<Melf<'brand, 'arena, V>, MelfError>> {
+ Melf::new(vertices, loop_).apply(self)
+ }
+
+ pub fn kelf(
+ &mut self,
+ edge: own!(Edge),
+ loop_: own!(Loop),
+ face: own!(Face),
+ ) -> Result<Melf<'brand, 'arena, V>, OperatorErr<Kelf<'brand, 'arena, V>, KelfError>> {
+ Kelf::new(edge, loop_, face).apply(self)
}
pub fn mve(
&mut self,
- shell: ptr!(Shell),
- old_edge: ptr!(Edge),
+ edge: ptr!(Edge),
data: V,
- ) -> Mve<'brand, 'arena, V> {
- // before:
- //
- // >
- // / a3
- // a1 ->
- // v1 v2
- // <- b1
- // \ b3
- // <
- //
- // after:
- //
- // >
- // / a3
- // a1 -> a2 ->
- // v1 v v2
- // <- b1 <- b2
- // \ b3
- // <
-
- let (new_edge, [a2, b2]) = Edge::create(shell, self);
- let v = shell.add_new_vertex(data, self);
-
- let [a1, b1] = old_edge.half_edges(self);
- let [v1, v2] = old_edge.vertices(self);
-
- let mut a3 = a1.next(self);
- let mut b3 = b1.prev(self);
-
- if a3.eq(b1, self) {
- a3 = b2;
- }
- if b3.eq(a1, self) {
- b3 = a2;
- }
-
- a2.update_origin(*v, self);
- b1.update_origin(*v, self);
- b2.update_origin(v2, self);
-
- self.follow(a1, a2);
- self.follow(a2, a3);
- self.follow(b3, b2);
- self.follow(b2, b1);
-
- a2.set_loop_(a1.loop_(self), self);
- b2.set_loop_(b1.loop_(self), self);
+ ) -> Result<Kve<'brand, 'arena, V>, OperatorErr<Mve<'brand, 'arena, V>, Infallible>> {
+ Mve::new(edge, data).apply(self)
+ }
- Mve {
- shell,
- old_edge,
- new_edge,
- vertex: v,
- }
+ pub fn kve(
+ &mut self,
+ edge: own!(Edge),
+ vertex: own!(Vertex),
+ ) -> Result<Mve<'brand, 'arena, V>, OperatorErr<Kve<'brand, 'arena, V>, KveError>> {
+ Kve::new(edge, vertex).apply(self)
}
pub fn mekh(
@@ -1029,8 +927,10 @@ fn main() {
let op2 = dcel.mev(*op.loop_, *op.vertices[1], ("E", [4, 0])).unwrap();
let op3 = dcel.mev(*op.loop_, *op2.vertex, ("S", [0, -4])).unwrap();
- dcel.melf(*op.shell, [*op3.vertex, *op.vertices[0]], *op.loop_);
- dcel.melf(*op.shell, [*op.vertices[0], *op2.vertex], *op.loop_);
+ dcel.melf([*op3.vertex, *op.vertices[0]], *op.loop_)
+ .unwrap();
+ dcel.melf([*op.vertices[0], *op2.vertex], *op.loop_)
+ .unwrap();
show("cool_stuff.dot", &dcel);
diff --git a/src/melf.rs b/src/melf.rs
new file mode 100644
index 0000000..2b8df3f
--- /dev/null
+++ b/src/melf.rs
@@ -0,0 +1,174 @@
+use crate::*;
+
+// Make Edge-Vertex
+
+pub struct Melf<'brand, 'arena, V> {
+ pub vertices: [ptr!(Vertex); 2],
+ pub loop_: ptr!(Loop),
+}
+
+impl<'brand, 'arena, V> Melf<'brand, 'arena, V> {
+ pub fn new(vertices: [ptr!(Vertex); 2], loop_: ptr!(Loop)) -> Self {
+ Self { vertices, loop_ }
+ }
+}
+
+#[derive(Debug, Error)]
+pub enum MelfError {
+ #[error("vertex is not part of loop")]
+ VertexLoopMismatch,
+}
+
+impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Melf<'brand, 'arena, V> {
+ type Inverse = Kelf<'brand, 'arena, V>;
+ type Error = MelfError;
+ type Check = [ptr!(HalfEdge); 2];
+
+ fn check(&self, dcel: &Dcel<'brand, 'arena, V>) -> Result<Self::Check, Self::Error> {
+ let b0 = self.vertices[0]
+ .find_outgoing(self.loop_, dcel)
+ .ok_or(MelfError::VertexLoopMismatch)?;
+ let a2 = self.vertices[1]
+ .find_outgoing(self.loop_, dcel)
+ .ok_or(MelfError::VertexLoopMismatch)?;
+
+ Ok([b0, a2])
+ }
+
+ fn apply(
+ self,
+ dcel: &mut Dcel<'brand, 'arena, V>,
+ ) -> Result<Self::Inverse, OperatorErr<Self, Self::Error>> {
+ // before:
+ // > >
+ // a0 \ / a2
+ // v1 v2
+ // b0 / \ b2
+ // < <
+ //
+ // after:
+ // > >
+ // a0 \ a1 -> / a2
+ // v1 v2
+ // b0 / <- b1 \ b2
+ // < <
+ //
+
+ let [b0, a2] = try_check!(self, dcel);
+ let a0 = b0.prev(dcel);
+ let b2 = a2.prev(dcel);
+
+ let old_loop = self.loop_;
+ let [v1, v2] = self.vertices;
+ let shell = old_loop.face(dcel).shell(dcel);
+
+ let (edge, [a1, b1]) = Edge::create(shell, dcel);
+ let face = shell.add_new_face(dcel);
+ let new_loop = Loop::new(dcel); // face.add_new_outer_loop(self);
+ new_loop.set_face(*face, dcel);
+ face.set_outer_loop(*new_loop, dcel);
+
+ a1.update_origin(v1, dcel);
+ dcel.follow(a0, a1);
+ dcel.follow(a1, a2);
+ old_loop.set_half_edges(a1, dcel);
+ a1.set_loop_(old_loop, dcel);
+
+ b1.update_origin(v2, dcel);
+ dcel.follow(b2, b1);
+ dcel.follow(b1, b0);
+ new_loop.set_half_edges(b1, dcel);
+ new_loop.update_connectivity(dcel);
+
+ Ok(Kelf {
+ loop_: new_loop,
+ edge,
+ face,
+ })
+ }
+}
+
+pub struct Kelf<'brand, 'arena, V> {
+ pub edge: own!(Edge),
+ pub loop_: own!(Loop),
+ pub face: own!(Face),
+}
+
+impl<'brand, 'arena, V> Kelf<'brand, 'arena, V> {
+ pub fn new(edge: own!(Edge), loop_: own!(Loop), face: own!(Face)) -> Self {
+ Self { edge, loop_, face }
+ }
+}
+
+#[derive(Debug, Error)]
+pub enum KelfError {
+ #[error("edge is not part of loop")]
+ EdgeLoopMismatch,
+ #[error("loop is not outer loop of face")]
+ FaceLoopMismatch,
+ #[error("face has inner loops")]
+ HasInnerLoops,
+}
+
+impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Kelf<'brand, 'arena, V> {
+ type Inverse = Melf<'brand, 'arena, V>;
+ type Error = KelfError;
+ type Check = [ptr!(HalfEdge); 2];
+
+ fn check(&self, dcel: &Dcel<'brand, 'arena, V>) -> Result<Self::Check, Self::Error> {
+ use KelfError::*;
+
+ let [mut a1, mut b1] = self.edge.lens(dcel).half_edges();
+
+ if a1.loop_().eq(*self.loop_) {
+ [a1, b1] = [b1, a1];
+ }
+
+ or_err(b1.loop_().eq(*self.loop_), EdgeLoopMismatch)?;
+ or_err(
+ self.face.outer_loop(dcel).eq(*self.loop_, dcel),
+ FaceLoopMismatch,
+ )?;
+ or_err(self.face.maybe_inner_loops(dcel).is_none(), HasInnerLoops)?;
+
+ Ok([a1.item, b1.item])
+ }
+
+ fn apply(
+ self,
+ dcel: &mut Dcel<'brand, 'arena, V>,
+ ) -> Result<Self::Inverse, OperatorErr<Self, Self::Error>> {
+ let [a1, b1] = try_check!(self, dcel);
+
+ let Kelf { edge, loop_, face } = self;
+ let shell = face.shell(dcel);
+
+ let a0 = a1.prev(dcel);
+ let b0 = b1.next(dcel);
+ let a2 = a1.next(dcel);
+ let b2 = b1.prev(dcel);
+
+ let v1 = a1.origin(dcel);
+ let v2 = b1.origin(dcel);
+
+ let old_loop = a1.loop_(dcel);
+
+ dcel.follow(a0, b0);
+ dcel.follow(b2, a2);
+
+ old_loop.set_half_edges(a0, dcel);
+ old_loop.update_connectivity(dcel);
+
+ shell.remove_edge(*edge, dcel);
+ shell.remove_face(*face, dcel);
+
+ edge.destroy(dcel);
+ face.free(dcel);
+ loop_.free(dcel);
+
+ Ok(Melf {
+ vertices: [v1, v2],
+ loop_: old_loop,
+ })
+ }
+}
diff --git a/src/mev.rs b/src/mev.rs
index 41a2ceb..5de1ce8 100644
--- a/src/mev.rs
+++ b/src/mev.rs
@@ -128,6 +128,10 @@ impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Kev<'brand, 'arena, V> {
let d = c.prev(dcel);
dcel.follow(d, a);
+ let shell = a.loop_(dcel).face(dcel).shell(dcel);
+ shell.remove_edge(*self.edge, dcel);
+ shell.remove_vertex(*self.vertex, dcel);
+
self.edge.destroy(dcel);
let data = self.vertex.destroy(dcel);
diff --git a/src/msev.rs b/src/msev.rs
index 9abc5a4..16d18e4 100644
--- a/src/msev.rs
+++ b/src/msev.rs
@@ -173,6 +173,9 @@ impl<'brand, 'arena, V> Operator<'brand, 'arena, V> for Ksev<'brand, 'arena, V>
loops[0].set_half_edges(a0, dcel);
loops[1].set_half_edges(b0, dcel);
+ shell.remove_edge(*edge, dcel);
+ shell.remove_vertex(*new_vertex, dcel);
+
edge.destroy(dcel);
let data = new_vertex.destroy(dcel);
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),
+ })
+ }
+}
diff --git a/src/tests.rs b/src/tests.rs
index 5dc0a78..4102add 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -1,4 +1,5 @@
use crate::*;
+use std::collections::HashSet;
#[test]
fn mev_cycle() {
@@ -7,7 +8,8 @@ fn mev_cycle() {
let op = dcel.mevvlfs(*body, [0, 1]).unwrap();
let op2 = dcel.mev(*op.loop_, *op.vertices[1], 2).unwrap();
let op3 = dcel.mev(*op.loop_, *op2.vertex, 3).unwrap();
- dcel.melf(*op.shell, [*op3.vertex, *op.vertices[0]], *op.loop_);
+ dcel.melf([*op3.vertex, *op.vertices[0]], *op.loop_)
+ .unwrap();
let mut vertices = op
.loop_
@@ -23,6 +25,71 @@ fn mev_cycle() {
})
}
+fn assert_verts<'brand, 'arena, V: Eq + Copy + Debug + Hash>(
+ loop_: ptr!(Loop),
+ dcel: &Dcel<'brand, 'arena, V>,
+ want: impl Into<HashSet<V>>,
+) {
+ assert_eq!(
+ loop_
+ .iter_half_edges(dcel)
+ .map(|x| *x.origin().data())
+ .collect::<HashSet<_>>(),
+ want.into()
+ );
+}
+
+#[test]
+fn mev_kve() {
+ Dcel::<u32>::new(|mut dcel| {
+ let body = dcel.new_body();
+ let Kevvlfs {
+ vertices: [v0, v1],
+ edge: old_edge,
+ loop_,
+ ..
+ } = dcel.mevvlfs(*body, [0, 1]).unwrap();
+ assert_verts(*loop_, &dcel, [0, 1]);
+
+ dcel.mev(*loop_, *v1, 2).unwrap();
+ assert_verts(*loop_, &dcel, [0, 1, 2]);
+
+ let undo = dcel.kve(old_edge, v1).unwrap();
+ assert_verts(*loop_, &dcel, [0, 2]);
+
+ undo.apply(&mut dcel).unwrap();
+ assert_verts(*loop_, &dcel, [0, 1, 2]);
+ })
+}
+
+#[test]
+fn mve_kev() {
+ Dcel::<u32>::new(|mut dcel| {
+ let body = dcel.new_body();
+ let Kevvlfs {
+ vertices: [v0, v1],
+ edge: old_edge,
+ loop_,
+ ..
+ } = dcel.mevvlfs(*body, [0, 1]).unwrap();
+ assert_verts(*loop_, &dcel, [0, 1]);
+
+ let mut edge = dcel.mve(*old_edge, 2).unwrap().edge;
+ assert_verts(*loop_, &dcel, [0, 2, 1]);
+
+ let verts = edge.lens(&dcel).vertices();
+ if !verts[0].eq(*v1) && !verts[1].eq(*v1) {
+ edge = old_edge;
+ }
+
+ let undo = dcel.kev(edge, v1).unwrap();
+ assert_verts(*loop_, &dcel, [0, 2]);
+
+ undo.apply(&mut dcel).unwrap();
+ assert_verts(*loop_, &dcel, [0, 2, 1]);
+ })
+}
+
/*
makes this shape:
@@ -51,7 +118,7 @@ fn make_hourglass<'brand, 'arena, V>(
} = dcel.mevvlfs(*body, [d0, d1]).unwrap();
let inner_2 = dcel.mev(*loop_0, *inner_1, d2).unwrap().vertex;
- let mut outer_loop = dcel.melf(*shell, [*inner_0, *inner_2], *loop_0).new_loop;
+ let mut outer_loop = dcel.melf([*inner_0, *inner_2], *loop_0).unwrap().loop_;
let Kev {
vertex: outer_0,
@@ -61,9 +128,7 @@ fn make_hourglass<'brand, 'arena, V>(
let outer_1 = dcel.mev(*outer_loop, *outer_0, d4).unwrap().vertex;
let outer_2 = dcel.mev(*outer_loop, *outer_1, d5).unwrap().vertex;
- let mut loop_2 = dcel
- .melf(*shell, [*outer_0, *outer_2], *outer_loop)
- .new_loop;
+ let mut loop_2 = dcel.melf([*outer_0, *outer_2], *outer_loop).unwrap().loop_;
if edge.lens(dcel).half_edges()[0].loop_().eq(*loop_2) {
[outer_loop, loop_2] = [loop_2, outer_loop];
}
@@ -183,25 +248,25 @@ fn msev_ksev() {
let out_2 = dcel.mev(*loop_0, *out_1, 2).unwrap().vertex;
let out_3 = dcel.mev(*loop_0, *out_2, 3).unwrap().vertex;
- dcel.melf(*shell, [*out_0, *out_3], *loop_0);
+ dcel.melf([*out_0, *out_3], *loop_0).unwrap();
- let Melf {
- new_loop: mut loop_2,
+ let Kelf {
+ loop_: mut loop_2,
edge,
..
- } = dcel.melf(*shell, [*out_0, *out_2], *loop_0);
+ } = dcel.melf([*out_0, *out_2], *loop_0).unwrap();
if out_1.find_outgoing(*loop_0, &dcel).is_none() {
[loop_0, loop_2] = [loop_2, loop_0];
}
- let in_0 = dcel.mve(*shell, *edge, 4).vertex;
+ let in_0 = dcel.mve(*edge, 4).unwrap().vertex;
- let mut loop_1 = dcel.melf(*shell, [*out_1, *in_0], *loop_0).new_loop;
+ let mut loop_1 = dcel.melf([*out_1, *in_0], *loop_0).unwrap().loop_;
if out_0.find_outgoing(*loop_0, &dcel).is_none() {
[loop_0, loop_1] = [loop_1, loop_0];
}
- let mut loop_3 = dcel.melf(*shell, [*out_3, *in_0], *loop_2).new_loop;
+ let mut loop_3 = dcel.melf([*out_3, *in_0], *loop_2).unwrap().loop_;
if out_2.find_outgoing(*loop_2, &dcel).is_none() {
[loop_2, loop_3] = [loop_3, loop_2];
}