nx_meshcheck_gate.nx source
↩ module page · 202 lines · 11846 B
1// nx_meshcheck_gate.nx -- proves the mesh integrity sweep, in BOTH directions, per defect class.
2//
3// THE POSITIVE CONTROL IS A TETRAHEDRON, and it is chosen because it is the smallest object for which
4// every property under test is simultaneously non-trivial: 4 vertices, 4 faces, 6 edges each shared by
5// exactly two faces traversing it in OPPOSITE directions, no loose vertices, no degeneracies, and an
6// Euler characteristic of exactly 2. A cube would work too and would hide a winding bug behind more
7// symmetry; a single triangle would pass most teeth vacuously because it has no shared edge at all.
8//
9// EVERY DEFECT CLASS GETS ITS OWN PLANTED MUTANT, because the classes have DIFFERENT REMEDIES and a
10// detector that fires on all of them identically is one counter wearing six names. Each mutant is
11// built at runtime from the same clean tetrahedron, so a tooth that fires is firing on exactly one
12// injected difference.
13import "nx_syscalls.nx"
14import "nx_gate_verdict.nx"
15import "nx_meshcheck.nx"
16
17const MG_U: i64 = 1000 // one millimetre in the micrometre units this fixture uses
18const MG_SCRATCH: i64 = 64
19
20func mg_out() -> *i64 { return sys_mmap(MC_O_SLOTS * MC_I64) as *i64 }
21func mg_list() -> *i64 { return sys_mmap(mc_list_slots() * MC_I64) as *i64 }
22
23// the clean tetrahedron: verts (0,0,0) (u,0,0) (0,u,0) (0,0,u)
24func mg_tet_verts(extra: i64) -> *i64 {
25 let v: *i64 = sys_mmap((4 + extra) * 3 * MC_I64) as *i64
26 v[0]=0; v[1]=0; v[2]=0
27 v[3]=MG_U; v[4]=0; v[5]=0
28 v[6]=0; v[7]=MG_U; v[8]=0
29 v[9]=0; v[10]=0; v[11]=MG_U
30 var i: i64 = 0
31 while i < extra * 3 { v[12 + i] = MG_U + MG_U; i = i + 1 }
32 return v
33}
34// faces wound consistently outward: every edge appears twice, in opposite directions
35func mg_tet_tris(extra: i64) -> *i64 {
36 let t: *i64 = sys_mmap((4 + extra) * 3 * MC_I64) as *i64
37 t[0]=0; t[1]=2; t[2]=1
38 t[3]=0; t[4]=1; t[5]=3
39 t[6]=0; t[7]=3; t[8]=2
40 t[9]=1; t[10]=2; t[11]=3
41 return t
42}
43
44func mg_eq(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 }
45func mg_pos(a: i64) -> i64 { if a > 0 { return 1 } return 0 }
46func mg_zero(a: i64) -> i64 { if a == 0 { return 1 } return 0 }
47func mg_eq2(a: i64, b: i64, c: i64, d: i64) -> i64 { if a == b { if c == d { return 1 } } return 0 }
48func mg_eq3(a: i64, b: i64, c: i64, d: i64, e: i64, f: i64) -> i64 {
49 if a == b { if c == d { if e == f { return 1 } } } return 0
50}
51
52func main() -> i64 {
53 let ctr: *i64 = gv_ctr()
54 gv_head("nx_meshcheck_gate -- mesh integrity: non-manifold edges, winding, loose vertices, degeneracy, duplicates" as *u8)
55
56 // ---- POSITIVE CONTROL --------------------------------------------------------------------------
57 let o: *i64 = mg_out()
58 let l: *i64 = mg_list()
59 let tv: *i64 = mg_tet_verts(0)
60 let tt: *i64 = mg_tet_tris(0)
61 let clean: i64 = mc_check(tv, 4, tt, 4, o, l)
62 gv_subjects("triangles in the clean control" as *u8, o[MC_O_TRIS], ctr)
63 gv_check("T1 a correctly wound closed tetrahedron reads CLEAN with zero defects of every class" as *u8,
64 mg_eq2(clean, MC_CLEAN, mc_defect_total(o), 0), ctr)
65 gv_check("T2 its six edges are each shared by exactly two faces -- zero boundary, zero non-manifold" as *u8,
66 mg_eq3(o[MC_O_EDGES], 6, o[MC_O_BOUNDARY], 0, o[MC_O_NONMANIFOLD], 0), ctr)
67 gv_check("T3 it is WATERTIGHT, and Euler is REPORTED as 2 rather than used as the verdict" as *u8,
68 mg_eq2(mc_watertight(o), 1, o[MC_O_EULER], 2), ctr)
69
70 // ---- THE EMPTY SET -----------------------------------------------------------------------------
71 let oe: *i64 = mg_out()
72 let le: *i64 = mg_list()
73 let empty: i64 = mc_check(tv, 4, tt, 0, oe, le)
74 gv_check("neg-control-a-mesh-with-ZERO-faces-is-UNMEASURABLE-never-CLEAN" as *u8,
75 mg_eq(empty, MC_UNMEASURABLE), ctr)
76
77 // ---- AN INDEX THAT CANNOT BE DEREFERENCED ------------------------------------------------------
78 // Checked FIRST inside the organ, because every later pass reads through these indices: validating
79 // them afterwards would mean reading out of bounds to discover they were out of bounds.
80 let ob: *i64 = mg_out()
81 let lb: *i64 = mg_list()
82 let bt: *i64 = mg_tet_tris(0)
83 bt[11] = 99
84 let badv: i64 = mc_check(tv, 4, bt, 4, ob, lb)
85 gv_check("neg-control-an-out-of-range-vertex-index-returns-INVALID-and-NAMES-the-offending-triangle" as *u8,
86 mg_eq3(badv, MC_INVALID, ob[MC_O_BADINDEX], 1, mc_list_get(lb, MC_L_BADINDEX, 0), 3), ctr)
87
88 // ---- NON-MANIFOLD: a third face on an existing edge ---------------------------------------------
89 let ov: *i64 = mg_out()
90 let lv: *i64 = mg_list()
91 let nv5: *i64 = mg_tet_verts(1)
92 let nt5: *i64 = mg_tet_tris(1)
93 nt5[12]=0; nt5[13]=1; nt5[14]=4
94 let nm: i64 = mc_check(nv5, 5, nt5, 5, ov, lv)
95 gv_check("T6 a third face on edge 0-1 is counted as exactly ONE non-manifold edge, not as three" as *u8,
96 mg_eq2(nm, MC_DEFECTS, ov[MC_O_NONMANIFOLD], 1), ctr)
97 gv_bite("T7 non-manifold edge detection" as *u8, mg_pos(ov[MC_O_NONMANIFOLD]), mg_pos(o[MC_O_NONMANIFOLD]), ctr)
98 // the same mutant opens two boundary edges, and boundary is DELIBERATELY not a defect
99 gv_check("T8 the same mutant opens two BOUNDARY edges, reported on their own axis and not as defects" as *u8,
100 mg_eq(ov[MC_O_BOUNDARY], 2), ctr)
101
102 // ---- WINDING: one face reversed ------------------------------------------------------------------
103 // The deepest of the classes: the mesh stays closed and manifold, every edge still has exactly two
104 // faces, and a deviation ruler comparing it to a reference would report perfect agreement. Only the
105 // traversal direction disagrees, and it renders as an inside-out patch.
106 let ow: *i64 = mg_out()
107 let lw: *i64 = mg_list()
108 let wt: *i64 = mg_tet_tris(0)
109 wt[9]=1; wt[10]=3; wt[11]=2
110 let wd: i64 = mc_check(tv, 4, wt, 4, ow, lw)
111 gv_check("T9 reversing ONE face leaves the mesh closed and manifold but flags its three shared edges" as *u8,
112 mg_eq3(wd, MC_DEFECTS, ow[MC_O_WINDING], 3, ow[MC_O_NONMANIFOLD], 0), ctr)
113 gv_check("T10 a wound-wrong mesh is NOT watertight even though it has zero boundary edges" as *u8,
114 mg_eq2(mc_watertight(ow), 0, ow[MC_O_BOUNDARY], 0), ctr)
115 gv_bite("T11 winding-consistency detection" as *u8, mg_pos(ow[MC_O_WINDING]), mg_pos(o[MC_O_WINDING]), ctr)
116
117 // ---- LOOSE VERTICES ------------------------------------------------------------------------------
118 let ol: *i64 = mg_out()
119 let ll: *i64 = mg_list()
120 let lv5: *i64 = mg_tet_verts(1)
121 let lt4: *i64 = mg_tet_tris(1)
122 let lo: i64 = mc_check(lv5, 5, lt4, 4, ol, ll)
123 gv_check("T12 a vertex no triangle references is found and NAMED by index, not merely counted" as *u8,
124 mg_eq3(lo, MC_DEFECTS, ol[MC_O_LOOSE], 1, mc_list_get(ll, MC_L_LOOSE, 0), 4), ctr)
125 gv_bite("T13 loose-vertex detection" as *u8, mg_pos(ol[MC_O_LOOSE]), mg_pos(o[MC_O_LOOSE]), ctr)
126
127 // ---- THE TWO DEGENERACIES ARE DIFFERENT DEFECTS --------------------------------------------------
128 // A triangle naming one vertex twice is BAD DATA. Three distinct vertices that are collinear is
129 // GOOD DATA describing a zero-area shape. Same black nothing on screen, different repair -- so a
130 // single degenerate counter would send half the readers to fix the wrong thing.
131 let od: *i64 = mg_out()
132 let ld: *i64 = mg_list()
133 let dt: *i64 = mg_tet_tris(0)
134 dt[0]=0; dt[1]=0; dt[2]=1
135 let dg: i64 = mc_check(tv, 4, dt, 4, od, ld)
136 gv_check("T14 a triangle naming one vertex twice counts as TOPOLOGICAL degeneracy only" as *u8,
137 mg_eq3(dg, MC_DEFECTS, od[MC_O_DEGEN_TOPO], 1, od[MC_O_DEGEN_AREA], 0), ctr)
138
139 // three DISTINCT but collinear vertices: exact integer cross product, no epsilon anywhere
140 let ca: *i64 = sys_mmap(3 * 3 * MC_I64) as *i64
141 ca[0]=0; ca[1]=0; ca[2]=0
142 ca[3]=MG_U; ca[4]=0; ca[5]=0
143 ca[6]=MG_U+MG_U; ca[7]=0; ca[8]=0
144 let ct: *i64 = sys_mmap(3 * MC_I64) as *i64
145 ct[0]=0; ct[1]=1; ct[2]=2
146 let oa: *i64 = mg_out()
147 let la: *i64 = mg_list()
148 let ar: i64 = mc_check(ca, 3, ct, 1, oa, la)
149 gv_check("T15 three DISTINCT collinear vertices count as AREA degeneracy only -- proven by exact integer cross product, no epsilon" as *u8,
150 mg_eq3(ar, MC_DEFECTS, oa[MC_O_DEGEN_AREA], 1, oa[MC_O_DEGEN_TOPO], 0), ctr)
151 gv_bite("T16 the two degeneracy classes discriminate" as *u8,
152 mg_eq2(od[MC_O_DEGEN_TOPO], 1, oa[MC_O_DEGEN_AREA], 1),
153 mg_pos(o[MC_O_DEGEN_TOPO] + o[MC_O_DEGEN_AREA]), ctr)
154
155 // ---- DUPLICATE FACES -----------------------------------------------------------------------------
156 let op: *i64 = mg_out()
157 let lp: *i64 = mg_list()
158 let pt: *i64 = mg_tet_tris(1)
159 pt[12]=1; pt[13]=0; pt[14]=2
160 let du: i64 = mc_check(tv, 4, pt, 5, op, lp)
161 gv_check("T17 two triangles over the same three vertices in a different ORDER are still duplicates" as *u8,
162 mg_eq2(op[MC_O_DUPFACE], 1, op[MC_O_DUPCHECKED], 1), ctr)
163 gv_bite("T18 duplicate-face detection" as *u8, mg_pos(op[MC_O_DUPFACE]), mg_pos(o[MC_O_DUPFACE]), ctr)
164
165 // ---- AN OPEN SURFACE IS NOT A BROKEN ONE ---------------------------------------------------------
166 // The deliberate non-defect, and the tooth that stops this organ becoming a false-positive machine.
167 // A plane, a cloth patch and a cut-away anatomical section are all legitimately open. Watertightness
168 // is a SEPARATE question asked separately, so a caller who needs it opts in rather than having a
169 // whole class of valid geometry condemned by default.
170 let pv: *i64 = sys_mmap(4 * 3 * MC_I64) as *i64
171 pv[0]=0; pv[1]=0; pv[2]=0
172 pv[3]=MG_U; pv[4]=0; pv[5]=0
173 pv[6]=MG_U; pv[7]=MG_U; pv[8]=0
174 pv[9]=0; pv[10]=MG_U; pv[11]=0
175 let ptr2: *i64 = sys_mmap(2 * 3 * MC_I64) as *i64
176 ptr2[0]=0; ptr2[1]=1; ptr2[2]=2
177 ptr2[3]=0; ptr2[4]=2; ptr2[5]=3
178 let opl: *i64 = mg_out()
179 let lpl: *i64 = mg_list()
180 let pl: i64 = mc_check(pv, 4, ptr2, 2, opl, lpl)
181 gv_check("neg-control-an-OPEN-square-is-CLEAN-with-four-boundary-edges-because-open-is-not-broken" as *u8,
182 mg_eq3(pl, MC_CLEAN, opl[MC_O_BOUNDARY], 4, mc_defect_total(opl), 0), ctr)
183 gv_check("T20 the same open square is correctly NOT watertight -- the two questions stay separate" as *u8,
184 mg_eq(mc_watertight(opl), 0), ctr)
185
186 // ---- COVERAGE IS ON THE RECORD -------------------------------------------------------------------
187 // The duplicate-face check is bounded by an i64 cube root and REFUSES above it rather than silently
188 // skipping. That refusal path is NOT exercised here and I am saying so rather than implying it is:
189 // reaching it needs over two million vertices, and manufacturing that to score a tooth would cost
190 // more than the tooth is worth. What IS asserted is that the flag reads 1 on every fixture above,
191 // so a future zero is visible as a refusal rather than passing as a clean result.
192 gv_check("T21 the duplicate-face check REPORTS that it ran on every fixture -- a skip could not pass as a pass" as *u8,
193 mg_eq3(o[MC_O_DUPCHECKED], 1, op[MC_O_DUPCHECKED], 1, opl[MC_O_DUPCHECKED], 1), ctr)
194 gv_check("T22 no worklist above overflowed, so every count published here is a whole set and not a prefix" as *u8,
195 mg_eq3(o[MC_O_LIST_PREFIX], 0, ov[MC_O_LIST_PREFIX], 0, ow[MC_O_LIST_PREFIX], 0), ctr)
196
197 let rc: i64 = gv_verdict("MESHCHECK-GATE" as *u8, ctr,
198 "every defect class fires on its own planted mutant and stays silent on the clean control, the two degeneracies discriminate, an open surface is correctly not a defect, and the empty mesh abstains rather than passing" as *u8)
199 gv_journal("nx_meshcheck_gate" as *u8, ctr[0], ctr[1], mg_zero(rc))
200 sys_exit(rc)
201 return rc
202}