code wiki / (root) / nx_cad_prims2_test.nx

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}