code wiki / (root) / nx_csg_rotxz_gate.nx

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}