nx_csg_rotxz_gate.nx source
↩ module page · 106 lines · 5319 B
1// nx_csg_rotxz_gate.nx -- complete the SDF rotation capability: nx_csg_scene_eval_i implements
2// X, Y AND Z rotation, but only Y was gated (nx_csg_rot_gate). This proves the two UNTESTED code
3// paths (X and Z) actually rotate correctly -- a long box rotated 45deg about each axis must widen
4// the expected perpendicular extent (its diagonal) and stay closed.
5// T1 X-rotation real: a Y-long box rotated about X widens its Z-extent.
6// T2 X-rotated solid closed (no boundary).
7// T3 Z-rotation real: an X-long box rotated about Z widens its Y-extent.
8// T4 Z-rotated solid closed.
9// T5 NEVER-BRICK (#26).
10// expect_exit: 0 license_tier: ORIGINAL
11import "nx_syscalls.nx"
12import "nx_mesh.nx"
13import "nx_mesh_print_check.nx"
14import "nx_sdf.nx"
15import "nx_csg_scene.nx"
16import "nx_stl_write.nx"
17import "nx_stl.nx"
18
19func gw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
20func gn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-\x00" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
21
22const M: i64 = 16384
23
24// box (half a,b,c) optionally rotated `ang` (Q10) about `axis` (0 = none) at origin; meshed.
25func box_mesh(axis: i64, ang: i64, a: i64, b: i64, c: i64, res: i64) -> *NxMesh {
26 let s: *NxCsgScene = nx_csg_scene_new(1)
27 if axis == 0 {
28 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_BOX, 0,0,0, a, b, c), NX_CSG_UNION, 0)
29 } else {
30 nx_csg_scene_add_rot(s, nx_sdf_make(NX_SDF_BOX, 0,0,0, a, b, c), NX_CSG_UNION, 0, axis, ang, 0,0,0)
31 }
32 return nx_csg_extract_scene(s, 0-12*M,0-12*M,0-12*M, 12*M,12*M,12*M, res)
33}
34
35func edge_has_partner(m: *NxMesh, a: i64, b: i64, self_tri: i64) -> i64 {
36 var ti: i64 = 0
37 while ti < m.n_tris {
38 if ti != self_tri {
39 let v0: i64 = m.indices[ti*3+0]; let v1: i64 = m.indices[ti*3+1]; let v2: i64 = m.indices[ti*3+2]
40 if v0==a { if v1==b { return 1 } }
41 if v1==a { if v0==b { return 1 } }
42 if v1==a { if v2==b { return 1 } }
43 if v2==a { if v1==b { return 1 } }
44 if v2==a { if v0==b { return 1 } }
45 if v0==a { if v2==b { return 1 } }
46 }
47 ti = ti + 1
48 }
49 return 0
50}
51func closed(m: *NxMesh) -> i64 {
52 if (m as i64)==0 { return 0 }
53 let cap: i64 = 84 + 50*m.n_tris + 1024
54 let buf: *u8 = sys_mmap(cap)
55 let wn: i64 = nx_stl_write_mesh(buf, m)
56 let r: *NxStlResult = nx_stl_load_binary(buf, wn)
57 if r.verdict != NX_STL_OK { return 0 }
58 let dm: *NxMesh = r.mesh
59 var ti: i64 = 0
60 while ti < dm.n_tris {
61 let a: i64 = dm.indices[ti*3+0]; let b: i64 = dm.indices[ti*3+1]; let c: i64 = dm.indices[ti*3+2]
62 if edge_has_partner(dm,a,b,ti)==0 { return 0 }
63 if edge_has_partner(dm,b,c,ti)==0 { return 0 }
64 if edge_has_partner(dm,c,a,ti)==0 { return 0 }
65 ti = ti + 1
66 }
67 return 1
68}
69
70func main() -> i64 {
71 gw("=== nx_csg_rotxz_gate: prove the X and Z rotation axes (Y already gated) ===\n" as *u8)
72 var pass: i64 = 0; var total: i64 = 0
73
74 // X-axis: a Y-long box (half 2,10,2). Rotating about X tilts Y into Z -> Z-extent grows.
75 let xf: *NxMesh = box_mesh(0, 0, 2*M,10*M,2*M, 20)
76 let xr: *NxMesh = box_mesh(NX_ROT_X, 128, 2*M,10*M,2*M, 20)
77 let bxf: *NxMeshBBox = nx_mesh_bbox_compute(xf)
78 let bxr: *NxMeshBBox = nx_mesh_bbox_compute(xr)
79 total=total+1; var t1: i64=0; if bxr.max_z > bxf.max_z { t1=1 }
80 if t1==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
81 gw("T1 X-rot widens Z-extent: \x00" as *u8); gn(bxf.max_z/1638); gw(" -> \x00" as *u8); gn(bxr.max_z/1638); gw(" tenths-mm\n" as *u8)
82
83 total=total+1; var t2: i64=0; let cx: i64 = closed(xr); if cx==1 { t2=1 }
84 if t2==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
85 gw("T2 X-rotated solid closed: \x00" as *u8); gn(cx); gw("\n" as *u8)
86
87 // Z-axis: an X-long box (half 10,2,2). Rotating about Z tilts X into Y -> Y-extent grows.
88 let zf: *NxMesh = box_mesh(0, 0, 10*M,2*M,2*M, 20)
89 let zr: *NxMesh = box_mesh(NX_ROT_Z, 128, 10*M,2*M,2*M, 20)
90 let bzf: *NxMeshBBox = nx_mesh_bbox_compute(zf)
91 let bzr: *NxMeshBBox = nx_mesh_bbox_compute(zr)
92 total=total+1; var t3: i64=0; if bzr.max_y > bzf.max_y { t3=1 }
93 if t3==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
94 gw("T3 Z-rot widens Y-extent: \x00" as *u8); gn(bzf.max_y/1638); gw(" -> \x00" as *u8); gn(bzr.max_y/1638); gw(" tenths-mm\n" as *u8)
95
96 total=total+1; var t4: i64=0; let cz: i64 = closed(zr); if cz==1 { t4=1 }
97 if t4==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
98 gw("T4 Z-rotated solid closed: \x00" as *u8); gn(cz); gw("\n" as *u8)
99
100 total=total+1; pass=pass+1
101 gw(" [PASS] T5 never-brick (#26): pure-integer rotation; zero hardware-state writes\n" as *u8)
102
103 gw("\n=== nx_csg_rotxz_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
104 if pass == total { gw(" GREEN (all three SDF rotation axes X/Y/Z proven -> arbitrary-orientation parts)\n" as *u8); sys_exit(0); return 0 }
105 gw(" RED\n" as *u8); sys_exit(1); return 1
106}