code wiki / (root) / nx_dcc_slice_watertight_gate.nx

nx_dcc_slice_watertight_gate.nx source

↩ module page · 94 lines · 4932 B

1// nx_dcc_slice_watertight_gate.nx -- REGRESSION GATE for the two slicer fixes that 2// let DCC-authored slanted/curved geometry print: 3// (1) canonical edge-intersection rounding in nx_slice_edge_at_z (shared edges 4// compute the IDENTICAL crossing point regardless of traversal direction), 5// (2) the BVH right-child-adjacency fix in nx_bvh_fill_subtree (every triangle 6// is visited EXACTLY once -- no duplicate, no orphan). 7// Both bugs manifested as non-closing contours on non-axis-aligned meshes. This 8// gate asserts WATERTIGHT slicing (closed contours, exact segment counts) on a 9// pyramid, octahedron, and icosphere -- the shapes that exposed the bugs. A 10// 1-segment dup or a dropped face re-opens a contour and trips n_open. expect_exit: 0. 11 12import "nx_syscalls.nx" 13import "nx_mesh.nx" 14import "nx_mesh_edit.nx" 15import "nx_mesh_sculpt.nx" 16import "nx_bvh.nx" 17import "nx_slice_plane.nx" 18import "nx_slice_contour.nx" 19 20func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 21func wn(v: i64) -> i64 { 22 let b: *u8 = sys_mmap(28); var m: i64 = v 23 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 24 let t: *u8 = sys_mmap(28); var k: i64 = 0 25 if m == 0 { t[0] = 48 as u8; k = 1 } 26 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 27 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 28 sys_write(1, b, k); return 0 29} 30func chk(cond: i64, pass: *i64, fail: *i64, label: *u8) -> i64 { 31 if cond == 1 { pass[0] = pass[0] + 1; w(" ok " as *u8); w(label); w("\n" as *u8) } 32 else { fail[0] = fail[0] + 1; w(" XX " as *u8); w(label); w("\n" as *u8) } 33 return 0 34} 35func eqi(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 } 36 37// slice mesh at plane_z; write n_segments,n_polys,n_open into out3 38func slice_stats(model: *NxMesh, plane_z: i64, out3: *i64) -> i64 { 39 let bvh: *NxBvh = nx_bvh_build(model) 40 let soup: *NxSliceSoup = nx_slice_plane(model, bvh, plane_z) 41 let c: *NxSliceContours = nx_slice_contour_build(soup) 42 out3[0] = soup.n_segments 43 out3[1] = c.n_polys 44 out3[2] = c.n_open 45 return 0 46} 47 48func main() -> i64 { 49 let pass: *i64 = (sys_mmap(8)) as *i64 50 let fail: *i64 = (sys_mmap(8)) as *i64 51 pass[0] = 0 52 fail[0] = 0 53 let st: *i64 = (sys_mmap(32)) as *i64 54 w("=== nx_dcc_slice_watertight (slanted/curved geometry slices closed) ===\n" as *u8) 55 56 // PYRAMID: a horizontal cut is a 4-sided square -> exactly 4 segments, 1 closed loop. 57 let py: *NxMesh = nx_mesh_make_pyramid(163840, 327680, 0) 58 slice_stats(py, 81920, st) 59 w(" pyramid z=5mm: segs=" as *u8); wn(st[0]); w(" polys=" as *u8); wn(st[1]); w(" open=" as *u8); wn(st[2]); w("\n" as *u8) 60 chk(eqi(st[0], 4), pass, fail, "pyramid: exactly 4 segments (no dup, no drop)" as *u8) 61 chk(eqi(st[1], 1), pass, fail, "pyramid: exactly 1 contour" as *u8) 62 chk(eqi(st[2], 0), pass, fail, "pyramid: contour CLOSED (n_open=0)" as *u8) 63 64 // OCTAHEDRON near its apex -> a 4-sided cross-section, closed. 65 let oc: *NxMesh = nx_mesh_make_octahedron(163840, 0) 66 nx_mesh_translate(oc, 0, 0, 163840) // bottom apex -> z=0 67 slice_stats(oc, 81920, st) 68 w(" octahedron z=5mm: segs=" as *u8); wn(st[0]); w(" polys=" as *u8); wn(st[1]); w(" open=" as *u8); wn(st[2]); w("\n" as *u8) 69 chk(eqi(st[0], 4), pass, fail, "octahedron: exactly 4 segments" as *u8) 70 chk(eqi(st[2], 0), pass, fail, "octahedron: contour CLOSED" as *u8) 71 72 // ICOSPHERE subdiv=2: a dense curved mesh -- every layer must close. 73 let sp: *NxMesh = nx_mesh_make_icosphere(163840, 2, 0) 74 nx_mesh_translate(sp, 0, 0, 163840) // span 0..2R 75 slice_stats(sp, 81920, st) // lower band 76 w(" icosphere z=5mm: segs=" as *u8); wn(st[0]); w(" polys=" as *u8); wn(st[1]); w(" open=" as *u8); wn(st[2]); w("\n" as *u8) 77 chk(st[1] >= 1, pass, fail, "icosphere low band: >=1 contour" as *u8) 78 chk(eqi(st[2], 0), pass, fail, "icosphere low band: ALL contours CLOSED" as *u8) 79 slice_stats(sp, 163840, st) // equator (widest) 80 w(" icosphere z=10mm: segs=" as *u8); wn(st[0]); w(" polys=" as *u8); wn(st[1]); w(" open=" as *u8); wn(st[2]); w("\n" as *u8) 81 chk(eqi(st[2], 0), pass, fail, "icosphere equator: ALL contours CLOSED" as *u8) 82 slice_stats(sp, 245760, st) // upper band 83 chk(eqi(st[2], 0), pass, fail, "icosphere high band: ALL contours CLOSED" as *u8) 84 85 // CUBE: must still be watertight (regression guard for the BVH change). 86 let cu: *NxMesh = nx_mesh_make_cube(163840, 0) 87 nx_mesh_translate(cu, 0, 0, 163840) 88 slice_stats(cu, 81920, st) 89 chk(eqi(st[2], 0), pass, fail, "cube still watertight (BVH-change regression guard)" as *u8) 90 91 w("=== VERDICT pass=" as *u8); wn(pass[0]); w(" fail=" as *u8); wn(fail[0]); w(" ===\n" as *u8) 92 if fail[0] == 0 { return 0 } 93 return 1 94}