code wiki / (root) / nx_csg_torus_test.nx

nx_csg_torus_test.nx source

↩ module page · 94 lines · 4291 B

1// nx_csg_torus_test.nx -- KAT gate for the torus SDF primitive (genus-1 solid). 2// Proves: valid mesh, watertight, the through-hole shows as 2 concentric loops at a 3// mid slice (the topological signature of a torus), and it prints. expect_exit: 0. 4 5import "nx_syscalls.nx" 6import "nx_mesh.nx" 7import "nx_mesh_edit.nx" 8import "nx_sdf.nx" 9import "nx_csg.nx" 10import "nx_bvh.nx" 11import "nx_slice_plane.nx" 12import "nx_slice_contour.nx" 13import "nx_stl_write.nx" 14import "nx_stl.nx" 15import "nx_machine_graph.nx" 16import "nx_material_profile.nx" 17import "nx_gcode_emit.nx" 18import "nx_slice_pipeline.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 smoke_count(buf: *u8, len: i64, needle: *u8) -> i64 { 31 var nlen: i64 = 0; while needle[nlen] != 0 { nlen = nlen + 1 } 32 if len < nlen { return 0 } 33 var count: i64 = 0; var i: i64 = 0; let last: i64 = len - nlen 34 while i <= last { 35 var j: i64 = 0; var matched: i64 = 1 36 while j < nlen { if buf[i + j] != needle[j] { matched = 0; j = nlen } j = j + 1 } 37 if matched == 1 { count = count + 1 } 38 i = i + 1 39 } 40 return count 41} 42func chk(cond: i64, pass: *i64, fail: *i64, label: *u8) -> i64 { 43 if cond == 1 { pass[0] = pass[0] + 1; w(" ok " as *u8); w(label); w("\n" as *u8) } 44 else { fail[0] = fail[0] + 1; w(" XX " as *u8); w(label); w("\n" as *u8) } 45 return 0 46} 47func eqi(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 } 48 49func main() -> i64 { 50 let pass: *i64 = (sys_mmap(8)) as *i64 51 let fail: *i64 = (sys_mmap(8)) as *i64 52 pass[0] = 0 53 fail[0] = 0 54 let bb: *i64 = (sys_mmap(48)) as *i64 55 let R: i64 = 163840 // 10mm major radius 56 let r: i64 = 65536 // 4mm minor radius 57 w("=== nx_csg torus KAT (genus-1 SDF solid) ===\n" as *u8) 58 59 let m: *NxMesh = nx_csg_torus_mesh(R, r, 24) 60 w(" torus tris=" as *u8); wn(m.n_tris); w("\n" as *u8) 61 chk(m.n_tris > 200, pass, fail, "torus meshed" as *u8) 62 chk(eqi(nx_mesh_validate(m), NX_MESH_OK), pass, fail, "torus mesh valid" as *u8) 63 nx_mesh_aabb(m, bb) 64 w(" AABB x[" as *u8); wn(bb[0]); w("," as *u8); wn(bb[3]); w("] z[" as *u8); wn(bb[2]); w("," as *u8); wn(bb[5]); w("]\n" as *u8) 65 chk(bb[3] >= 220000, pass, fail, "torus outer extent ~ R+r (14mm)" as *u8) 66 chk(bb[3] <= 245000, pass, fail, "torus not over-grown" as *u8) 67 68 // sit on bed, slice through the tube band -> 2 concentric loops (outer + inner) 69 nx_mesh_translate(m, 0, 0, r) 70 let bvh: *NxBvh = nx_bvh_build(m) 71 let soup: *NxSliceSoup = nx_slice_plane(m, bvh, r + 3000) // off-grid mid band 72 let c: *NxSliceContours = nx_slice_contour_build(soup) 73 w(" mid slice: polys=" as *u8); wn(c.n_polys); w(" open=" as *u8); wn(c.n_open); w("\n" as *u8) 74 chk(eqi(c.n_open, 0), pass, fail, "torus slices WATERTIGHT" as *u8) 75 chk(c.n_polys >= 2, pass, fail, "torus hole: mid slice has >=2 concentric loops" as *u8) 76 77 let stl: *u8 = sys_mmap(524288) 78 let n: i64 = nx_stl_write_mesh(stl, m) 79 let res2: *NxStlResult = nx_stl_load_binary(stl, n) 80 chk(eqi(res2.verdict, NX_STL_OK), pass, fail, "torus STL round-trips" as *u8) 81 let qidi: *NxMachineGraph = nx_machine_graph_qidi_xmax3() 82 let pla: *NxMaterialProfile = nx_material_profile_generic_pla() 83 let e: *NxGcodeEmitter = nx_gemit_new(qidi, pla, 3277, 6554, 4194304) 84 nx_gemit_preamble(e) 85 let nl: i64 = nx_slice_pipe_run_v2(e, res2.mesh, 20, 3277) 86 let g1: i64 = smoke_count(e.buf, e.len, "G1 X" as *u8) 87 w(" torus->print: layers=" as *u8); wn(nl); w(" G1=" as *u8); wn(g1); w("\n" as *u8) 88 chk(nl >= 20, pass, fail, "torus sliced" as *u8) 89 chk(g1 >= 300, pass, fail, "torus: real extrusion moves" 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}