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}