mod delaunay;
use crate::geom::{vert_ccw, Real};
pub const INVALID: u32 = u32::MAX;
pub type VertIdx = u32;
pub type FaceIdx = u32;
pub type EdgeIdx = u32;
#[inline(always)]
pub fn sym(e: EdgeIdx) -> EdgeIdx {
e ^ 1
}
#[derive(Clone, Debug)]
pub struct Vertex {
pub next: VertIdx,
pub prev: VertIdx,
pub an_edge: EdgeIdx,
pub coords: [Real; 3],
pub s: Real,
pub t: Real,
pub pq_handle: i32,
pub n: u32,
pub idx: u32,
}
impl Default for Vertex {
fn default() -> Self {
Self {
next: INVALID,
prev: INVALID,
an_edge: INVALID,
coords: [0.0; 3],
s: 0.0,
t: 0.0,
pq_handle: 0,
n: INVALID,
idx: INVALID,
}
}
}
#[derive(Clone, Debug)]
pub struct Face {
pub next: FaceIdx,
pub prev: FaceIdx,
pub an_edge: EdgeIdx,
pub trail: FaceIdx,
pub n: u32,
pub marked: bool,
pub inside: bool,
}
impl Default for Face {
fn default() -> Self {
Self {
next: INVALID,
prev: INVALID,
an_edge: INVALID,
trail: INVALID,
n: INVALID,
marked: false,
inside: false,
}
}
}
#[derive(Clone, Debug)]
pub struct HalfEdge {
pub next: EdgeIdx,
pub onext: EdgeIdx,
pub lnext: EdgeIdx,
pub org: VertIdx,
pub lface: FaceIdx,
pub active_region: u32,
pub winding: i32,
pub mark: bool,
}
impl Default for HalfEdge {
fn default() -> Self {
Self {
next: INVALID,
onext: INVALID,
lnext: INVALID,
org: INVALID,
lface: INVALID,
active_region: INVALID,
winding: 0,
mark: false,
}
}
}
pub struct Mesh {
pub verts: Vec<Vertex>,
pub faces: Vec<Face>,
pub edges: Vec<HalfEdge>,
}
pub const V_HEAD: VertIdx = 0;
pub const F_HEAD: FaceIdx = 0;
pub const E_HEAD: EdgeIdx = 0;
pub const E_HEAD_SYM: EdgeIdx = 1;
impl Mesh {
pub fn new() -> Self {
let mut m = Mesh {
verts: Vec::new(),
faces: Vec::new(),
edges: Vec::new(),
};
let mut v_head = Vertex::default();
v_head.next = V_HEAD;
v_head.prev = V_HEAD;
v_head.an_edge = INVALID;
m.verts.push(v_head);
let mut f_head = Face::default();
f_head.next = F_HEAD;
f_head.prev = F_HEAD;
f_head.an_edge = INVALID;
f_head.trail = INVALID;
f_head.marked = false;
f_head.inside = false;
m.faces.push(f_head);
let mut e_head = HalfEdge::default();
e_head.next = E_HEAD;
e_head.onext = INVALID;
e_head.lnext = INVALID;
e_head.org = INVALID;
e_head.lface = INVALID;
e_head.winding = 0;
e_head.active_region = INVALID;
let mut e_head_sym = HalfEdge::default();
e_head_sym.next = E_HEAD_SYM;
e_head_sym.onext = INVALID;
e_head_sym.lnext = INVALID;
e_head_sym.org = INVALID;
e_head_sym.lface = INVALID;
e_head_sym.winding = 0;
e_head_sym.active_region = INVALID;
m.edges.push(e_head);
m.edges.push(e_head_sym);
m
}
#[inline(always)]
pub fn esym(&self, e: EdgeIdx) -> EdgeIdx {
e ^ 1
}
#[inline]
pub fn rface(&self, e: EdgeIdx) -> FaceIdx {
self.edges[(e ^ 1) as usize].lface
}
#[inline]
pub fn dst(&self, e: EdgeIdx) -> VertIdx {
self.edges[(e ^ 1) as usize].org
}
#[inline]
pub fn oprev(&self, e: EdgeIdx) -> EdgeIdx {
self.edges[(e ^ 1) as usize].lnext
}
#[inline]
pub fn lprev(&self, e: EdgeIdx) -> EdgeIdx {
self.edges[e as usize].onext ^ 1
}
#[inline]
pub fn dprev(&self, e: EdgeIdx) -> EdgeIdx {
self.edges[e as usize].lnext ^ 1
}
#[inline]
pub fn rprev(&self, e: EdgeIdx) -> EdgeIdx {
self.edges[(e ^ 1) as usize].onext
}
#[inline]
pub fn dnext(&self, e: EdgeIdx) -> EdgeIdx {
self.edges[(e ^ 1) as usize].onext ^ 1
}
#[inline]
pub fn rnext(&self, e: EdgeIdx) -> EdgeIdx {
self.edges[(e ^ 1) as usize].lnext ^ 1
}
#[inline]
pub fn edge_goes_left(&self, e: EdgeIdx) -> bool {
let dst = self.dst(e);
let org = self.edges[e as usize].org;
let ds = self.verts[dst as usize].s;
let dt = self.verts[dst as usize].t;
let os = self.verts[org as usize].s;
let ot = self.verts[org as usize].t;
crate::geom::vert_leq(ds, dt, os, ot)
}
#[inline]
pub fn edge_goes_right(&self, e: EdgeIdx) -> bool {
let org = self.edges[e as usize].org;
let dst = self.dst(e);
let os = self.verts[org as usize].s;
let ot = self.verts[org as usize].t;
let ds = self.verts[dst as usize].s;
let dt = self.verts[dst as usize].t;
crate::geom::vert_leq(os, ot, ds, dt)
}
#[inline]
pub fn edge_is_internal(&self, e: EdgeIdx) -> bool {
let rf = self.rface(e);
rf != INVALID && self.faces[rf as usize].inside
}
fn make_edge_pair(&mut self, e_next: EdgeIdx) -> EdgeIdx {
let e_next = if e_next & 1 != 0 { e_next ^ 1 } else { e_next };
let e_next_sym = e_next ^ 1;
if (e_next as usize) >= self.edges.len() || (e_next_sym as usize) >= self.edges.len() {
return INVALID;
}
let e_new = self.edges.len() as EdgeIdx;
let e_sym = e_new ^ 1;
let e_prev = self.edges[(e_next ^ 1) as usize].next;
if e_prev == INVALID {
return INVALID;
}
let mut e = HalfEdge::default();
e.next = e_next;
let mut e_s = HalfEdge::default();
e_s.next = e_prev;
self.edges.push(e); self.edges.push(e_s);
self.edges[(e_prev ^ 1) as usize].next = e_new;
self.edges[(e_next ^ 1) as usize].next = e_sym;
self.edges[e_new as usize].onext = e_new;
self.edges[e_new as usize].lnext = e_sym;
self.edges[e_new as usize].org = INVALID;
self.edges[e_new as usize].lface = INVALID;
self.edges[e_new as usize].winding = 0;
self.edges[e_new as usize].active_region = INVALID;
self.edges[e_new as usize].mark = false;
self.edges[e_sym as usize].onext = e_sym;
self.edges[e_sym as usize].lnext = e_new;
self.edges[e_sym as usize].org = INVALID;
self.edges[e_sym as usize].lface = INVALID;
self.edges[e_sym as usize].winding = 0;
self.edges[e_sym as usize].active_region = INVALID;
self.edges[e_sym as usize].mark = false;
e_new
}
fn make_vertex(&mut self, e_orig: EdgeIdx, v_next: VertIdx) -> VertIdx {
if v_next == INVALID || (v_next as usize) >= self.verts.len() {
return INVALID;
}
let v_new = self.verts.len() as VertIdx;
let v_prev = self.verts[v_next as usize].prev;
if v_prev == INVALID || (v_prev as usize) >= self.verts.len() {
return INVALID;
}
let mut v = Vertex::default();
v.prev = v_prev;
v.next = v_next;
v.an_edge = e_orig;
self.verts.push(v);
self.verts[v_prev as usize].next = v_new;
self.verts[v_next as usize].prev = v_new;
let mut e = e_orig;
loop {
self.edges[e as usize].org = v_new;
e = self.edges[e as usize].onext;
if e == e_orig {
break;
}
}
v_new
}
fn make_face(&mut self, e_orig: EdgeIdx, f_next: FaceIdx) -> FaceIdx {
if f_next == INVALID || (f_next as usize) >= self.faces.len() {
return INVALID;
}
let f_new = self.faces.len() as FaceIdx;
let f_prev = self.faces[f_next as usize].prev;
if f_prev == INVALID || (f_prev as usize) >= self.faces.len() {
return INVALID;
}
let inside_val = self.faces[f_next as usize].inside;
let mut f = Face::default();
f.prev = f_prev;
f.next = f_next;
f.an_edge = e_orig;
f.trail = INVALID;
f.marked = false;
f.inside = inside_val;
self.faces.push(f);
self.faces[f_prev as usize].next = f_new;
self.faces[f_next as usize].prev = f_new;
let mut e = e_orig;
loop {
self.edges[e as usize].lface = f_new;
e = self.edges[e as usize].lnext;
if e == e_orig {
break;
}
}
f_new
}
fn kill_vertex(&mut self, v_del: VertIdx, new_org: VertIdx) {
let e_start = self.verts[v_del as usize].an_edge;
if e_start != INVALID {
let mut e = e_start;
loop {
self.edges[e as usize].org = new_org;
e = self.edges[e as usize].onext;
if e == e_start {
break;
}
}
}
let v_prev = self.verts[v_del as usize].prev;
let v_next = self.verts[v_del as usize].next;
if v_prev != INVALID && v_prev < self.verts.len() as u32 {
self.verts[v_prev as usize].next = v_next;
}
if v_next != INVALID && v_next < self.verts.len() as u32 {
self.verts[v_next as usize].prev = v_prev;
}
self.verts[v_del as usize].next = INVALID;
self.verts[v_del as usize].prev = INVALID;
self.verts[v_del as usize].an_edge = INVALID;
}
fn kill_face(&mut self, f_del: FaceIdx, new_lface: FaceIdx) {
let e_start = self.faces[f_del as usize].an_edge;
if e_start != INVALID {
let mut e = e_start;
loop {
self.edges[e as usize].lface = new_lface;
e = self.edges[e as usize].lnext;
if e == e_start {
break;
}
}
}
let f_prev = self.faces[f_del as usize].prev;
let f_next = self.faces[f_del as usize].next;
if f_prev != INVALID && f_prev < self.faces.len() as u32 {
self.faces[f_prev as usize].next = f_next;
}
if f_next != INVALID && f_next < self.faces.len() as u32 {
self.faces[f_next as usize].prev = f_prev;
}
self.faces[f_del as usize].next = INVALID;
self.faces[f_del as usize].prev = INVALID;
self.faces[f_del as usize].an_edge = INVALID;
}
fn kill_edge(&mut self, e_del: EdgeIdx) {
let e_del = if e_del & 1 != 0 { e_del ^ 1 } else { e_del };
let e_next = self.edges[e_del as usize].next;
let e_prev = self.edges[(e_del ^ 1) as usize].next;
let nlen = self.edges.len() as u32;
if e_next != INVALID && (e_next ^ 1) < nlen {
self.edges[(e_next ^ 1) as usize].next = e_prev;
}
if e_prev != INVALID && (e_prev ^ 1) < nlen {
self.edges[(e_prev ^ 1) as usize].next = e_next;
}
self.edges[e_del as usize].next = INVALID;
self.edges[(e_del ^ 1) as usize].next = INVALID;
}
pub fn make_edge(&mut self) -> Option<EdgeIdx> {
let e = self.make_edge_pair(E_HEAD);
let e_sym = e ^ 1;
let v1 = self.make_vertex(e, V_HEAD);
let v2 = self.make_vertex(e_sym, V_HEAD);
let _f = self.make_face(e, F_HEAD);
self.edges[e as usize].org = v1;
self.edges[e_sym as usize].org = v2;
Some(e)
}
pub fn splice(&mut self, e_org: EdgeIdx, e_dst: EdgeIdx) -> bool {
if e_org == e_dst {
return true;
}
let org_org = self.edges[e_org as usize].org;
let dst_org = self.edges[e_dst as usize].org;
let org_lface = self.edges[e_org as usize].lface;
let dst_lface = self.edges[e_dst as usize].lface;
let joining_vertices = dst_org != org_org;
let joining_loops = dst_lface != org_lface;
if joining_vertices {
self.kill_vertex(dst_org, org_org);
}
if joining_loops {
self.kill_face(dst_lface, org_lface);
}
Mesh::do_splice(&mut self.edges, e_org, e_dst);
if !joining_vertices {
let new_v = self.make_vertex(e_dst, org_org);
self.edges[e_org as usize].org = org_org; self.verts[org_org as usize].an_edge = e_org;
let _ = new_v;
}
if !joining_loops {
let new_f = self.make_face(e_dst, org_lface);
self.verts[org_org as usize].an_edge = e_org; self.faces[org_lface as usize].an_edge = e_org;
let _ = new_f;
}
true
}
fn do_splice(edges: &mut Vec<HalfEdge>, a: EdgeIdx, b: EdgeIdx) {
let a_onext = edges[a as usize].onext;
let b_onext = edges[b as usize].onext;
edges[(a_onext ^ 1) as usize].lnext = b;
edges[(b_onext ^ 1) as usize].lnext = a;
edges[a as usize].onext = b_onext;
edges[b as usize].onext = a_onext;
}
pub fn delete_edge(&mut self, e_del: EdgeIdx) -> bool {
let e_del_sym = e_del ^ 1;
let e_del_lface = self.edges[e_del as usize].lface;
let e_del_rface = self.rface(e_del);
let joining_loops = e_del_lface != e_del_rface;
if joining_loops {
self.kill_face(e_del_lface, e_del_rface);
}
let e_del_onext = self.edges[e_del as usize].onext;
if e_del_onext == e_del {
let e_del_org = self.edges[e_del as usize].org;
self.kill_vertex(e_del_org, INVALID);
} else {
let e_del_oprev = self.oprev(e_del);
let e_del_rface2 = self.rface(e_del);
self.faces[e_del_rface2 as usize].an_edge = e_del_oprev;
let e_del_org2 = self.edges[e_del as usize].org;
self.verts[e_del_org2 as usize].an_edge = e_del_onext;
Mesh::do_splice(&mut self.edges, e_del, e_del_oprev);
if !joining_loops {
let new_f = self.make_face(e_del, e_del_lface);
let _ = new_f;
}
}
let e_del_sym_onext = self.edges[e_del_sym as usize].onext;
if e_del_sym_onext == e_del_sym {
let e_del_sym_org = self.edges[e_del_sym as usize].org;
self.kill_vertex(e_del_sym_org, INVALID);
let e_del_lface2 = self.edges[e_del as usize].lface;
self.kill_face(e_del_lface2, INVALID);
} else {
let e_del_lface3 = self.edges[e_del as usize].lface;
let e_del_sym_oprev = self.oprev(e_del_sym);
self.faces[e_del_lface3 as usize].an_edge = e_del_sym_oprev;
let e_del_sym_org2 = self.edges[e_del_sym as usize].org;
self.verts[e_del_sym_org2 as usize].an_edge = e_del_sym_onext;
Mesh::do_splice(&mut self.edges, e_del_sym, e_del_sym_oprev);
}
self.kill_edge(e_del);
true
}
pub fn add_edge_vertex(&mut self, e_org: EdgeIdx) -> Option<EdgeIdx> {
let e_new = self.make_edge_pair(e_org);
if e_new == INVALID {
return None;
}
let e_new_sym = e_new ^ 1;
let e_org_lnext = self.edges[e_org as usize].lnext;
Mesh::do_splice(&mut self.edges, e_new, e_org_lnext);
let e_org_dst = self.dst(e_org);
self.edges[e_new as usize].org = e_org_dst;
let v_new = self.make_vertex(e_new_sym, e_org_dst);
if v_new == INVALID {
return None;
}
let e_org_lface = self.edges[e_org as usize].lface;
self.edges[e_new as usize].lface = e_org_lface;
self.edges[e_new_sym as usize].lface = e_org_lface;
Some(e_new)
}
pub fn split_edge(&mut self, e_org: EdgeIdx) -> Option<EdgeIdx> {
let temp = self.add_edge_vertex(e_org)?;
let e_new = temp ^ 1;
let e_org_sym = e_org ^ 1;
let e_org_sym_oprev = self.oprev(e_org_sym);
Mesh::do_splice(&mut self.edges, e_org_sym, e_org_sym_oprev);
Mesh::do_splice(&mut self.edges, e_org_sym, e_new);
let e_new_org = self.edges[e_new as usize].org;
let e_org_dst_idx = e_org ^ 1; self.edges[e_org_dst_idx as usize].org = e_new_org;
let e_new_dst = self.dst(e_new);
self.verts[e_new_dst as usize].an_edge = e_new ^ 1;
let e_org_rface = self.rface(e_org);
self.edges[(e_new ^ 1) as usize].lface = e_org_rface; let e_org_winding = self.edges[e_org as usize].winding;
let e_org_sym_winding = self.edges[e_org_sym as usize].winding;
self.edges[e_new as usize].winding = e_org_winding;
self.edges[(e_new ^ 1) as usize].winding = e_org_sym_winding;
Some(e_new)
}
pub fn connect(&mut self, e_org: EdgeIdx, e_dst: EdgeIdx) -> Option<EdgeIdx> {
let e_new = self.make_edge_pair(e_org);
if e_new == INVALID { return None; }
let e_new_sym = e_new ^ 1;
let e_dst_lface = self.edges[e_dst as usize].lface;
let e_org_lface = self.edges[e_org as usize].lface;
let joining_loops = e_dst_lface != e_org_lface;
if joining_loops {
self.kill_face(e_dst_lface, e_org_lface);
}
let e_org_lnext = self.edges[e_org as usize].lnext;
Mesh::do_splice(&mut self.edges, e_new, e_org_lnext);
Mesh::do_splice(&mut self.edges, e_new_sym, e_dst);
let e_org_dst = self.dst(e_org);
self.edges[e_new as usize].org = e_org_dst;
let e_dst_org = self.edges[e_dst as usize].org;
self.edges[e_new_sym as usize].org = e_dst_org;
self.edges[e_new as usize].lface = e_org_lface;
self.edges[e_new_sym as usize].lface = e_org_lface;
self.faces[e_org_lface as usize].an_edge = e_new_sym;
if !joining_loops {
let new_f = self.make_face(e_new, e_org_lface);
let _ = new_f;
}
Some(e_new)
}
pub fn zap_face(&mut self, f_zap: FaceIdx) {
let e_start = self.faces[f_zap as usize].an_edge;
let mut e_next = self.edges[e_start as usize].lnext;
loop {
let e = e_next;
e_next = self.edges[e as usize].lnext;
self.edges[e as usize].lface = INVALID;
let e_rface = self.rface(e);
if e_rface == INVALID {
let e_onext = self.edges[e as usize].onext;
if e_onext == e {
let e_org = self.edges[e as usize].org;
if e_org != INVALID {
self.kill_vertex(e_org, INVALID);
}
} else {
let e_org = self.edges[e as usize].org;
if e_org != INVALID {
self.verts[e_org as usize].an_edge = e_onext;
}
let e_oprev = self.oprev(e);
Mesh::do_splice(&mut self.edges, e, e_oprev);
}
let e_sym = e ^ 1;
let e_sym_onext = self.edges[e_sym as usize].onext;
if e_sym_onext == e_sym {
let e_sym_org = self.edges[e_sym as usize].org;
if e_sym_org != INVALID {
self.kill_vertex(e_sym_org, INVALID);
}
} else {
let e_sym_org = self.edges[e_sym as usize].org;
if e_sym_org != INVALID {
self.verts[e_sym_org as usize].an_edge = e_sym_onext;
}
let e_sym_oprev = self.oprev(e_sym);
Mesh::do_splice(&mut self.edges, e_sym, e_sym_oprev);
}
self.kill_edge(e);
}
if e == e_start {
break;
}
}
let f_prev = self.faces[f_zap as usize].prev;
let f_next = self.faces[f_zap as usize].next;
self.faces[f_prev as usize].next = f_next;
self.faces[f_next as usize].prev = f_prev;
self.faces[f_zap as usize].next = INVALID;
self.faces[f_zap as usize].prev = INVALID;
self.faces[f_zap as usize].an_edge = INVALID;
}
pub fn count_face_verts(&self, f: FaceIdx) -> usize {
let e_start = self.faces[f as usize].an_edge;
let mut e = e_start;
let mut n = 0;
loop {
n += 1;
e = self.edges[e as usize].lnext;
if e == e_start {
break;
}
}
n
}
pub fn merge_convex_faces(&mut self, max_verts_per_face: usize) -> bool {
let mut e = self.edges[E_HEAD as usize].next;
while e != E_HEAD {
let e_next = self.edges[e as usize].next;
let e_sym = e ^ 1;
let e_lface = self.edges[e as usize].lface;
let e_sym_lface = self.edges[e_sym as usize].lface;
if e_lface == INVALID
|| !self.faces[e_lface as usize].inside
|| e_sym_lface == INVALID
|| !self.faces[e_sym_lface as usize].inside
{
e = e_next;
continue;
}
let left_nv = self.count_face_verts(e_lface);
let right_nv = self.count_face_verts(e_sym_lface);
if left_nv + right_nv - 2 > max_verts_per_face {
e = e_next;
continue;
}
let va = self.edges[self.lprev(e) as usize].org;
let vb = self.edges[e as usize].org;
let vc_edge = self.edges[e_sym as usize].lnext;
let vc = self.dst(vc_edge);
let vd = self.edges[self.lprev(e_sym) as usize].org;
let ve = self.edges[e_sym as usize].org;
let vf_edge = self.edges[e as usize].lnext;
let vf = self.dst(vf_edge);
let convex = vert_ccw(
self.verts[va as usize].s,
self.verts[va as usize].t,
self.verts[vb as usize].s,
self.verts[vb as usize].t,
self.verts[vc as usize].s,
self.verts[vc as usize].t,
) && vert_ccw(
self.verts[vd as usize].s,
self.verts[vd as usize].t,
self.verts[ve as usize].s,
self.verts[ve as usize].t,
self.verts[vf as usize].s,
self.verts[vf as usize].t,
);
if convex {
let actual_next = if e == e_next || e == e_next ^ 1 {
self.edges[e_next as usize].next
} else {
e_next
};
if !self.delete_edge(e) {
return false;
}
e = actual_next;
continue;
}
e = e_next;
}
true
}
pub fn flip_edge(&mut self, edge: EdgeIdx) {
let a0 = edge;
let a1 = self.edges[a0 as usize].lnext;
let a2 = self.edges[a1 as usize].lnext;
let b0 = edge ^ 1;
let b1 = self.edges[b0 as usize].lnext;
let b2 = self.edges[b1 as usize].lnext;
let a_org = self.edges[a0 as usize].org;
let a_opp = self.edges[a2 as usize].org;
let b_org = self.edges[b0 as usize].org;
let b_opp = self.edges[b2 as usize].org;
let fa = self.edges[a0 as usize].lface;
let fb = self.edges[b0 as usize].lface;
self.edges[a0 as usize].org = b_opp;
self.edges[a0 as usize].onext = self.edges[b1 as usize].onext ^ 1; self.edges[b0 as usize].org = a_opp;
self.edges[b0 as usize].onext = self.edges[a1 as usize].onext ^ 1; self.edges[a2 as usize].onext = b0;
self.edges[b2 as usize].onext = a0;
self.edges[b1 as usize].onext = self.edges[a2 as usize].onext ^ 1;
self.edges[a0 as usize].lnext = a2;
self.edges[a2 as usize].lnext = b1;
self.edges[b1 as usize].lnext = a0;
self.edges[b0 as usize].lnext = b2;
self.edges[b2 as usize].lnext = a1;
self.edges[a1 as usize].lnext = b0;
self.edges[a1 as usize].lface = fb;
self.edges[b1 as usize].lface = fa;
self.faces[fa as usize].an_edge = a0;
self.faces[fb as usize].an_edge = b0;
if self.verts[a_org as usize].an_edge == a0 {
self.verts[a_org as usize].an_edge = b1;
}
if self.verts[b_org as usize].an_edge == b0 {
self.verts[b_org as usize].an_edge = a1;
}
}
pub fn set_winding_number(&mut self, value: i32, keep_only_boundary: bool) -> bool {
let mut e = self.edges[E_HEAD as usize].next;
while e != E_HEAD {
let e_next = self.edges[e as usize].next;
let e_lface = self.edges[e as usize].lface;
let e_rface = self.rface(e);
let lf_inside = if e_lface != INVALID {
self.faces[e_lface as usize].inside
} else {
false
};
let rf_inside = if e_rface != INVALID {
self.faces[e_rface as usize].inside
} else {
false
};
if rf_inside != lf_inside {
self.edges[e as usize].winding = if lf_inside { value } else { -value };
} else if !keep_only_boundary {
self.edges[e as usize].winding = 0;
} else if !self.delete_edge(e) {
return false;
}
e = e_next;
}
true
}
pub fn discard_exterior(&mut self) {
let mut f = self.faces[F_HEAD as usize].next;
while f != F_HEAD {
let next = self.faces[f as usize].next;
if !self.faces[f as usize].inside {
self.zap_face(f);
}
f = next;
}
}
}
mod tessellate;
impl Default for Mesh {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn make_edge_creates_single_edge() {
let mut mesh = Mesh::new();
let e = mesh.make_edge().unwrap();
assert_eq!(mesh.verts.len(), 3);
assert_eq!(mesh.faces.len(), 2);
assert_eq!(mesh.edges.len(), 4);
let org1 = mesh.edges[e as usize].org;
let org2 = mesh.edges[(e ^ 1) as usize].org;
assert_ne!(org1, org2);
assert_ne!(org1, INVALID);
assert_ne!(org2, INVALID);
}
#[test]
fn sym_involution() {
for e in 0u32..16 {
assert_eq!(sym(sym(e)), e);
}
}
#[test]
fn vertex_list_circular() {
let mut mesh = Mesh::new();
mesh.make_edge().unwrap();
let first = mesh.verts[V_HEAD as usize].next;
assert_ne!(first, V_HEAD);
let second = mesh.verts[first as usize].next;
assert_ne!(second, INVALID);
}
}