use std::{
fmt,
marker::PhantomData,
mem,
ops,
slice,
};
use optional::Optioned as Opt;
use typebool::True;
use crate::{
hsize,
prelude::*,
map::{DenseMap, set::DenseSet},
};
use super::{
Checked, OptionalField, StoreField, TriFaces, FaceKind, PolyFaces, SplitEdgeWithFacesResult,
util::FieldStorage,
};
use self::adj::{CwVertexCirculator, FaceCirculator};
mod adj;
#[cfg(test)]
mod tests;
const NON_MANIFOLD_VERTEX_ERR: &str =
"new face would add a non-manifold vertex (no hole found in cycle)";
const NON_MANIFOLD_EDGE_ERR: &str =
"new face would add a non-manifold edge";
pub trait Config: 'static {
type FaceKind: FaceKind;
type PrevEdge: OptionalField;
}
#[allow(missing_debug_implementations)]
pub enum PolyConfig {}
impl Config for PolyConfig {
type FaceKind = PolyFaces;
type PrevEdge = StoreField;
}
#[allow(missing_debug_implementations)]
pub enum TriConfig {}
impl Config for TriConfig {
type FaceKind = TriFaces;
type PrevEdge = StoreField;
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
struct HalfEdgeHandle(hsize);
impl HalfEdgeHandle {
#[inline(always)]
fn lower_half_of(edge: EdgeHandle) -> Self {
Self(edge.idx() * 2)
}
#[inline(always)]
fn full_edge(self) -> EdgeHandle {
EdgeHandle::new(self.0 / 2)
}
}
impl Handle for HalfEdgeHandle {
#[inline(always)]
fn new(id: hsize) -> Self {
HalfEdgeHandle(id)
}
#[inline(always)]
fn idx(&self) -> hsize {
self.0
}
}
impl Checked<HalfEdgeHandle> {
#[inline(always)]
fn twin(self) -> Checked<HalfEdgeHandle> {
unsafe { Self::new(HalfEdgeHandle::new(self.idx() ^ 1)) }
}
}
impl fmt::Debug for HalfEdgeHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "HE{}", self.idx())
}
}
#[doc = include_str!("diagram.svg")]
#[derive(Empty)]
pub struct HalfEdgeMesh<C: Config = PolyConfig> {
vertices: DenseMap<VertexHandle, Vertex>,
faces: DenseMap<FaceHandle, Face>,
half_edges: DenseMap<HalfEdgeHandle, HalfEdge<C>>,
cache: Box<OpCache>,
_config: PhantomData<C>,
}
#[derive(Empty)]
struct OpCache {
inner_half_edges: Vec<Checked<HalfEdgeHandle>>,
}
#[derive(Clone, Copy)]
pub(crate) struct Face {
edge: Checked<HalfEdgeHandle>,
}
#[derive(Clone, Copy)]
pub(crate) struct Vertex {
outgoing: Opt<Checked<HalfEdgeHandle>>,
}
struct HalfEdge<C: Config> {
face: Opt<Checked<FaceHandle>>,
target: Checked<VertexHandle>,
next: Checked<HalfEdgeHandle>,
prev: <C::PrevEdge as OptionalField>::Storage<Checked<HalfEdgeHandle>>,
}
impl<C: Config> Copy for HalfEdge<C> {}
impl<C: Config> Clone for HalfEdge<C> {
fn clone(&self) -> Self {
Self {
face: self.face.clone(),
target: self.target.clone(),
next: self.next.clone(),
prev: self.prev.clone(),
}
}
}
impl<C: Config> fmt::Debug for HalfEdgeMesh<C> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("HalfEdgeMesh")
.field("vertices", &self.vertices)
.field("faces", &self.faces)
.field("half_edges", &self.half_edges)
.finish()
}
}
impl<C: Config> Clone for HalfEdgeMesh<C> {
fn clone(&self) -> Self {
Self {
vertices: self.vertices.clone(),
faces: self.faces.clone(),
half_edges: self.half_edges.clone(),
cache: Box::new(OpCache::empty()),
_config: PhantomData,
}
}
}
impl fmt::Debug for Vertex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Vertex {{ outgoing: {:?} }}", self.outgoing)
}
}
impl fmt::Debug for Face {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Face {{ edge: {:?} }}", self.edge)
}
}
impl<C: Config> fmt::Debug for HalfEdge<C> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let prev = self.prev.into_option()
.map(|prev| format!(" prev: {:6}", format!("{:?},", prev)))
.unwrap_or("".into());
write!(
f,
"HalfEdge {{ target: {:5} next: {:6}{} face: {:?} }}",
format!("{:?},", self.target),
format!("{:?},", self.next),
prev,
self.face,
)
}
}
macro_rules! set_next_prev {
($mesh:ident, $prev:tt -> $next:tt) => {{
$mesh[$prev].next = $next;
$mesh[$next].prev = $prev.into();
}};
}
impl<C: Config> HalfEdgeMesh<C> {
fn check_face(&self, fh: FaceHandle) -> Checked<FaceHandle> {
if self.faces.contains_handle(fh) {
unsafe { Checked::new(fh) }
} else {
panic!(
"{:?} was passed to a half edge mesh, but this face does not exist in this mesh",
fh,
);
}
}
fn check_vertex(&self, vh: VertexHandle) -> Checked<VertexHandle> {
if self.vertices.contains_handle(vh) {
unsafe { Checked::new(vh) }
} else {
panic!(
"{:?} was passed to a half edge mesh, but this vertex does not exist in this mesh",
vh,
);
}
}
fn checked_half_of(&self, eh: EdgeHandle) -> Checked<HalfEdgeHandle> {
let heh = HalfEdgeHandle::lower_half_of(eh);
if self.half_edges.contains_handle(heh) {
unsafe { Checked::new(heh) }
} else {
panic!(
"{:?} was passed to a half edge mesh, but this edge does not exist in this mesh",
eh,
);
}
}
fn circulate_around_face(&self, center: Checked<FaceHandle>) -> FaceCirculator<'_, C> {
let start_he = self[center].edge;
FaceCirculator::NonEmpty {
mesh: self,
current_he: start_he,
start_he,
}
}
fn circulate_around_vertex(&self, center: Checked<VertexHandle>) -> CwVertexCirculator<'_, C> {
match self[center].outgoing.into_option() {
None => CwVertexCirculator::Empty,
Some(start_he) => CwVertexCirculator::new(self, start_he),
}
}
fn he_between(
&self,
from: Checked<VertexHandle>,
to: Checked<VertexHandle>,
) -> Option<Checked<HalfEdgeHandle>> {
self.circulate_around_vertex(from)
.find(|&outgoing| self[outgoing].target == to)
}
fn prev(&self, he: Checked<HalfEdgeHandle>) -> Checked<HalfEdgeHandle> {
match self[he].prev.into_option() {
Some(prev) => prev,
None => {
self.find_incoming_he(he.twin(), |incoming| self[incoming].next == he)
.expect("internal HEM error: could not find `prev` half edge")
}
}
}
#[inline(always)]
fn find_incoming_he(
&self,
start_edge: Checked<HalfEdgeHandle>,
mut predicate: impl FnMut(Checked<HalfEdgeHandle>) -> bool,
) -> Option<Checked<HalfEdgeHandle>> {
let mut incoming = start_edge;
loop {
if predicate(incoming) {
return Some(incoming);
}
let next = self[incoming].next.twin();
if next == start_edge {
return None;
}
incoming = next;
}
}
unsafe fn add_edge_partially(
&mut self,
from: Checked<VertexHandle>,
to: Checked<VertexHandle>,
) -> Checked<HalfEdgeHandle> {
let face = Opt::none();
let next = Checked::new(HalfEdgeHandle::new(0));
let prev = Checked::new(HalfEdgeHandle::new(0)).into();
self.half_edges.push(HalfEdge { target: from, face, next, prev });
let out = self.half_edges.push(HalfEdge { target: to, face, next, prev });
Checked::new(out)
}
fn add_face_impl<'a>(
&mut self,
vertices: &'a [VertexHandle],
inner_half_edges: &mut [Checked<HalfEdgeHandle>],
) -> FaceHandle {
for &vh in vertices {
self.check_vertex(vh);
}
let vertices = unsafe {
slice::from_raw_parts::<'a>(
vertices.as_ptr() as *const Checked<VertexHandle>,
vertices.len(),
)
};
let mut last_edge: Option<Checked<HalfEdgeHandle>> = None;
for vi in 0..vertices.len() {
let from = vertices[vi];
let to = vertices[(vi + 1) % vertices.len()];
let he = if let Some(last_edge) = last_edge {
let mut outgoing = self[last_edge].next;
loop {
if self[outgoing].target == to {
break Some(outgoing);
}
let ingoing = outgoing.twin();
if ingoing == last_edge {
break None;
}
outgoing = self[ingoing].next;
}
} else {
self.he_between(from, to)
};
last_edge = he;
if let Some(he) = he {
assert!(self[he].face.is_none(), "{}", NON_MANIFOLD_EDGE_ERR);
}
let he = he.unwrap_or_else(|| unsafe { self.add_edge_partially(from, to) });
inner_half_edges[vi] = he;
}
let new_face = self.faces.push(Face {
edge: inner_half_edges[0], });
let new_face = unsafe { Checked::new(new_face) };
for he in &*inner_half_edges {
self[*he].face = Opt::some(new_face);
}
for vi in 0..vertices.len() {
let prev_idx = vi.checked_sub(1).unwrap_or(vertices.len() - 1);
let vh = vertices[vi];
let incoming = inner_half_edges[vi].twin();
let outgoing = inner_half_edges[prev_idx].twin();
let v = &self[vh];
let incoming_face = self[incoming].face;
let outgoing_face = self[outgoing].face;
match (incoming_face.is_some(), outgoing_face.is_some()) {
(false, false) => {
if let Some(outgoing_from_v) = v.outgoing.into_option() {
let end = self.find_incoming_he(
outgoing_from_v.twin(),
|incoming| self[incoming].face.is_none(),
).expect(NON_MANIFOLD_VERTEX_ERR);
let start = self[end].next;
set_next_prev!(self, incoming -> start);
set_next_prev!(self, end -> outgoing);
} else {
set_next_prev!(self, incoming -> outgoing);
self[vh].outgoing = Opt::some(outgoing);
}
}
(true, false) => {
let before_new = self.prev(incoming.twin());
set_next_prev!(self, before_new -> outgoing);
self[vh].outgoing = Opt::some(outgoing);
}
(false, true) => {
let blade_start = self[outgoing.twin()].next;
set_next_prev!(self, incoming -> blade_start);
}
(true, true) => {
let ib_end_opt = self.find_incoming_he(
incoming,
|incoming| self[incoming].face.is_none(),
);
if self[outgoing.twin()].next != incoming.twin() {
let ib_end = ib_end_opt.expect("internal HEM error: cannot find `ib_end`");
let bib_end = self.prev(incoming.twin());
let after_ib = self[ib_end].next;
set_next_prev!(self, bib_end -> after_ib);
let aob_start = self[outgoing.twin()].next;
set_next_prev!(self, ib_end -> aob_start);
self[vh].outgoing = Opt::some(aob_start);
} else {
if let Some(ib_end) = ib_end_opt {
let new_outgoing = self[ib_end].next;
self[vh].outgoing = Opt::some(new_outgoing);
}
}
}
}
}
for he_i in 0..inner_half_edges.len() {
let curr = inner_half_edges[he_i];
let next = inner_half_edges[(he_i + 1) % inner_half_edges.len()];
set_next_prev!(self, curr -> next);
}
*new_face
}
}
macro_rules! impl_index {
($handle:ident, $field:ident, |$c:ident| $out:ty) => {
impl<$c: Config> ops::Index<Checked<$handle>> for HalfEdgeMesh<$c> {
type Output = $out;
#[inline(always)]
fn index(&self, idx: Checked<$handle>) -> &Self::Output {
unsafe { self.$field.get_unchecked(*idx) }
}
}
impl<$c: Config> ops::IndexMut<Checked<$handle>> for HalfEdgeMesh<$c> {
#[inline(always)]
fn index_mut(&mut self, idx: Checked<$handle>) -> &mut Self::Output {
unsafe { self.$field.get_unchecked_mut(*idx) }
}
}
}
}
impl_index!(VertexHandle, vertices, |C| Vertex);
impl_index!(FaceHandle, faces, |C| Face);
impl_index!(HalfEdgeHandle, half_edges, |C| HalfEdge<C>);
impl<C: Config> Mesh for HalfEdgeMesh<C> {
type FaceKind = C::FaceKind;
type Orientable = True;
fn num_vertices(&self) -> hsize {
self.vertices.num_elements()
}
fn next_vertex_handle_from(&self, start: VertexHandle) -> Option<VertexHandle> {
(start.idx()..self.vertices.next_push_handle().idx())
.map(VertexHandle::new)
.find(|&vh| self.vertices.contains_handle(vh))
}
fn next_face_handle_from(&self, start: FaceHandle) -> Option<FaceHandle> {
(start.idx()..self.faces.next_push_handle().idx())
.map(FaceHandle::new)
.find(|&fh| self.faces.contains_handle(fh))
}
fn last_vertex_handle(&self) -> Option<VertexHandle> {
self.vertices.last_handle()
}
fn last_face_handle(&self) -> Option<FaceHandle> {
self.faces.last_handle()
}
fn contains_vertex(&self, vertex: VertexHandle) -> bool {
self.vertices.contains_handle(vertex)
}
fn num_faces(&self) -> hsize {
self.faces.num_elements()
}
fn contains_face(&self, face: FaceHandle) -> bool {
self.faces.contains_handle(face)
}
fn num_edges(&self) -> hsize
where
Self: EdgeMesh,
{
self.half_edges.num_elements() / 2
}
fn next_edge_handle_from(&self, start: EdgeHandle) -> Option<EdgeHandle>
where
Self: EdgeMesh,
{
let mut idx = HalfEdgeHandle::lower_half_of(start).idx();
let end = self.half_edges.next_push_handle().idx();
while idx < end {
let he = HalfEdgeHandle::new(idx);
if self.half_edges.contains_handle(he) {
return Some(he.full_edge());
}
idx += 2;
}
None
}
fn last_edge_handle(&self) -> Option<EdgeHandle>
where
Self: EdgeMesh,
{
self.half_edges.last_handle().map(|he| he.full_edge())
}
fn contains_edge(&self, edge: EdgeHandle) -> bool
where
Self: EdgeMesh,
{
let he = HalfEdgeHandle::lower_half_of(edge);
self.half_edges.contains_handle(he)
}
fn check_integrity(&self) {
for (vh, v) in self.vertices.iter() {
if let Some(outgoing) = v.outgoing.into_option() {
if !self.half_edges.contains_handle(*outgoing) {
panic!(
"bug (broken reference): [{:?}].outgoing = Some({:?}), but that \
half edge does not exist!",
vh,
outgoing,
);
}
if *self[outgoing.twin()].target != vh {
panic!(
"bug: [{:?}].outgoing = Some({:?}), but [{:?}.twin()].target = {:?} \
(should be {:?})",
vh,
*outgoing,
*outgoing,
*self[outgoing.twin()].target,
vh,
);
}
}
}
for (fh, f) in self.faces.iter() {
if !self.half_edges.contains_handle(*f.edge) {
panic!(
"bug (broken reference): [{:?}].edge = {:?}, but that \
half edge does not exist!",
fh,
*f.edge,
);
}
if self[f.edge].face.into_option().map(|h| *h) != Some(fh) {
panic!(
"bug: [{:?}].edge = {:?}, but [{:?}].face = {:?} (should be {:?})",
fh,
*f.edge,
*f.edge,
self[f.edge].face,
fh,
);
}
}
for (heh, he) in self.half_edges.iter() {
if let Some(face) = he.face.into_option() {
if !self.faces.contains_handle(*face) {
panic!(
"bug (broken reference): [{:?}].face = {:?}, but that face does not exist!",
heh,
*face,
);
}
}
if !self.vertices.contains_handle(*he.target) {
panic!(
"bug (broken reference): [{:?}].target = {:?}, but that vertex \
does not exist!",
heh,
*he.target,
);
}
if !self.half_edges.contains_handle(*he.next) {
panic!(
"bug (broken reference): [{:?}].next = {:?}, but that \
half edge does not exist!",
heh,
*he.next,
);
}
if let Some(prev) = he.prev.into_option() {
if !self.half_edges.contains_handle(*prev) {
panic!(
"bug (broken reference): [{:?}].prev = {:?}, but that \
half edge does not exist!",
heh,
*prev,
);
}
if *self[prev].next != heh {
panic!(
"bug: [{:?}].prev = {:?}, but [{:?}].next = {:?} (should be {:?})",
heh,
*prev,
*prev,
self[prev].next,
heh,
);
}
}
}
let mut visited = DenseSet::with_capacity(self.half_edges.num_elements());
for start in self.half_edges.handles() {
if visited.contains_handle(start) {
continue;
}
let face = self.half_edges[start].face;
let mut heh = start;
loop {
if self.half_edges[heh].face != face {
panic!(
"bug: while iterating around {:?} starting from {:?}, {:?} was \
encountered and its face is {:?}",
face,
start,
heh,
self.half_edges[heh].face,
);
}
if visited.insert(heh) {
panic!(
"bug: encountered {:?} while iterating around {:?}, but we \
already visited it!",
heh,
face,
);
}
heh = *self.half_edges[heh].next;
if heh == start {
break;
}
}
}
let mut visited = DenseSet::with_capacity(self.half_edges.num_elements());
for start in self.half_edges.handles() {
if visited.contains_handle(start) {
continue;
}
let vertex = self.half_edges[start].target;
let mut heh = start;
loop {
if self.half_edges[heh].target != vertex {
panic!(
"bug: while iterating around {:?} starting from {:?}, {:?} was \
encountered and its target is {:?}",
vertex,
start,
heh,
self.half_edges[heh].target,
);
}
if visited.insert(heh) {
panic!(
"bug: encountered {:?} while iterating around {:?}, but we \
already visited it!",
heh,
vertex,
);
}
heh = *self.half_edges[heh].next.twin();
if heh == start {
break;
}
}
}
}
}
impl<C: Config> MeshMut for HalfEdgeMesh<C> {
fn add_vertex(&mut self) -> VertexHandle {
self.vertices.push(Vertex {
outgoing: Opt::none()
})
}
fn add_triangle(&mut self, [a, b, c]: [VertexHandle; 3]) -> FaceHandle {
assert_ne!(a, b, "vertices of new face are not unique");
assert_ne!(a, c, "vertices of new face are not unique");
self.add_face_impl(
&[a, b, c],
&mut [unsafe { Checked::new(HalfEdgeHandle::new(0)) }; 3],
)
}
fn add_face(&mut self, vertices: &[VertexHandle]) -> FaceHandle
where
Self: PolyMesh,
{
assert!(
vertices.len() >= 3,
"attempt to add a face with only {} vertices, but at least 3 vertices are required",
vertices.len(),
);
let dummy_he = unsafe { Checked::new(HalfEdgeHandle::new(0))};
match vertices.len() {
3 => self.add_face_impl(vertices, &mut [dummy_he; 3]),
4 => self.add_face_impl(vertices, &mut [dummy_he; 4]),
len => {
let mut inner_half_edges
= mem::replace(&mut self.cache.inner_half_edges, Vec::new());
inner_half_edges.clear();
inner_half_edges.resize(len, dummy_he);
let fh = self.add_face_impl(vertices, &mut inner_half_edges);
self.cache.inner_half_edges = inner_half_edges;
fh
}
}
}
fn remove_isolated_vertex(&mut self, v: VertexHandle) {
assert!(
self.vertices[v].outgoing.is_none(),
"{:?} is not isolated but was passed to `remove_isolated_vertex",
v,
);
self.vertices.remove(v);
}
fn remove_face(&mut self, f: FaceHandle) {
let f = self.check_face(f);
macro_rules! maybe_remove_edge {
($inner:ident) => {
if self[$inner.twin()].face.is_none() {
self.half_edges.remove(*$inner);
self.half_edges.remove(*$inner.twin());
} else {
self[$inner].face = Opt::none();
}
};
}
let start_incoming = self[f].edge;
let mut incoming_inner = start_incoming;
loop {
let outgoing_inner = self[incoming_inner].next;
let vh = self[incoming_inner].target;
let outgoing_outer = incoming_inner.twin();
let incoming_outer = outgoing_inner.twin();
match (self[incoming_outer].face.is_some(), self[outgoing_outer].face.is_some()) {
(false, false) if self[incoming_outer].next == outgoing_outer => {
self[vh].outgoing = Opt::none();
}
(false, false) => {
let start = self[incoming_outer].next;
let end = self[outgoing_outer].prev.into_option().unwrap_or_else(|| {
self.find_incoming_he(start.twin(), |incoming| {
self[incoming].next == outgoing_outer
}).expect("HEM bug: invalid cycle around vertex")
});
self[vh].outgoing = Opt::some(start);
set_next_prev!(self, end -> start);
}
(true, false) => {
let end = self[outgoing_outer].prev.into_option().unwrap_or_else(|| {
self.find_incoming_he(incoming_outer, |incoming| {
self[incoming].next == outgoing_outer
}).expect("HEM bug: invalid cycle around vertex")
});
set_next_prev!(self, end -> outgoing_inner);
self[vh].outgoing = Opt::some(outgoing_inner);
}
(false, true) => {
let start = self[incoming_outer].next;
set_next_prev!(self, incoming_inner -> start);
}
(true, true) => {
self[vh].outgoing = Opt::some(outgoing_inner);
}
}
if incoming_inner != start_incoming {
maybe_remove_edge!(incoming_inner);
if outgoing_inner == start_incoming {
break;
}
}
incoming_inner = outgoing_inner;
}
maybe_remove_edge!(start_incoming);
self.faces.remove(*f);
}
#[inline(never)]
fn reserve_for_vertices(&mut self, count: hsize) {
self.vertices.reserve(count);
}
#[inline(never)]
fn reserve_for_faces(&mut self, count: hsize) {
self.half_edges.reserve(count * 3);
self.faces.reserve(count);
}
fn remove_all_vertices(&mut self) {
assert!(
self.num_faces() == 0,
"call to `remove_all_vertices`, but there are faces in the mesh!",
);
self.vertices.clear();
}
fn remove_all_faces(&mut self) {
self.half_edges.clear();
self.faces.clear();
for v in self.vertices.values_mut() {
v.outgoing = Opt::none();
}
}
fn split_face(&mut self, f: FaceHandle) -> VertexHandle {
let f = self.check_face(f);
let midpoint = unsafe { Checked::new(self.add_vertex()) };
let start_ohe = self[f].edge;
let start_vertex = self[start_ohe.twin()].target;
let start_nhe = unsafe { self.add_edge_partially(midpoint, start_vertex) };
self[midpoint].outgoing = Opt::some(start_nhe);
let mut border_ohe = start_ohe;
let mut last_nhe = start_nhe;
while self[border_ohe].target != start_vertex {
let next_border_ohe = self[border_ohe].next;
let next_vertex = self[border_ohe].target;
let next_nhe = unsafe { self.add_edge_partially(midpoint, next_vertex) };
let inner_new = next_nhe.twin();
let new_face = unsafe { Checked::new(self.faces.push(Face { edge: inner_new })) };
set_next_prev!(self, inner_new -> last_nhe);
set_next_prev!(self, last_nhe -> border_ohe);
set_next_prev!(self, border_ohe -> inner_new);
self[inner_new].face = Opt::some(new_face);
self[last_nhe].face = Opt::some(new_face);
self[border_ohe].face = Opt::some(new_face);
last_nhe = next_nhe;
border_ohe = next_border_ohe;
}
let start_inner_nhe = start_nhe.twin();
self[f].edge = start_inner_nhe;
set_next_prev!(self, start_inner_nhe -> last_nhe);
set_next_prev!(self, last_nhe -> border_ohe);
set_next_prev!(self, border_ohe -> start_inner_nhe);
self[start_inner_nhe].face = Opt::some(f);
self[last_nhe].face = Opt::some(f);
*midpoint
}
fn flip_edge(&mut self, edge: EdgeHandle)
where
Self: TriMesh + EdgeMesh,
{
let he_center_above = self.checked_half_of(edge);
let he_center_below = he_center_above.twin();
let he_above_right = self[he_center_above].next;
let he_above_left = self[he_above_right].next;
let he_below_left = self[he_center_below].next;
let he_below_right = self[he_below_left].next;
let faces = [
self[he_center_above].face.into_option(),
self[he_center_below].face.into_option(),
];
let (f_above, f_below) = match faces {
[Some(above), Some(below)] => (above, below),
_ => {
panic!("`flip_edge` called on boundary edge {:?}", edge);
}
};
let v_right = self[he_center_above].target;
let v_left = self[he_center_below].target;
let v_above = self[he_above_right].target;
let v_below = self[he_below_left].target;
if self[v_left].outgoing == Opt::some(he_center_above) {
self[v_left].outgoing = Opt::some(he_below_left);
}
if self[v_right].outgoing == Opt::some(he_center_below) {
self[v_right].outgoing = Opt::some(he_above_right);
}
self[f_above].edge = he_center_above;
self[f_below].edge = he_center_below;
self[he_center_above].target = v_below;
set_next_prev!(self, he_center_above -> he_below_right);
self[he_center_below].target = v_above;
set_next_prev!(self, he_center_below -> he_above_left);
self[he_below_right].face = Opt::some(f_above);
set_next_prev!(self, he_below_right -> he_above_right);
set_next_prev!(self, he_above_right -> he_center_above);
self[he_above_left].face = Opt::some(f_below);
set_next_prev!(self, he_above_left -> he_below_left);
set_next_prev!(self, he_below_left -> he_center_below);
}
fn split_edge_with_faces(&mut self, edge: EdgeHandle) -> SplitEdgeWithFacesResult
where
Self: TriMesh + EdgeMesh,
{
let he_above = self.checked_half_of(edge);
let he_below = he_above.twin();
let v_right = self[he_above].target;
let he_below_prev = self.prev(he_below);
let v_mid = unsafe { Checked::new(self.add_vertex()) };
let he_new_above = unsafe { self.add_edge_partially(v_mid, v_right) };
let he_new_below = he_new_above.twin();
let he_above_next = self[he_above].next;
set_next_prev!(self, he_new_above -> he_above_next);
set_next_prev!(self, he_above -> he_new_above);
self[he_above].target = v_mid;
set_next_prev!(self, he_new_below -> he_below);
set_next_prev!(self, he_below_prev -> he_new_below);
if self[v_right].outgoing == Opt::some(he_below) {
self[v_right].outgoing = Opt::some(he_new_below)
}
let face_above = self[he_above].face.into_option();
let face_below = self[he_below].face.into_option();
let outgoing = match (face_above.is_some(), face_below.is_some()) {
(false, true) => he_new_above,
(true, false) => he_below,
(false, false) | (true, true) => he_new_above,
};
self[v_mid].outgoing = Opt::some(outgoing);
let split_face = |
mesh: &mut Self,
old_face: Checked<FaceHandle>,
he_bottom_left: Checked<HalfEdgeHandle>,
he_bottom_right: Checked<HalfEdgeHandle>,
| {
let he_top_right = mesh[he_bottom_right].next;
let v_top = mesh[he_top_right].target;
let he_top_left = mesh[he_top_right].next;
let he_mid_left = unsafe { mesh.add_edge_partially(v_mid, v_top) };
let he_mid_right = he_mid_left.twin();
set_next_prev!(mesh, he_bottom_left -> he_mid_left);
mesh[he_bottom_left].face = Opt::some(old_face);
set_next_prev!(mesh, he_mid_left -> he_top_left);
mesh[he_mid_left].face = Opt::some(old_face);
mesh[old_face].edge = he_bottom_left;
let right_face = unsafe {
Checked::new(mesh.faces.push(Face { edge: he_bottom_right }))
};
mesh[he_mid_right].face = Opt::some(right_face);
mesh[he_bottom_right].face = Opt::some(right_face);
mesh[he_top_right].face = Opt::some(right_face);
set_next_prev!(mesh, he_top_right -> he_mid_right);
set_next_prev!(mesh, he_mid_right -> he_bottom_right);
};
if let Some(face) = face_above {
split_face(self, face, he_above, he_new_above);
}
if let Some(face) = face_below {
split_face(self, face, he_new_below, he_below);
}
SplitEdgeWithFacesResult {
vertex: *v_mid,
replacement_edges: [he_above.full_edge(), he_new_above.full_edge()],
}
}
}
impl<C: Config> EdgeMesh for HalfEdgeMesh<C> {}
impl<C: Config> SupportsMultiBlade for HalfEdgeMesh<C> {}