Skip to main content

tess2_rust/mesh/
mod.rs

1// Copyright 2025 Lars Brubaker
2// License: SGI Free Software License B (MIT-compatible)
3//
4// Port of libtess2 mesh.c/h
5//
6// The mesh is a half-edge data structure (similar to Guibas/Stolfi quad-edge).
7// All pointers from the C code are replaced with u32 indices into Vec arenas.
8//
9// Design:
10//   - INVALID: u32::MAX  (null pointer equivalent)
11//   - Half-edges allocated in pairs: edges[i] and edges[i^1] are always a pair.
12//     sym(e) = e ^ 1.  Even index = e, odd index = eSym.
13//   - Sentinel/dummy nodes:
14//     - verts[0] = vHead (dummy vertex)
15//     - faces[0] = fHead (dummy face)
16//     - edges[0] = eHead, edges[1] = eHeadSym (dummy edge pair)
17
18mod delaunay;
19
20use crate::geom::{vert_ccw, Real};
21
22pub const INVALID: u32 = u32::MAX;
23
24/// Index into Mesh::verts
25pub type VertIdx = u32;
26/// Index into Mesh::faces
27pub type FaceIdx = u32;
28/// Index into Mesh::edges
29pub type EdgeIdx = u32;
30
31/// Compute the symmetric half-edge index (always the other half of the pair).
32#[inline(always)]
33pub fn sym(e: EdgeIdx) -> EdgeIdx {
34    e ^ 1
35}
36
37#[derive(Clone, Debug)]
38pub struct Vertex {
39    pub next: VertIdx,
40    pub prev: VertIdx,
41    pub an_edge: EdgeIdx,
42    pub coords: [Real; 3],
43    pub s: Real,
44    pub t: Real,
45    pub pq_handle: i32,
46    pub n: u32,
47    pub idx: u32,
48}
49
50impl Default for Vertex {
51    fn default() -> Self {
52        Self {
53            next: INVALID,
54            prev: INVALID,
55            an_edge: INVALID,
56            coords: [0.0; 3],
57            s: 0.0,
58            t: 0.0,
59            pq_handle: 0,
60            n: INVALID,
61            idx: INVALID,
62        }
63    }
64}
65
66#[derive(Clone, Debug)]
67pub struct Face {
68    pub next: FaceIdx,
69    pub prev: FaceIdx,
70    pub an_edge: EdgeIdx,
71    pub trail: FaceIdx,
72    pub n: u32,
73    pub marked: bool,
74    pub inside: bool,
75}
76
77impl Default for Face {
78    fn default() -> Self {
79        Self {
80            next: INVALID,
81            prev: INVALID,
82            an_edge: INVALID,
83            trail: INVALID,
84            n: INVALID,
85            marked: false,
86            inside: false,
87        }
88    }
89}
90
91#[derive(Clone, Debug)]
92pub struct HalfEdge {
93    /// Next in the global edge list (even-indexed edges link to even-indexed edges,
94    /// odd-indexed edges link to odd-indexed edges).
95    pub next: EdgeIdx,
96    /// Next edge CCW around the origin vertex.
97    pub onext: EdgeIdx,
98    /// Next edge CCW around the left face.
99    pub lnext: EdgeIdx,
100    /// Origin vertex index.
101    pub org: VertIdx,
102    /// Left face index.
103    pub lface: FaceIdx,
104    /// Active region index (INVALID if not in the edge dictionary).
105    pub active_region: u32,
106    /// Winding number change when crossing this edge.
107    pub winding: i32,
108    /// Used by edge flip (Delaunay refinement).
109    pub mark: bool,
110}
111
112impl Default for HalfEdge {
113    fn default() -> Self {
114        Self {
115            next: INVALID,
116            onext: INVALID,
117            lnext: INVALID,
118            org: INVALID,
119            lface: INVALID,
120            active_region: INVALID,
121            winding: 0,
122            mark: false,
123        }
124    }
125}
126
127/// The half-edge mesh.
128pub struct Mesh {
129    pub verts: Vec<Vertex>,
130    pub faces: Vec<Face>,
131    pub edges: Vec<HalfEdge>,
132}
133
134// ──────────────────────────────── Sentinel indices ────────────────────────────
135pub const V_HEAD: VertIdx = 0;
136pub const F_HEAD: FaceIdx = 0;
137pub const E_HEAD: EdgeIdx = 0;
138pub const E_HEAD_SYM: EdgeIdx = 1;
139
140impl Mesh {
141    /// Create a new empty mesh with dummy sentinel nodes.
142    pub fn new() -> Self {
143        let mut m = Mesh {
144            verts: Vec::new(),
145            faces: Vec::new(),
146            edges: Vec::new(),
147        };
148
149        // vHead (index 0) -- dummy vertex
150        let mut v_head = Vertex::default();
151        v_head.next = V_HEAD;
152        v_head.prev = V_HEAD;
153        v_head.an_edge = INVALID;
154        m.verts.push(v_head);
155
156        // fHead (index 0) -- dummy face
157        let mut f_head = Face::default();
158        f_head.next = F_HEAD;
159        f_head.prev = F_HEAD;
160        f_head.an_edge = INVALID;
161        f_head.trail = INVALID;
162        f_head.marked = false;
163        f_head.inside = false;
164        m.faces.push(f_head);
165
166        // eHead (index 0), eHeadSym (index 1) -- dummy edge pair
167        let mut e_head = HalfEdge::default();
168        e_head.next = E_HEAD;
169        e_head.onext = INVALID;
170        e_head.lnext = INVALID;
171        e_head.org = INVALID;
172        e_head.lface = INVALID;
173        e_head.winding = 0;
174        e_head.active_region = INVALID;
175
176        let mut e_head_sym = HalfEdge::default();
177        e_head_sym.next = E_HEAD_SYM;
178        e_head_sym.onext = INVALID;
179        e_head_sym.lnext = INVALID;
180        e_head_sym.org = INVALID;
181        e_head_sym.lface = INVALID;
182        e_head_sym.winding = 0;
183        e_head_sym.active_region = INVALID;
184
185        m.edges.push(e_head);
186        m.edges.push(e_head_sym);
187
188        m
189    }
190
191    // ──────────────── Navigation helpers (C macro translations) ────────────────
192
193    /// Symmetric half-edge (always the other element of the pair).
194    #[inline(always)]
195    pub fn esym(&self, e: EdgeIdx) -> EdgeIdx {
196        e ^ 1
197    }
198
199    /// Right face of e (= lface of Sym).
200    #[inline]
201    pub fn rface(&self, e: EdgeIdx) -> FaceIdx {
202        self.edges[(e ^ 1) as usize].lface
203    }
204
205    /// Destination vertex of e (= org of Sym).
206    #[inline]
207    pub fn dst(&self, e: EdgeIdx) -> VertIdx {
208        self.edges[(e ^ 1) as usize].org
209    }
210
211    /// Oprev: Sym->Lnext
212    #[inline]
213    pub fn oprev(&self, e: EdgeIdx) -> EdgeIdx {
214        self.edges[(e ^ 1) as usize].lnext
215    }
216
217    /// Lprev: Onext->Sym
218    #[inline]
219    pub fn lprev(&self, e: EdgeIdx) -> EdgeIdx {
220        self.edges[e as usize].onext ^ 1
221    }
222
223    /// Dprev: Lnext->Sym
224    #[inline]
225    pub fn dprev(&self, e: EdgeIdx) -> EdgeIdx {
226        self.edges[e as usize].lnext ^ 1
227    }
228
229    /// Rprev: Sym->Onext
230    #[inline]
231    pub fn rprev(&self, e: EdgeIdx) -> EdgeIdx {
232        self.edges[(e ^ 1) as usize].onext
233    }
234
235    /// Dnext: Rprev->Sym = (Sym->Onext)->Sym
236    #[inline]
237    pub fn dnext(&self, e: EdgeIdx) -> EdgeIdx {
238        self.edges[(e ^ 1) as usize].onext ^ 1
239    }
240
241    /// Rnext: Oprev->Sym = (Sym->Lnext)->Sym
242    #[inline]
243    pub fn rnext(&self, e: EdgeIdx) -> EdgeIdx {
244        self.edges[(e ^ 1) as usize].lnext ^ 1
245    }
246
247    /// EdgeGoesLeft: VertLeq(Dst, Org)
248    #[inline]
249    pub fn edge_goes_left(&self, e: EdgeIdx) -> bool {
250        let dst = self.dst(e);
251        let org = self.edges[e as usize].org;
252        let ds = self.verts[dst as usize].s;
253        let dt = self.verts[dst as usize].t;
254        let os = self.verts[org as usize].s;
255        let ot = self.verts[org as usize].t;
256        crate::geom::vert_leq(ds, dt, os, ot)
257    }
258
259    /// EdgeGoesRight: VertLeq(Org, Dst)
260    #[inline]
261    pub fn edge_goes_right(&self, e: EdgeIdx) -> bool {
262        let org = self.edges[e as usize].org;
263        let dst = self.dst(e);
264        let os = self.verts[org as usize].s;
265        let ot = self.verts[org as usize].t;
266        let ds = self.verts[dst as usize].s;
267        let dt = self.verts[dst as usize].t;
268        crate::geom::vert_leq(os, ot, ds, dt)
269    }
270
271    /// EdgeIsInternal: e->Rface && e->Rface->inside
272    #[inline]
273    pub fn edge_is_internal(&self, e: EdgeIdx) -> bool {
274        let rf = self.rface(e);
275        rf != INVALID && self.faces[rf as usize].inside
276    }
277
278    // ──────────────────────── Private allocation helpers ─────────────────────
279
280    /// Allocate a new half-edge pair.  Returns the index of `e` (even); sym is `e ^ 1`.
281    /// The new pair is inserted in the global edge list before `e_next`.
282    fn make_edge_pair(&mut self, e_next: EdgeIdx) -> EdgeIdx {
283        // Normalize: e_next must be the even half (e, not eSym)
284        let e_next = if e_next & 1 != 0 { e_next ^ 1 } else { e_next };
285
286        // Validate e_next
287        let e_next_sym = e_next ^ 1;
288        if (e_next as usize) >= self.edges.len() || (e_next_sym as usize) >= self.edges.len() {
289            return INVALID;
290        }
291
292        let e_new = self.edges.len() as EdgeIdx;
293        let e_sym = e_new ^ 1;
294
295        // ePrev = eNext->Sym->next
296        let e_prev = self.edges[(e_next ^ 1) as usize].next;
297        if e_prev == INVALID {
298            return INVALID;
299        }
300
301        // Insert new pair between ePrev and eNext in the global edge list.
302        // List A (even edges): ePrev ← e_new → e_next (forward)
303        // List B (odd edges): ePrev^1 ← e_sym → e_next^1
304        let mut e = HalfEdge::default();
305        e.next = e_next;
306        let mut e_s = HalfEdge::default();
307        e_s.next = e_prev;
308
309        self.edges.push(e); // index e_new
310        self.edges.push(e_s); // index e_sym
311
312        // ePrev->Sym->next = e_new  →  edges[e_prev^1].next = e_new
313        self.edges[(e_prev ^ 1) as usize].next = e_new;
314        // eNext->Sym->next = e_sym  →  edges[e_next^1].next = e_sym
315        self.edges[(e_next ^ 1) as usize].next = e_sym;
316
317        // Initialize edge fields
318        self.edges[e_new as usize].onext = e_new;
319        self.edges[e_new as usize].lnext = e_sym;
320        self.edges[e_new as usize].org = INVALID;
321        self.edges[e_new as usize].lface = INVALID;
322        self.edges[e_new as usize].winding = 0;
323        self.edges[e_new as usize].active_region = INVALID;
324        self.edges[e_new as usize].mark = false;
325
326        self.edges[e_sym as usize].onext = e_sym;
327        self.edges[e_sym as usize].lnext = e_new;
328        self.edges[e_sym as usize].org = INVALID;
329        self.edges[e_sym as usize].lface = INVALID;
330        self.edges[e_sym as usize].winding = 0;
331        self.edges[e_sym as usize].active_region = INVALID;
332        self.edges[e_sym as usize].mark = false;
333
334        e_new
335    }
336
337    /// Allocate a new vertex and insert it before `v_next` in the vertex list.
338    fn make_vertex(&mut self, e_orig: EdgeIdx, v_next: VertIdx) -> VertIdx {
339        let v_new = self.verts.len() as VertIdx;
340        let v_prev = self.verts[v_next as usize].prev;
341
342        let mut v = Vertex::default();
343        v.prev = v_prev;
344        v.next = v_next;
345        v.an_edge = e_orig;
346        self.verts.push(v);
347
348        self.verts[v_prev as usize].next = v_new;
349        self.verts[v_next as usize].prev = v_new;
350
351        // Set all edges in the origin ring to point to v_new
352        let mut e = e_orig;
353        loop {
354            self.edges[e as usize].org = v_new;
355            e = self.edges[e as usize].onext;
356            if e == e_orig {
357                break;
358            }
359        }
360
361        v_new
362    }
363
364    /// Allocate a new face and insert it before `f_next` in the face list.
365    fn make_face(&mut self, e_orig: EdgeIdx, f_next: FaceIdx) -> FaceIdx {
366        if f_next == INVALID || (f_next as usize) >= self.faces.len() {
367            return INVALID;
368        }
369        let f_new = self.faces.len() as FaceIdx;
370        let f_prev = self.faces[f_next as usize].prev;
371        if f_prev == INVALID || (f_prev as usize) >= self.faces.len() {
372            return INVALID;
373        }
374
375        let inside_val = self.faces[f_next as usize].inside;
376
377        let mut f = Face::default();
378        f.prev = f_prev;
379        f.next = f_next;
380        f.an_edge = e_orig;
381        f.trail = INVALID;
382        f.marked = false;
383        f.inside = inside_val;
384        self.faces.push(f);
385
386        self.faces[f_prev as usize].next = f_new;
387        self.faces[f_next as usize].prev = f_new;
388
389        // Set all edges in the face loop to point to f_new
390        let mut e = e_orig;
391        loop {
392            self.edges[e as usize].lface = f_new;
393            e = self.edges[e as usize].lnext;
394            if e == e_orig {
395                break;
396            }
397        }
398
399        f_new
400    }
401
402    /// Kill (remove) a vertex from the global vertex list and update its edges to point to `new_org`.
403    fn kill_vertex(&mut self, v_del: VertIdx, new_org: VertIdx) {
404        // Re-point all edges in the vertex ring
405        let e_start = self.verts[v_del as usize].an_edge;
406        if e_start != INVALID {
407            let mut e = e_start;
408            loop {
409                self.edges[e as usize].org = new_org;
410                e = self.edges[e as usize].onext;
411                if e == e_start {
412                    break;
413                }
414            }
415        }
416
417        // Remove from doubly-linked vertex list
418        let v_prev = self.verts[v_del as usize].prev;
419        let v_next = self.verts[v_del as usize].next;
420        if v_prev != INVALID && v_prev < self.verts.len() as u32 {
421            self.verts[v_prev as usize].next = v_next;
422        }
423        if v_next != INVALID && v_next < self.verts.len() as u32 {
424            self.verts[v_next as usize].prev = v_prev;
425        }
426
427        // Mark as deleted (we don't actually reclaim the Vec slot)
428        self.verts[v_del as usize].next = INVALID;
429        self.verts[v_del as usize].prev = INVALID;
430        self.verts[v_del as usize].an_edge = INVALID;
431    }
432
433    /// Kill (remove) a face from the global face list and update its edges to point to `new_lface`.
434    fn kill_face(&mut self, f_del: FaceIdx, new_lface: FaceIdx) {
435        let e_start = self.faces[f_del as usize].an_edge;
436        if e_start != INVALID {
437            let mut e = e_start;
438            loop {
439                self.edges[e as usize].lface = new_lface;
440                e = self.edges[e as usize].lnext;
441                if e == e_start {
442                    break;
443                }
444            }
445        }
446
447        let f_prev = self.faces[f_del as usize].prev;
448        let f_next = self.faces[f_del as usize].next;
449        if f_prev != INVALID && f_prev < self.faces.len() as u32 {
450            self.faces[f_prev as usize].next = f_next;
451        }
452        if f_next != INVALID && f_next < self.faces.len() as u32 {
453            self.faces[f_next as usize].prev = f_prev;
454        }
455
456        self.faces[f_del as usize].next = INVALID;
457        self.faces[f_del as usize].prev = INVALID;
458        self.faces[f_del as usize].an_edge = INVALID;
459    }
460
461    /// Kill (remove) an edge pair from the global edge list.
462    fn kill_edge(&mut self, e_del: EdgeIdx) {
463        let e_del = if e_del & 1 != 0 { e_del ^ 1 } else { e_del };
464        let e_next = self.edges[e_del as usize].next;
465        let e_prev = self.edges[(e_del ^ 1) as usize].next;
466
467        let nlen = self.edges.len() as u32;
468        if e_next != INVALID && (e_next ^ 1) < nlen {
469            self.edges[(e_next ^ 1) as usize].next = e_prev;
470        }
471        if e_prev != INVALID && (e_prev ^ 1) < nlen {
472            self.edges[(e_prev ^ 1) as usize].next = e_next;
473        }
474
475        // Mark edge as deleted
476        self.edges[e_del as usize].next = INVALID;
477        self.edges[(e_del ^ 1) as usize].next = INVALID;
478    }
479
480    // ──────────────────────── Public mesh operations ──────────────────────────
481
482    /// tessMeshMakeEdge: creates one edge, two vertices, and a loop (face).
483    pub fn make_edge(&mut self) -> Option<EdgeIdx> {
484        let e = self.make_edge_pair(E_HEAD);
485        let e_sym = e ^ 1;
486
487        let v1 = self.make_vertex(e, V_HEAD);
488        let v2 = self.make_vertex(e_sym, V_HEAD);
489        let _f = self.make_face(e, F_HEAD);
490
491        self.edges[e as usize].org = v1;
492        self.edges[e_sym as usize].org = v2;
493
494        Some(e)
495    }
496
497    /// tessMeshSplice: the fundamental connectivity-changing operation.
498    /// Exchanges eOrg->Onext and eDst->Onext.
499    pub fn splice(&mut self, e_org: EdgeIdx, e_dst: EdgeIdx) -> bool {
500        if e_org == e_dst {
501            return true;
502        }
503
504        let org_org = self.edges[e_org as usize].org;
505        let dst_org = self.edges[e_dst as usize].org;
506        let org_lface = self.edges[e_org as usize].lface;
507        let dst_lface = self.edges[e_dst as usize].lface;
508
509        let joining_vertices = dst_org != org_org;
510        let joining_loops = dst_lface != org_lface;
511
512        if joining_vertices {
513            self.kill_vertex(dst_org, org_org);
514        }
515        if joining_loops {
516            self.kill_face(dst_lface, org_lface);
517        }
518
519        Mesh::do_splice(&mut self.edges, e_org, e_dst);
520
521        if !joining_vertices {
522            let new_v = self.make_vertex(e_dst, org_org);
523            // make sure old vertex still has a valid half-edge
524            self.edges[e_org as usize].org = org_org; // org unchanged
525            self.verts[org_org as usize].an_edge = e_org;
526            let _ = new_v;
527        }
528        if !joining_loops {
529            let new_f = self.make_face(e_dst, org_lface);
530            self.verts[org_org as usize].an_edge = e_org; // leave org alone
531            self.faces[org_lface as usize].an_edge = e_org;
532            let _ = new_f;
533        }
534
535        true
536    }
537
538    fn do_splice(edges: &mut Vec<HalfEdge>, a: EdgeIdx, b: EdgeIdx) {
539        let a_onext = edges[a as usize].onext;
540        let b_onext = edges[b as usize].onext;
541        edges[(a_onext ^ 1) as usize].lnext = b;
542        edges[(b_onext ^ 1) as usize].lnext = a;
543        edges[a as usize].onext = b_onext;
544        edges[b as usize].onext = a_onext;
545    }
546
547    /// tessMeshDelete: remove edge eDel.
548    pub fn delete_edge(&mut self, e_del: EdgeIdx) -> bool {
549        let e_del_sym = e_del ^ 1;
550
551        let e_del_lface = self.edges[e_del as usize].lface;
552        let e_del_rface = self.rface(e_del);
553        let joining_loops = e_del_lface != e_del_rface;
554
555        if joining_loops {
556            self.kill_face(e_del_lface, e_del_rface);
557        }
558
559        let e_del_onext = self.edges[e_del as usize].onext;
560        if e_del_onext == e_del {
561            let e_del_org = self.edges[e_del as usize].org;
562            self.kill_vertex(e_del_org, INVALID);
563        } else {
564            // Make sure eDel->Org and eDel->Rface point to valid half-edges
565            let e_del_oprev = self.oprev(e_del);
566            let e_del_rface2 = self.rface(e_del);
567            self.faces[e_del_rface2 as usize].an_edge = e_del_oprev;
568            let e_del_org2 = self.edges[e_del as usize].org;
569            self.verts[e_del_org2 as usize].an_edge = e_del_onext;
570
571            Mesh::do_splice(&mut self.edges, e_del, e_del_oprev);
572
573            if !joining_loops {
574                let new_f = self.make_face(e_del, e_del_lface);
575                let _ = new_f;
576            }
577        }
578
579        let e_del_sym_onext = self.edges[e_del_sym as usize].onext;
580        if e_del_sym_onext == e_del_sym {
581            let e_del_sym_org = self.edges[e_del_sym as usize].org;
582            self.kill_vertex(e_del_sym_org, INVALID);
583            let e_del_lface2 = self.edges[e_del as usize].lface;
584            self.kill_face(e_del_lface2, INVALID);
585        } else {
586            let e_del_lface3 = self.edges[e_del as usize].lface;
587            let e_del_sym_oprev = self.oprev(e_del_sym);
588            self.faces[e_del_lface3 as usize].an_edge = e_del_sym_oprev;
589            let e_del_sym_org2 = self.edges[e_del_sym as usize].org;
590            self.verts[e_del_sym_org2 as usize].an_edge = e_del_sym_onext;
591            Mesh::do_splice(&mut self.edges, e_del_sym, e_del_sym_oprev);
592        }
593
594        self.kill_edge(e_del);
595        true
596    }
597
598    /// tessMeshAddEdgeVertex: create a new edge eNew = eOrg->Lnext,
599    /// and eNew->Dst is a new vertex. eOrg and eNew share the same left face.
600    pub fn add_edge_vertex(&mut self, e_org: EdgeIdx) -> Option<EdgeIdx> {
601        let e_new = self.make_edge_pair(e_org);
602        if e_new == INVALID {
603            return None;
604        }
605        let e_new_sym = e_new ^ 1;
606
607        // Connect: eNew is inserted after eOrg in the Lnext ring
608        let e_org_lnext = self.edges[e_org as usize].lnext;
609        Mesh::do_splice(&mut self.edges, e_new, e_org_lnext);
610
611        // Set origin of eNew to eOrg->Dst
612        let e_org_dst = self.dst(e_org);
613        self.edges[e_new as usize].org = e_org_dst;
614
615        // Create new vertex at the other end
616        let v_new = self.make_vertex(e_new_sym, e_org_dst);
617        let _ = v_new;
618
619        // Both eNew and eNewSym share the same left face as eOrg
620        let e_org_lface = self.edges[e_org as usize].lface;
621        self.edges[e_new as usize].lface = e_org_lface;
622        self.edges[e_new_sym as usize].lface = e_org_lface;
623
624        Some(e_new)
625    }
626
627    /// tessMeshSplitEdge: split eOrg into eOrg and eNew, with eNew = eOrg->Lnext.
628    pub fn split_edge(&mut self, e_org: EdgeIdx) -> Option<EdgeIdx> {
629        let temp = self.add_edge_vertex(e_org)?;
630        let e_new = temp ^ 1;
631
632        // Disconnect eOrg from eOrg->Dst and reconnect to eNew->Org
633        let e_org_sym = e_org ^ 1;
634        let e_org_sym_oprev = self.oprev(e_org_sym);
635        Mesh::do_splice(&mut self.edges, e_org_sym, e_org_sym_oprev);
636        Mesh::do_splice(&mut self.edges, e_org_sym, e_new);
637
638        // Update vertex/face pointers
639        let e_new_org = self.edges[e_new as usize].org;
640        let e_org_dst_idx = e_org ^ 1; // sym
641        self.edges[e_org_dst_idx as usize].org = e_new_org;
642        let e_new_dst = self.dst(e_new);
643        self.verts[e_new_dst as usize].an_edge = e_new ^ 1;
644
645        let e_org_rface = self.rface(e_org);
646        self.edges[(e_new ^ 1) as usize].lface = e_org_rface; // eNew->Rface = eOrg->Rface (Rface = Sym->Lface)
647        let e_org_winding = self.edges[e_org as usize].winding;
648        let e_org_sym_winding = self.edges[e_org_sym as usize].winding;
649        self.edges[e_new as usize].winding = e_org_winding;
650        self.edges[(e_new ^ 1) as usize].winding = e_org_sym_winding;
651
652        Some(e_new)
653    }
654
655    /// tessMeshConnect: create a new edge from eOrg->Dst to eDst->Org.
656    /// Returns the new half-edge.
657    pub fn connect(&mut self, e_org: EdgeIdx, e_dst: EdgeIdx) -> Option<EdgeIdx> {
658        let e_new = self.make_edge_pair(e_org);
659        let e_new_sym = e_new ^ 1;
660
661        let e_dst_lface = self.edges[e_dst as usize].lface;
662        let e_org_lface = self.edges[e_org as usize].lface;
663        let joining_loops = e_dst_lface != e_org_lface;
664
665        if joining_loops {
666            self.kill_face(e_dst_lface, e_org_lface);
667        }
668
669        // Connect: Splice(eNew, eOrg->Lnext); Splice(eNewSym, eDst)
670        let e_org_lnext = self.edges[e_org as usize].lnext;
671        Mesh::do_splice(&mut self.edges, e_new, e_org_lnext);
672        Mesh::do_splice(&mut self.edges, e_new_sym, e_dst);
673
674        // Set vertex/face
675        let e_org_dst = self.dst(e_org);
676        self.edges[e_new as usize].org = e_org_dst;
677        let e_dst_org = self.edges[e_dst as usize].org;
678        self.edges[e_new_sym as usize].org = e_dst_org;
679        self.edges[e_new as usize].lface = e_org_lface;
680        self.edges[e_new_sym as usize].lface = e_org_lface;
681
682        // Make sure the old face points to a valid half-edge
683        self.faces[e_org_lface as usize].an_edge = e_new_sym;
684
685        if !joining_loops {
686            let new_f = self.make_face(e_new, e_org_lface);
687            let _ = new_f;
688        }
689
690        Some(e_new)
691    }
692
693    /// tessMeshZapFace: destroy a face and remove it from the global face list.
694    /// All edges of fZap get lface = INVALID. Edges whose rface is also INVALID
695    /// are deleted entirely.
696    pub fn zap_face(&mut self, f_zap: FaceIdx) {
697        let e_start = self.faces[f_zap as usize].an_edge;
698        let mut e_next = self.edges[e_start as usize].lnext;
699
700        loop {
701            let e = e_next;
702            e_next = self.edges[e as usize].lnext;
703
704            self.edges[e as usize].lface = INVALID;
705
706            let e_rface = self.rface(e);
707            if e_rface == INVALID {
708                // Delete the edge
709                let e_onext = self.edges[e as usize].onext;
710                if e_onext == e {
711                    let e_org = self.edges[e as usize].org;
712                    if e_org != INVALID {
713                        self.kill_vertex(e_org, INVALID);
714                    }
715                } else {
716                    let e_org = self.edges[e as usize].org;
717                    if e_org != INVALID {
718                        self.verts[e_org as usize].an_edge = e_onext;
719                    }
720                    let e_oprev = self.oprev(e);
721                    Mesh::do_splice(&mut self.edges, e, e_oprev);
722                }
723
724                let e_sym = e ^ 1;
725                let e_sym_onext = self.edges[e_sym as usize].onext;
726                if e_sym_onext == e_sym {
727                    let e_sym_org = self.edges[e_sym as usize].org;
728                    if e_sym_org != INVALID {
729                        self.kill_vertex(e_sym_org, INVALID);
730                    }
731                } else {
732                    let e_sym_org = self.edges[e_sym as usize].org;
733                    if e_sym_org != INVALID {
734                        self.verts[e_sym_org as usize].an_edge = e_sym_onext;
735                    }
736                    let e_sym_oprev = self.oprev(e_sym);
737                    Mesh::do_splice(&mut self.edges, e_sym, e_sym_oprev);
738                }
739
740                self.kill_edge(e);
741            }
742
743            if e == e_start {
744                break;
745            }
746        }
747
748        // Delete from face list
749        let f_prev = self.faces[f_zap as usize].prev;
750        let f_next = self.faces[f_zap as usize].next;
751        self.faces[f_prev as usize].next = f_next;
752        self.faces[f_next as usize].prev = f_prev;
753        self.faces[f_zap as usize].next = INVALID;
754        self.faces[f_zap as usize].prev = INVALID;
755        self.faces[f_zap as usize].an_edge = INVALID;
756    }
757
758    /// Count vertices in a face loop.
759    pub fn count_face_verts(&self, f: FaceIdx) -> usize {
760        let e_start = self.faces[f as usize].an_edge;
761        let mut e = e_start;
762        let mut n = 0;
763        loop {
764            n += 1;
765            e = self.edges[e as usize].lnext;
766            if e == e_start {
767                break;
768            }
769        }
770        n
771    }
772
773    /// tessMeshMergeConvexFaces: merge convex adjacent faces if the result
774    /// would have <= maxVertsPerFace vertices.
775    pub fn merge_convex_faces(&mut self, max_verts_per_face: usize) -> bool {
776        let mut e = self.edges[E_HEAD as usize].next;
777        while e != E_HEAD {
778            let e_next = self.edges[e as usize].next;
779            let e_sym = e ^ 1;
780
781            let e_lface = self.edges[e as usize].lface;
782            let e_sym_lface = self.edges[e_sym as usize].lface;
783
784            if e_lface == INVALID
785                || !self.faces[e_lface as usize].inside
786                || e_sym_lface == INVALID
787                || !self.faces[e_sym_lface as usize].inside
788            {
789                e = e_next;
790                continue;
791            }
792
793            let left_nv = self.count_face_verts(e_lface);
794            let right_nv = self.count_face_verts(e_sym_lface);
795            if left_nv + right_nv - 2 > max_verts_per_face {
796                e = e_next;
797                continue;
798            }
799
800            // Check convexity: va--vb--vc and vd--ve--vf must be CCW
801            let va = self.edges[self.lprev(e) as usize].org;
802            let vb = self.edges[e as usize].org;
803            let vc_edge = self.edges[e_sym as usize].lnext;
804            let vc = self.dst(vc_edge);
805
806            let vd = self.edges[self.lprev(e_sym) as usize].org;
807            let ve = self.edges[e_sym as usize].org;
808            let vf_edge = self.edges[e as usize].lnext;
809            let vf = self.dst(vf_edge);
810
811            let convex = vert_ccw(
812                self.verts[va as usize].s,
813                self.verts[va as usize].t,
814                self.verts[vb as usize].s,
815                self.verts[vb as usize].t,
816                self.verts[vc as usize].s,
817                self.verts[vc as usize].t,
818            ) && vert_ccw(
819                self.verts[vd as usize].s,
820                self.verts[vd as usize].t,
821                self.verts[ve as usize].s,
822                self.verts[ve as usize].t,
823                self.verts[vf as usize].s,
824                self.verts[vf as usize].t,
825            );
826
827            if convex {
828                let actual_next = if e == e_next || e == e_next ^ 1 {
829                    self.edges[e_next as usize].next
830                } else {
831                    e_next
832                };
833                if !self.delete_edge(e) {
834                    return false;
835                }
836                e = actual_next;
837                continue;
838            }
839
840            e = e_next;
841        }
842        true
843    }
844
845    /// tessMeshFlipEdge: flip an internal edge (used for Delaunay refinement).
846    pub fn flip_edge(&mut self, edge: EdgeIdx) {
847        let a0 = edge;
848        let a1 = self.edges[a0 as usize].lnext;
849        let a2 = self.edges[a1 as usize].lnext;
850        let b0 = edge ^ 1;
851        let b1 = self.edges[b0 as usize].lnext;
852        let b2 = self.edges[b1 as usize].lnext;
853
854        let a_org = self.edges[a0 as usize].org;
855        let a_opp = self.edges[a2 as usize].org;
856        let b_org = self.edges[b0 as usize].org;
857        let b_opp = self.edges[b2 as usize].org;
858
859        let fa = self.edges[a0 as usize].lface;
860        let fb = self.edges[b0 as usize].lface;
861
862        self.edges[a0 as usize].org = b_opp;
863        self.edges[a0 as usize].onext = self.edges[b1 as usize].onext ^ 1; // b1->Sym
864        self.edges[b0 as usize].org = a_opp;
865        self.edges[b0 as usize].onext = self.edges[a1 as usize].onext ^ 1; // a1->Sym
866        self.edges[a2 as usize].onext = b0;
867        self.edges[b2 as usize].onext = a0;
868        self.edges[b1 as usize].onext = self.edges[a2 as usize].onext ^ 1; // a2->Sym... wait
869
870        // Redo using correct flip logic from C code:
871        self.edges[a0 as usize].lnext = a2;
872        self.edges[a2 as usize].lnext = b1;
873        self.edges[b1 as usize].lnext = a0;
874
875        self.edges[b0 as usize].lnext = b2;
876        self.edges[b2 as usize].lnext = a1;
877        self.edges[a1 as usize].lnext = b0;
878
879        self.edges[a1 as usize].lface = fb;
880        self.edges[b1 as usize].lface = fa;
881
882        self.faces[fa as usize].an_edge = a0;
883        self.faces[fb as usize].an_edge = b0;
884
885        if self.verts[a_org as usize].an_edge == a0 {
886            self.verts[a_org as usize].an_edge = b1;
887        }
888        if self.verts[b_org as usize].an_edge == b0 {
889            self.verts[b_org as usize].an_edge = a1;
890        }
891    }
892
893    /// tessMeshSetWindingNumber: reset winding numbers.
894    pub fn set_winding_number(&mut self, value: i32, keep_only_boundary: bool) -> bool {
895        let mut e = self.edges[E_HEAD as usize].next;
896        while e != E_HEAD {
897            let e_next = self.edges[e as usize].next;
898            let e_lface = self.edges[e as usize].lface;
899            let e_rface = self.rface(e);
900
901            let lf_inside = if e_lface != INVALID {
902                self.faces[e_lface as usize].inside
903            } else {
904                false
905            };
906            let rf_inside = if e_rface != INVALID {
907                self.faces[e_rface as usize].inside
908            } else {
909                false
910            };
911
912            if rf_inside != lf_inside {
913                self.edges[e as usize].winding = if lf_inside { value } else { -value };
914            } else if !keep_only_boundary {
915                self.edges[e as usize].winding = 0;
916            } else if !self.delete_edge(e) {
917                return false;
918            }
919
920            e = e_next;
921        }
922        true
923    }
924
925    /// Discard all exterior faces (zap them).
926    pub fn discard_exterior(&mut self) {
927        let mut f = self.faces[F_HEAD as usize].next;
928        while f != F_HEAD {
929            let next = self.faces[f as usize].next;
930            if !self.faces[f as usize].inside {
931                self.zap_face(f);
932            }
933            f = next;
934        }
935    }
936
937    /// Tessellate a single monotone region (face).
938    /// The face must be a CCW-oriented simple polygon.
939    pub fn tessellate_mono_region(&mut self, face: FaceIdx) -> bool {
940        use crate::geom::{edge_sign, vert_leq};
941
942        let mut up = self.faces[face as usize].an_edge;
943        assert!(
944            self.edges[up as usize].lnext != up
945                && self.edges[self.edges[up as usize].lnext as usize].lnext != up,
946            "face must have at least 3 edges"
947        );
948
949        // Find the edge whose origin vertex is rightmost (largest s).
950        // VertLeq(Dst, Org) means Dst <= Org (going left = bad), so we want
951        // to find an edge where the Org is the rightmost.
952        loop {
953            let up_dst = self.dst(up);
954            let up_org = self.edges[up as usize].org;
955            if !vert_leq(
956                self.verts[up_dst as usize].s,
957                self.verts[up_dst as usize].t,
958                self.verts[up_org as usize].s,
959                self.verts[up_org as usize].t,
960            ) {
961                break;
962            }
963            up = self.lprev(up);
964        }
965        loop {
966            let up_org = self.edges[up as usize].org;
967            let up_dst = self.dst(up);
968            if !vert_leq(
969                self.verts[up_org as usize].s,
970                self.verts[up_org as usize].t,
971                self.verts[up_dst as usize].s,
972                self.verts[up_dst as usize].t,
973            ) {
974                break;
975            }
976            up = self.edges[up as usize].lnext;
977        }
978
979        let mut lo = self.lprev(up);
980
981        while self.edges[up as usize].lnext != lo {
982            let up_dst = self.dst(up);
983            let lo_org = self.edges[lo as usize].org;
984            if vert_leq(
985                self.verts[up_dst as usize].s,
986                self.verts[up_dst as usize].t,
987                self.verts[lo_org as usize].s,
988                self.verts[lo_org as usize].t,
989            ) {
990                // up->Dst is on the left; make triangles from lo->Org
991                while self.edges[lo as usize].lnext != up {
992                    let lo_lnext = self.edges[lo as usize].lnext;
993                    let lo_lnext_dst = self.dst(lo_lnext);
994                    let lo_org2 = self.edges[lo as usize].org;
995                    let lo_dst = self.dst(lo);
996                    let goes_left = self.edge_goes_left(lo_lnext);
997                    let sign_val = edge_sign(
998                        self.verts[lo_org2 as usize].s,
999                        self.verts[lo_org2 as usize].t,
1000                        self.verts[lo_dst as usize].s,
1001                        self.verts[lo_dst as usize].t,
1002                        self.verts[lo_lnext_dst as usize].s,
1003                        self.verts[lo_lnext_dst as usize].t,
1004                    );
1005                    if !goes_left && sign_val > 0.0 {
1006                        break;
1007                    }
1008                    let temp = match self.connect(lo_lnext, lo) {
1009                        Some(e) => e,
1010                        None => return false,
1011                    };
1012                    lo = temp ^ 1;
1013                }
1014                lo = self.lprev(lo);
1015            } else {
1016                // lo->Org is on the left; make CCW triangles from up->Dst
1017                while self.edges[lo as usize].lnext != up {
1018                    let up_lprev = self.lprev(up);
1019                    let up_lprev_org = self.edges[up_lprev as usize].org;
1020                    let up_dst2 = self.dst(up);
1021                    let up_org2 = self.edges[up as usize].org;
1022                    let goes_right = self.edge_goes_right(up_lprev);
1023                    let sign_val = edge_sign(
1024                        self.verts[up_dst2 as usize].s,
1025                        self.verts[up_dst2 as usize].t,
1026                        self.verts[up_org2 as usize].s,
1027                        self.verts[up_org2 as usize].t,
1028                        self.verts[up_lprev_org as usize].s,
1029                        self.verts[up_lprev_org as usize].t,
1030                    );
1031                    if !goes_right && sign_val < 0.0 {
1032                        break;
1033                    }
1034                    let temp = match self.connect(up, up_lprev) {
1035                        Some(e) => e,
1036                        None => return false,
1037                    };
1038                    up = temp ^ 1;
1039                }
1040                up = self.edges[up as usize].lnext;
1041            }
1042        }
1043
1044        // Tessellate the remaining fan from the leftmost vertex.
1045        assert!(self.edges[lo as usize].lnext != up);
1046        while self.edges[self.edges[lo as usize].lnext as usize].lnext != up {
1047            let lo_lnext = self.edges[lo as usize].lnext;
1048            let temp = match self.connect(lo_lnext, lo) {
1049                Some(e) => e,
1050                None => return false,
1051            };
1052            lo = temp ^ 1;
1053        }
1054
1055        true
1056    }
1057
1058    /// Tessellate all interior monotone regions.
1059    pub fn tessellate_interior(&mut self) -> bool {
1060        let mut f = self.faces[F_HEAD as usize].next;
1061        while f != F_HEAD {
1062            let next = self.faces[f as usize].next;
1063            if self.faces[f as usize].inside && !self.tessellate_mono_region(f) {
1064                return false;
1065            }
1066            f = next;
1067        }
1068        true
1069    }
1070
1071}
1072
1073impl Default for Mesh {
1074    fn default() -> Self {
1075        Self::new()
1076    }
1077}
1078
1079#[cfg(test)]
1080mod tests {
1081    use super::*;
1082
1083    #[test]
1084    fn make_edge_creates_single_edge() {
1085        let mut mesh = Mesh::new();
1086        let e = mesh.make_edge().unwrap();
1087        // Should have 3 vertices (vHead + 2 new), 2 faces (fHead + 1 new), 4 edges (eHead pair + 1 pair)
1088        assert_eq!(mesh.verts.len(), 3);
1089        assert_eq!(mesh.faces.len(), 2);
1090        assert_eq!(mesh.edges.len(), 4);
1091        // Edge and its sym should have different orgs
1092        let org1 = mesh.edges[e as usize].org;
1093        let org2 = mesh.edges[(e ^ 1) as usize].org;
1094        assert_ne!(org1, org2);
1095        assert_ne!(org1, INVALID);
1096        assert_ne!(org2, INVALID);
1097    }
1098
1099    #[test]
1100    fn sym_involution() {
1101        // sym(sym(e)) == e
1102        for e in 0u32..16 {
1103            assert_eq!(sym(sym(e)), e);
1104        }
1105    }
1106
1107    #[test]
1108    fn vertex_list_circular() {
1109        let mut mesh = Mesh::new();
1110        mesh.make_edge().unwrap();
1111        // vHead.next.next should eventually circle back
1112        let first = mesh.verts[V_HEAD as usize].next;
1113        assert_ne!(first, V_HEAD);
1114        let second = mesh.verts[first as usize].next;
1115        assert_ne!(second, INVALID);
1116    }
1117}