nx_cad_prims2_test.nx source
↩ module page · 128 lines · 5580 B
1// nx_cad_prims2_test.nx -- KAT gate for two more primitives: parametric CONE (direct
2// factory) and ROUNDED BOX (SDF edge-rounding). Proves counts/validity, watertight
3// slicing, the rounding actually removes corner material, and both print. expect_exit: 0.
4
5import "nx_syscalls.nx"
6import "nx_mesh.nx"
7import "nx_mesh_edit.nx"
8import "nx_cad.nx"
9import "nx_sdf.nx"
10import "nx_csg.nx"
11import "nx_bvh.nx"
12import "nx_slice_plane.nx"
13import "nx_slice_contour.nx"
14import "nx_stl_write.nx"
15import "nx_stl.nx"
16import "nx_machine_graph.nx"
17import "nx_material_profile.nx"
18import "nx_gcode_emit.nx"
19import "nx_slice_pipeline.nx"
20
21func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
22func wn(v: i64) -> i64 {
23 let b: *u8 = sys_mmap(28); var m: i64 = v
24 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }
25 let t: *u8 = sys_mmap(28); var k: i64 = 0
26 if m == 0 { t[0] = 48 as u8; k = 1 }
27 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
28 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
29 sys_write(1, b, k); return 0
30}
31func smoke_count(buf: *u8, len: i64, needle: *u8) -> i64 {
32 var nlen: i64 = 0; while needle[nlen] != 0 { nlen = nlen + 1 }
33 if len < nlen { return 0 }
34 var count: i64 = 0; var i: i64 = 0; let last: i64 = len - nlen
35 while i <= last {
36 var j: i64 = 0; var matched: i64 = 1
37 while j < nlen { if buf[i + j] != needle[j] { matched = 0; j = nlen } j = j + 1 }
38 if matched == 1 { count = count + 1 }
39 i = i + 1
40 }
41 return count
42}
43func chk(cond: i64, pass: *i64, fail: *i64, label: *u8) -> i64 {
44 if cond == 1 { pass[0] = pass[0] + 1; w(" ok " as *u8); w(label); w("\n" as *u8) }
45 else { fail[0] = fail[0] + 1; w(" XX " as *u8); w(label); w("\n" as *u8) }
46 return 0
47}
48func eqi(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 }
49
50func prints(m: *NxMesh) -> i64 {
51 let stl: *u8 = sys_mmap(1048576)
52 let n: i64 = nx_stl_write_mesh(stl, m)
53 let r: *NxStlResult = nx_stl_load_binary(stl, n)
54 if r.verdict != NX_STL_OK { return 0 }
55 let qidi: *NxMachineGraph = nx_machine_graph_qidi_xmax3()
56 let pla: *NxMaterialProfile = nx_material_profile_generic_pla()
57 let e: *NxGcodeEmitter = nx_gemit_new(qidi, pla, 3277, 6554, 4194304)
58 nx_gemit_preamble(e)
59 nx_slice_pipe_run_v2(e, r.mesh, 20, 3277)
60 return smoke_count(e.buf, e.len, "G1 X" as *u8)
61}
62
63func main() -> i64 {
64 let pass: *i64 = (sys_mmap(8)) as *i64
65 let fail: *i64 = (sys_mmap(8)) as *i64
66 pass[0] = 0
67 fail[0] = 0
68 let bb: *i64 = (sys_mmap(48)) as *i64
69 w("=== nx_cad prims2 KAT (cone + rounded box) ===\n" as *u8)
70
71 // --- CONE: 32-gon base, apex at 20mm ---
72 let cone: *NxMesh = nx_cad_make_cone(163840, 327680, 32, 0)
73 chk(eqi(cone.n_verts, 33), pass, fail, "cone 32+1 = 33 verts" as *u8)
74 chk(eqi(cone.n_tris, 62), pass, fail, "cone 2*32-2 = 62 tris" as *u8)
75 chk(eqi(nx_mesh_validate(cone), NX_MESH_OK), pass, fail, "cone valid" as *u8)
76 nx_mesh_aabb(cone, bb)
77 chk(eqi(bb[2], 0), pass, fail, "cone base on z=0" as *u8)
78 chk(eqi(bb[5], 327680), pass, fail, "cone apex at 20mm" as *u8)
79 let bvh: *NxBvh = nx_bvh_build(cone)
80 let soup: *NxSliceSoup = nx_slice_plane(cone, bvh, 81920 + 3000) // 5mm, off-grid
81 let cc: *NxSliceContours = nx_slice_contour_build(soup)
82 chk(eqi(cc.n_open, 0), pass, fail, "cone slices WATERTIGHT (1 loop)" as *u8)
83 chk(prints(cone) >= 300, pass, fail, "cone prints (real moves)" as *u8)
84
85 // --- ROUNDED BOX: half-extent 10mm, 3mm corner radius ---
86 let H: i64 = 163840
87 let rr: i64 = 49152
88 let rbox: *NxMesh = nx_csg_roundbox_mesh(H, rr, 22)
89 chk(rbox.n_tris > 200, pass, fail, "rounded box meshed" as *u8)
90 chk(eqi(nx_mesh_validate(rbox), NX_MESH_OK), pass, fail, "rounded box valid" as *u8)
91 nx_mesh_aabb(rbox, bb)
92 w(" rbox AABB x[" as *u8); wn(bb[0]); w("," as *u8); wn(bb[3]); w("]\n" as *u8)
93 chk(bb[3] >= 158000, pass, fail, "rounded box reaches ~+10mm at face centre" as *u8)
94 chk(bb[3] <= 167000, pass, fail, "rounded box not over-grown" as *u8)
95
96 // rounding REMOVES corner material vs a sharp box of the same half-extent
97 let sharp: *NxSdfPrim = nx_sdf_make(NX_SDF_BOX, 0, 0, 0, H, H, H)
98 let round: *NxSdfPrim = nx_sdf_make4(NX_SDF_ROUNDBOX, 0, 0, 0, H - rr, H - rr, H - rr, rr)
99 var nsharp: i64 = 0
100 var nround: i64 = 0
101 var gz: i64 = 0 - H
102 while gz <= H {
103 var gy: i64 = 0 - H
104 while gy <= H {
105 var gx: i64 = 0 - H
106 while gx <= H {
107 if nx_sdf_eval(sharp, gx, gy, gz) < 0 { nsharp = nsharp + 1 }
108 if nx_sdf_eval(round, gx, gy, gz) < 0 { nround = nround + 1 }
109 gx = gx + 16384
110 }
111 gy = gy + 16384
112 }
113 gz = gz + 16384
114 }
115 w(" inside: sharp box=" as *u8); wn(nsharp); w(" rounded=" as *u8); wn(nround); w("\n" as *u8)
116 chk(nround < nsharp, pass, fail, "rounding REMOVED corner material (rounded < sharp)" as *u8)
117
118 nx_mesh_translate(rbox, 0, 0, H)
119 let bvh2: *NxBvh = nx_bvh_build(rbox)
120 let soup2: *NxSliceSoup = nx_slice_plane(rbox, bvh2, H + 3000)
121 let c2: *NxSliceContours = nx_slice_contour_build(soup2)
122 chk(eqi(c2.n_open, 0), pass, fail, "rounded box slices WATERTIGHT" as *u8)
123 chk(prints(rbox) >= 500, pass, fail, "rounded box prints (real moves)" as *u8)
124
125 w("=== VERDICT pass=" as *u8); wn(pass[0]); w(" fail=" as *u8); wn(fail[0]); w(" ===\n" as *u8)
126 if fail[0] == 0 { return 0 }
127 return 1
128}