#![allow(private_bounds)] use core::ops::Deref; pub use ghost_cell::{GhostBorrow, GhostCell, GhostToken}; use paste::paste; use std::{ convert::Infallible, fmt::{self, Debug, Display, Formatter}, hash::{Hash, Hasher}, }; use thiserror::Error; pub use typed_arena::Arena; macro_rules! try_check { ($this:ident, $dcel:ident) => { match $this.check($dcel) { Ok(x) => x, Err(e) => return Err(OperatorErr::new($this, e)), } }; } #[macro_use] mod entity; use entity::*; mod entity_iterator; pub use entity_iterator::*; mod dot; pub use dot::*; #[cfg(test)] mod tests; mod mevvlfs; pub use mevvlfs::*; mod mekh; pub use mekh::*; pub trait ReflAsRef { fn as_ref(&self) -> &T; } impl ReflAsRef for T { fn as_ref(&self) -> &T { self } } pub trait ReflAsMut: ReflAsRef { fn as_mut(&mut self) -> &mut T; } impl ReflAsMut for T { fn as_mut(&mut self) -> &mut T { self } } struct DisplayFn fmt::Result>(F); impl fmt::Result> Display for DisplayFn { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.0(f) } } impl fmt::Result> Debug for DisplayFn { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.0(f) } } #[macro_export] macro_rules! ptr_t { ($T:ty) => { Ptr<'brand, 'arena, $T> } } #[macro_export] macro_rules! ptr { ($T:ident) => { Ptr<'brand, 'arena, $T<'brand, 'arena, V>> }; } #[macro_export] macro_rules! own_t { ($T:ty) => { Own<'brand, 'arena, $T> } } #[macro_export] macro_rules! own { ($T:ident) => { Own<'brand, 'arena, $T<'brand, 'arena, V>> }; } #[macro_export] macro_rules! lens_t { ($T:ty) => { Lens<'tok, 'brand, 'arena, $T> } } #[macro_export] macro_rules! lens { ($T:ident) => { Lens<'tok, 'brand, 'arena, $T<'brand, 'arena, V>> }; } #[macro_export] macro_rules! mklens { ($token: expr, $($name:ident),*) => { $( let $name = $name.lens($token); )* }; } fn _short_debug(ty: &'static str, id: usize, f: &mut Formatter) -> fmt::Result { f.debug_tuple(ty).field(&id).finish() } fn short_debug<'tok, 'brand, 'arena, T: Entity<'brand, 'arena>>( x: lens_t!(T), f: &mut Formatter, ) -> fmt::Result { _short_debug(T::type_name(), x.id(), f) } fn short_debug_fn<'tok, 'brand, 'arena, T: Entity<'brand, 'arena>>(x: lens_t!(T)) -> impl Debug { let id = x.id(); DisplayFn(move |f| _short_debug(T::type_name(), id, f)) } fn short_debug_list<'tok, 'brand, 'arena, T, I>(iter: I, f: &mut Formatter) -> fmt::Result where 'brand: 'tok + 'arena, T: Entity<'brand, 'arena> + 'arena, I: Iterator, { f.debug_list().entries(iter.map(short_debug_fn)).finish() } fn or_err(cond: bool, err: T) -> Result<(), T> { if cond { Ok(()) } else { Err(err) } } pub struct Ptr<'brand, 'arena, T>(pub &'arena GhostCell<'brand, T>); impl<'brand, 'arena, T> Clone for ptr_t!(T) { fn clone(&self) -> Self { Self(self.0) } } impl<'brand, 'arena, T> Copy for ptr_t!(T) {} impl<'brand, 'arena, T> ptr_t!(T) { pub fn borrow<'tok, 'out>(self, token: &'tok impl ReflAsRef>) -> &'out T where 'arena: 'out, 'tok: 'out, { self.0.borrow(token.as_ref()) } pub fn borrow_mut<'tok, 'out>( self, token: &'tok mut impl ReflAsMut>, ) -> &'out mut T where 'arena: 'out, 'tok: 'out, { self.0.borrow_mut(token.as_mut()) } pub fn lens<'tok>(self, token: &'tok impl ReflAsRef>) -> lens_t!(T) { Lens::new(self, token) } } #[allow(unused)] impl<'brand, 'arena, T: Entity<'brand, 'arena>> ptr_t!(T) { fn clear(self, token: &mut impl ReflAsMut>) { self.borrow_mut(token).clear() } pub fn id(self, token: &impl ReflAsRef>) -> usize { self.borrow(token).id() } fn maybe_id(self, token: &impl ReflAsRef>) -> Option { self.borrow(token).maybe_id() } fn alive(self, token: &impl ReflAsRef>) -> bool { self.borrow(token).alive() } pub fn eq(self, other: Self, token: &impl ReflAsRef>) -> bool { self.borrow(token) == other.borrow(token) } fn next(self, token: &impl ReflAsRef>) -> Self { self.borrow(token).next() } fn maybe_next(self, token: &impl ReflAsRef>) -> Option { self.borrow(token).maybe_next() } fn set_next(self, x: Self, token: &mut impl ReflAsMut>) { self.borrow_mut(token).set_next(x) } fn set_next_opt(self, x: Option, token: &mut impl ReflAsMut>) { self.borrow_mut(token).set_next_opt(x) } fn prev(self, token: &impl ReflAsRef>) -> Self { self.borrow(token).prev() } fn maybe_prev(self, token: &impl ReflAsRef>) -> Option { self.borrow(token).maybe_prev() } fn set_prev(self, x: Self, token: &mut impl ReflAsMut>) { self.borrow_mut(token).set_prev(x) } fn set_prev_opt(self, x: Option, token: &mut impl ReflAsMut>) { self.borrow_mut(token).set_prev_opt(x) } } pub struct Own<'brand, 'arena, T>(ptr_t!(T)); impl<'brand, 'arena, T> Own<'brand, 'arena, T> { // avoid this pub fn unsafe_make_owned(this: ptr_t!(T)) -> Self { Self(this) } } impl<'brand, 'arena, T> Deref for own_t!(T) { type Target = ptr_t!(T); fn deref(&self) -> &Self::Target { &self.0 } } pub struct Lens<'tok, 'brand, 'arena, T> { pub item: ptr_t!(T), pub token: &'tok GhostToken<'brand>, } impl<'tok, 'brand, 'arena, T> Clone for lens_t!(T) { fn clone(&self) -> Self { Self::new(self.item, self.token) } } impl<'tok, 'brand, 'arena, T> Copy for lens_t!(T) {} impl<'tok, 'brand, 'arena, T: PartialEq> PartialEq for lens_t!(T) { fn eq(&self, other: &Self) -> bool { self.item.borrow(self.token) == other.item.borrow(other.token) } } impl<'tok, 'brand, 'arena, T: PartialEq> Eq for lens_t!(T) {} impl<'tok, 'brand, 'arena, T> ReflAsRef> for lens_t!(T) { fn as_ref(&self) -> &GhostToken<'brand> { &self.token } } impl<'tok, 'brand, 'arena, T> From for ptr_t!(T) { fn from(x: lens_t!(T)) -> Self { x.item } } impl<'tok, 'brand, 'arena, T> lens_t!(T) { pub fn new(item: ptr_t!(T), token: &'tok impl ReflAsRef>) -> Self { Self { item, token: token.as_ref(), } } } #[allow(unused)] impl<'tok, 'brand, 'arena, T: Entity<'brand, 'arena>> lens_t!(T) { pub fn id(self) -> usize { self.item.id(&self) } fn maybe_id(self) -> Option { self.item.maybe_id(&self) } fn alive(self) -> bool { self.item.alive(&self) } pub fn eq(self, other: ptr_t!(T)) -> bool { self.item.eq(other, &self) } fn next(self) -> Self { self.item.next(&self).lens(self.token) } fn maybe_next(self) -> Option { self.item.maybe_next(&self).map(|x| x.lens(self.token)) } fn prev(self) -> Self { self.item.prev(self.token).lens(self.token) } fn maybe_prev(self) -> Option { self.item.maybe_prev(&self).map(|x| x.lens(self.token)) } } entity!(vertex: Vertex (init: V), data: Option = Some(init); outgoing: HalfEdge ); pub struct OutgoingIterator<'tok, 'brand, 'arena, V>(Option<(lens!(HalfEdge), lens!(HalfEdge))>); impl<'tok, 'brand, 'arena, V> Clone for OutgoingIterator<'tok, 'brand, 'arena, V> { fn clone(&self) -> Self { Self(self.0) } } impl<'tok, 'brand, 'arena, V> Copy for OutgoingIterator<'tok, 'brand, 'arena, V> {} impl<'tok, 'brand, 'arena, V> OutgoingIterator<'tok, 'brand, 'arena, V> { fn new(start: Option, token: &'tok impl ReflAsRef>) -> Self { Self(start.map(|s| { let l = Lens::new(s, token); (l, l) })) } } impl<'tok, 'brand, 'arena, V> Iterator for OutgoingIterator<'tok, 'brand, 'arena, V> { type Item = lens!(HalfEdge); fn next(&mut self) -> Option { let range = self.0.as_mut()?; let ret = range.0; range.0 = range.0.twin().next(); if range.0 == range.1 { self.0 = None; } Some(ret) } } impl<'brand, 'arena, V> own!(Vertex) { fn destroy(self, dcel: &mut Dcel<'brand, 'arena, V>) -> V { let data = self.borrow_mut(dcel).data.take().unwrap(); self.free(dcel); data } } impl<'brand, 'arena, V> ptr!(Vertex) { pub fn data<'tok, 'out>(self, token: &'tok impl ReflAsRef>) -> &'out V where 'arena: 'out, 'tok: 'out, { self.borrow(token).data.as_ref().unwrap() } pub fn mut_data<'tok, 'out>( self, token: &'tok mut impl ReflAsMut>, ) -> &'out mut V where 'arena: 'out, 'tok: 'out, { self.borrow_mut(token).data.as_mut().unwrap() } pub fn iter_outgoing<'tok>( self, token: &'tok impl ReflAsRef>, ) -> OutgoingIterator<'tok, 'brand, 'arena, V> { // FIXME: maybe enforce at least one item by using .outgoing() // there should be no "standalone" vertices (?) OutgoingIterator::new(self.maybe_outgoing(token), token) } pub fn find_outgoing( self, loop_: ptr!(Loop), token: &impl ReflAsRef>, ) -> Option { self.lens(token).find_outgoing(loop_).map(|x| x.item) } } impl<'tok, 'brand, 'arena, V> lens!(Vertex) { pub fn data(&self) -> &V { self.item.data(self) } pub fn iter_outgoing(self) -> OutgoingIterator<'tok, 'brand, 'arena, V> { self.item.iter_outgoing(self.token) } pub fn find_outgoing(self, loop_: ptr!(Loop)) -> Option { self.iter_outgoing().find(|x| x.loop_().eq(loop_)) } fn debug_data(self, f: &mut Formatter) -> fmt::Result where V: Debug, { self.data().fmt(f) } } // TODO: target entity!(half_edge: HalfEdge; pub origin: Vertex, pub twin: HalfEdge, pub loop_: Loop, pub edge: Edge ); impl<'brand, 'arena, V> ptr!(HalfEdge) { pub fn target(self, token: &impl ReflAsRef>) -> ptr!(Vertex) { self.twin(token).origin(token) } fn update_origin(self, v: ptr!(Vertex), token: &mut impl ReflAsMut>) { self.set_origin(v, token); v.set_outgoing(self, token); } } impl<'tok, 'brand, 'arena, V> lens!(HalfEdge) { pub fn target(self) -> lens!(Vertex) { self.item.target(&self).lens(self.token) } } entity!(loop_: Loop; half_edges[half_edge: half_edge back]: HalfEdge, pub face: Face ); impl<'brand, 'arena, V> ptr!(Loop) { pub fn is_outer(self, token: &impl ReflAsRef>) -> bool { self.lens(token).is_outer() } fn update_connectivity(self, token: &mut impl ReflAsMut>) { self.iter_mut_half_edges(token, |x, token| x.set_loop_(self, token)); } } impl<'tok, 'brand, 'arena, V> lens!(Loop) { pub fn is_outer(self) -> bool { self.face().outer_loop() == self } } entity!(edge: Edge, half_edges: Option<[own!(HalfEdge); 2]> = None ); impl<'brand, 'arena, V> Edge<'brand, 'arena, V> { fn create( shell: ptr!(Shell), dcel: &mut Dcel<'brand, 'arena, V>, ) -> (own!(Edge), [ptr!(HalfEdge); 2]) { let edge = shell.add_new_edge(dcel); let he1_own = HalfEdge::new(dcel); let he2_own = HalfEdge::new(dcel); let he1 = *he1_own; let he2 = *he2_own; edge.borrow_mut(dcel).half_edges = Some([he1_own, he2_own]); // edge.set_half_edges([he1_own, he2_own], dcel); he1.set_twin(he2, dcel); he2.set_twin(he1, dcel); he1.set_edge(*edge, dcel); he2.set_edge(*edge, dcel); (edge, [he1, he2]) } } impl<'brand, 'arena, V> own!(Edge) { fn destroy(self, dcel: &mut Dcel<'brand, 'arena, V>) { let [a, b] = self.borrow_mut(dcel).half_edges.take().unwrap(); self.free(dcel); a.free(dcel); b.free(dcel); } } impl<'brand, 'arena, V> ptr!(Edge) { pub fn half_edges(self, token: &impl ReflAsRef>) -> [ptr!(HalfEdge); 2] { let he = self.borrow(token).half_edges.as_ref().unwrap(); [*he[0], *he[1]] } pub fn vertices(self, token: &impl ReflAsRef>) -> [ptr!(Vertex); 2] { self.half_edges(token).map(|x| x.origin(token)) } /* fn set_half_edges( self, x: [own!(HalfEdge); 2], token: &mut impl ReflAsMut>, ) { self.borrow_mut(token).half_edges = Some(x); }*/ } impl<'tok, 'brand, 'arena, V> lens!(Edge) { pub fn half_edges(self) -> [lens!(HalfEdge); 2] { self.item.half_edges(self.token).map(|x| x.lens(self.token)) } pub fn vertices(self) -> [lens!(Vertex); 2] { self.item.vertices(self.token).map(|x| x.lens(self.token)) } fn debug_half_edges(self, f: &mut Formatter) -> fmt::Result where V: Debug, { f.debug_list().entries(self.half_edges()).finish() } } entity!(face: Face; pub outer_loop: Loop, inner_loops[inner_loop: loop_ back]: Loop, pub shell: Shell ); entity!(shell: Shell; faces[face: face back]: Face, edges[edge: edge]: Edge, vertices[vertex: vertex (V)]: Vertex, pub body: Body ); entity!(body: Body; shells[shell: shell back]: Shell ); struct Allocator<'brand, 'arena, T: Entity<'brand, 'arena>> { next_id: usize, arena: &'arena Arena, freelist: Vec, } impl<'brand, 'arena, T: Entity<'brand, 'arena>> Allocator<'brand, 'arena, T> { fn new(arena: &'arena Arena) -> Self { Self { next_id: 0, arena, freelist: Vec::new(), } } fn next_id(&mut self) -> usize { let id = self.next_id; self.next_id += 1; id } fn alloc(&mut self, x: T, token: &mut impl ReflAsMut>) -> own_t!(T) { if let Some(ptr) = self.freelist.pop() { *ptr.borrow_mut(token) = x; ptr } else { Own::unsafe_make_owned(Ptr(GhostCell::from_mut(self.arena.alloc(x)))) } } fn free(&mut self, token: &mut impl ReflAsMut>, ptr: own_t!(T)) { debug_assert!(ptr.alive(token), "double free"); ptr.clear(token); self.freelist.push(ptr); } } 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 Mev<'brand, 'arena, V> { pub shell: ptr!(Shell), pub loop_: ptr!(Loop), pub old_vertex: ptr!(Vertex), pub new_vertex: own!(Vertex), pub edge: own!(Edge), } 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 { pub op: T, pub err: E, } impl OperatorErr { pub fn new(op: T, err: E) -> Self { Self { op, err } } } impl std::error::Error for OperatorErr {} impl Debug for OperatorErr { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.err.fmt(f) } } impl Display for OperatorErr { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.err.fmt(f) } } pub trait Operator<'brand, 'arena, V>: Sized { type Inverse; //: Operator<'brand, 'arena, V>; type Error: std::error::Error; type Check; fn check(&self, dcel: &Dcel<'brand, 'arena, V>) -> Result; fn apply( self, dcel: &mut Dcel<'brand, 'arena, V>, ) -> Result>; } pub struct DcelArena<'brand, 'arena, V> { pub vertex: Arena>, pub half_edge: Arena>, pub loop_: Arena>, pub edge: Arena>, pub face: Arena>, pub shell: Arena>, pub body: Arena>, } impl<'brand, 'arena, V> Default for DcelArena<'brand, 'arena, V> { fn default() -> Self { Self { vertex: Default::default(), half_edge: Default::default(), loop_: Default::default(), edge: Default::default(), face: Default::default(), shell: Default::default(), body: Default::default(), } } } pub struct Dcel<'brand, 'arena, V> { pub token: GhostToken<'brand>, vertex: Allocator<'brand, 'arena, Vertex<'brand, 'arena, V>>, half_edge: Allocator<'brand, 'arena, HalfEdge<'brand, 'arena, V>>, loop_: Allocator<'brand, 'arena, Loop<'brand, 'arena, V>>, edge: Allocator<'brand, 'arena, Edge<'brand, 'arena, V>>, face: Allocator<'brand, 'arena, Face<'brand, 'arena, V>>, shell: Allocator<'brand, 'arena, Shell<'brand, 'arena, V>>, body: Allocator<'brand, 'arena, Body<'brand, 'arena, V>>, bodies: Option, } impl<'brand, 'arena, V> ReflAsRef> for Dcel<'brand, 'arena, V> { fn as_ref(&self) -> &GhostToken<'brand> { &self.token } } impl<'brand, 'arena, V> ReflAsMut> for Dcel<'brand, 'arena, V> { fn as_mut(&mut self) -> &mut GhostToken<'brand> { &mut self.token } } impl<'brand, 'arena, V> Dcel<'brand, 'arena, V> { pub fn from_token(token: GhostToken<'brand>, ar: &'arena DcelArena<'brand, 'arena, V>) -> Self { Self { token, bodies: None, vertex: Allocator::new(&ar.vertex), half_edge: Allocator::new(&ar.half_edge), loop_: Allocator::new(&ar.loop_), edge: Allocator::new(&ar.edge), face: Allocator::new(&ar.face), shell: Allocator::new(&ar.shell), body: Allocator::new(&ar.body), } } pub fn new(fun: F) -> R where for<'new_brand, 'new_arena> F: FnOnce(Dcel<'new_brand, 'new_arena, W>) -> R, { GhostToken::new(|token| { let arena = DcelArena::default(); let dcel = Dcel::from_token(token, &arena); fun(dcel) }) } pub fn new_body(&mut self) -> own!(Body) { let body = Body::new(self); self.bodies = Some(Entity::list_add(*body, self.bodies, self)); body } pub fn delete_body(&mut self, body: own!(Body)) { self.bodies = Entity::list_remove(*body, self); body.free(self); } pub fn iter_bodies<'tok>( &'tok self, ) -> EntityIterator<'tok, 'brand, 'arena, Body<'brand, 'arena, V>> { EntityIterator::new(self.bodies, self) } // fn new_edge(&mut self, shell: ptr!(Shell)) -> (own!(Edge), [ptr!(HalfEdge); 2]) {} fn follow(&mut self, prev: ptr!(HalfEdge), next: ptr!(HalfEdge)) { next.set_prev(prev, self); prev.set_next(next, self); } pub fn mevvlfs( &mut self, body: ptr!(Body), data: [V; 2], ) -> Result, OperatorErr, Infallible>> { Mevvlfs::new(body, data).apply(self) } pub fn kevvlfs( &mut self, body: ptr!(Body), edge: own!(Edge), vertices: [own!(Vertex); 2], loop_: own!(Loop), face: own!(Face), shell: own!(Shell), ) -> Result, OperatorErr, KevvlfsError>> { Kevvlfs::new(body, edge, vertices, loop_, face, shell).apply(self) } pub fn mev( &mut self, shell: ptr!(Shell), loop_: ptr!(Loop), old_vertex: ptr!(Vertex), data: V, ) -> Mev<'brand, 'arena, V> { // // o // a / \ d // < < // // < n < // b | | c // o // a / \ d // < < let (edge, [b, c]) = Edge::create(shell, self); let new_vertex = shell.add_new_vertex(data, self); let a = old_vertex.find_outgoing(loop_, self).unwrap(); let d = a.prev(self); self.follow(d, c); self.follow(c, b); self.follow(b, a); b.set_loop_(loop_, self); c.set_loop_(loop_, self); b.update_origin(*new_vertex, self); c.update_origin(old_vertex, self); Mev { shell, loop_, old_vertex, new_vertex, edge, } } 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, } } pub fn mve( &mut self, shell: ptr!(Shell), old_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 = b2.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); Mve { shell, old_edge, new_edge, vertex: v, } } pub fn mekh( &mut self, shell: ptr!(Shell), into_loop: ptr!(Loop), into_vertex: ptr!(Vertex), hole_loop: own!(Loop), hole_vertex: ptr!(Vertex), ) -> Result, OperatorErr, MekhError>> { Mekh::new(shell, into_loop, into_vertex, hole_loop, hole_vertex).apply(self) } pub fn kemh( &mut self, shell: ptr!(Shell), edge: own!(Edge), loop_: ptr!(Loop), hole_vertex: ptr!(Vertex), ) -> Result, OperatorErr, KemhError>> { Kemh::new(shell, edge, loop_, hole_vertex).apply(self) } /* pub fn mekh( &mut self, ) -> Result, MekhError> { let face = loops[0].0.face(self); assert!(loops[1].0.lens(self).face().eq(face)); let outer = loops.map(|(l, _)| face.lens(self).outer_loop().eq(l)); if outer[0] && outer[1] { panic!("cannot connect outer loops"); } if outer[1] { loops = [loops[1], loops[0]]; } let [b0, a2] = loops.map(|(l, v)| v.find_outgoing(l, self).unwrap()); let (edge, [a1, b1]) = self.new_edge(shell); let a0 = b0.prev(self); let b2 = a2.prev(self); self.origin(loops[0].1, a1); self.follow(a0, a1); self.follow(a1, a2); self.origin(loops[1].1, b1); self.follow(b2, b1); self.follow(b1, b0); loops[0] .0 .iter_mut_half_edges(self, |x, dcel| x.set_loop_(loops[0].0, dcel)); face.remove_inner_loop(loops[1].0, self); from_loop.free(self); Ok(Mekh { shell }) } */ } use std::io::Write; fn main() { let show = |name, dcel: &Dcel<(&'static str, [i64; 2])>| { write!( &mut std::fs::File::create(name).unwrap(), "{}", DisplayFn(|f: &mut fmt::Formatter<'_>| dcel_write_dot( dcel, |v| v.1.map(|x| x as _), |v, f| write!(f, "{}", v.0), f, DcelDotOptions { prev: false, next: true, twin: true, } )) ) .unwrap(); }; GhostToken::new(|token| { let arena = DcelArena::default(); let mut dcel = Dcel::from_token(token, &arena); let body = dcel.new_body(); // Mevvlfs(a, [w, n], l, f, s) //let op = dcel.mevvlfs(*body, [("W", [-4, 0]), ("N", [0, 4])]); let op = dcel .mevvlfs(*body, [("W", [-4, 0]), ("N", [0, 4])]) .unwrap(); let op2 = dcel.mev(*op.shell, *op.loop_, *op.vertices[1], ("E", [4, 0])); let op3 = dcel.mev(*op.shell, *op.loop_, *op2.new_vertex, ("S", [0, -4])); dcel.melf(*op.shell, [*op3.new_vertex, *op.vertices[0]], *op.loop_); dcel.melf(*op.shell, [*op.vertices[0], *op2.new_vertex], *op.loop_); show("cool_stuff.dot", &dcel); /*println!("{:?}", op.edge.lens(&dcel)); println!("{:?}", op.vertices[0].lens(&dcel)); println!("{:?}", op.vertices[1].lens(&dcel)); println!("{:?}", op.loop_.lens(&dcel)); println!("{:?}", op.face.lens(&dcel)); println!("{:?}", op.shell.lens(&dcel));*/ //dbg!(body.lens(&dcel)); // dcel.undo(op); /* let (a, [w, n], _) = dcel.mevvls([("W", [-4, 0]), ("N", [0, 4])]); show("1.dot", &dcel); let b = dcel.mve(a, ("E", [4, 0])).unwrap().0; show("2.dot", &dcel); dcel.mve(a, ("S", [0, -4])).unwrap(); show("3.dot", &dcel); //dcel.mel(w, n); show("4.dot", &dcel);*/ /* eprintln!( "{} {}", a.borrow(&dcel.token).id.unwrap(), b.borrow(&dcel.token).id.unwrap() );*/ /* print!( "{}", "{}", layFn(|f: &mut fmt::Formatter<'_>| { v in dcel.vertices.elements.iter() { } h in dcel.half_edges.elements.iter() { } Ok(()) }) }) );*/ }); }