code wiki / (root) / nx_slice_plane_test.nx

nx_slice_plane_test.nx source

↩ module page · 86 lines · 3194 B

1// nx_slice_plane_test.nx -- slice a unit tetrahedron at its midplane 2// and verify the resulting segment soup describes the expected 3// right-triangle cross-section. 4// 5// Tetrahedron at unit-mm scale: 6// v0=(0,0,0), v1=(1,0,0), v2=(0,1,0), v3=(0,0,1) (in Q14: 0 vs 16384) 7// Sliced at z = 0.5 mm (8192 Q14): 8// T0 (v1,v2,v3): produces segment (8192,0) -- (0,8192) 9// T1 (v0,v3,v2): produces segment (0,0) -- (0,8192) 10// T2 (v0,v1,v3): produces segment (8192,0) -- (0,0) 11// T3 (v0,v2,v1): all z=0, plane at 8192 -> all below -> no segment 12// 13// Result: 3 segments whose 6 endpoints cover the set 14// {(0,0), (8192,0), (0,8192)}, each appearing exactly twice. 15// This is the boundary of a right triangle in 2D. 16// 17// Closed-form invariants: 18// (a) Soup verdict == OK. 19// (b) Exactly 3 segments at z=8192. 20// (c) Each of the 3 corner points appears exactly twice in the 21// segment-endpoint multiset. 22// (d) Slicing at z above tetrahedron (z = 2 * Q14) -> 0 segments. 23// (e) Slicing at z below tetrahedron (z = -1) -> 0 segments. 24// (f) Slicing at the bottom face (z = 0) yields 3 segments 25// (the three coplanar tri edges of the bottom face's 26// neighbours; T3 itself coplanar -> no segment). 27// 28// expect_exit: 0 29// license_tier: ORIGINAL 30 31import "nx_syscalls.nx" 32import "nx_mesh.nx" 33import "nx_mesh_print_check.nx" 34import "nx_bvh.nx" 35import "nx_slice_plane.nx" 36 37const Q14_ONE: i64 = 16384 38const Q14_HALF: i64 = 8192 39 40// Count occurrences of (px, py) in the segment endpoints. 41func smoke_count_endpoint(s: *NxSliceSoup, px: i64, py: i64) -> i64 { 42 var count: i64 = 0 43 var i: i64 = 0 44 while i < s.n_segments { 45 let p: *i64 = nx_slice_soup_seg_ptr(s, i) 46 if p[0] == px { if p[1] == py { count = count + 1 } } 47 if p[2] == px { if p[3] == py { count = count + 1 } } 48 i = i + 1 49 } 50 return count 51} 52 53func main() -> i64 { 54 let m: *NxMesh = nx_mesh_make_tetrahedron(Q14_ONE, 0) 55 if (m as i64) == 0 { return 5 } 56 let b: *NxBvh = nx_bvh_build(m) 57 if (b as i64) == 0 { return 6 } 58 59 // --- (a)(b) Slice at mid-plane --- 60 let s: *NxSliceSoup = nx_slice_plane(m, b, Q14_HALF) 61 if s.verdict != NX_SLICE_OK { return 10 } 62 if s.n_segments != 3 { return 11 } 63 64 // --- (c) Endpoint multiset --- 65 if smoke_count_endpoint(s, 0, 0) != 2 { return 20 } 66 if smoke_count_endpoint(s, Q14_HALF, 0) != 2 { return 21 } 67 if smoke_count_endpoint(s, 0, Q14_HALF) != 2 { return 22 } 68 69 // --- (d) Slice above tetrahedron --- 70 let s_above: *NxSliceSoup = nx_slice_plane(m, b, 2 * Q14_ONE) 71 if s_above.n_segments != 0 { return 30 } 72 73 // --- (e) Slice below tetrahedron --- 74 let s_below: *NxSliceSoup = nx_slice_plane(m, b, -1) 75 if s_below.n_segments != 0 { return 40 } 76 77 // --- (f) Slice at bottom face z=0 --- 78 // T3 (v0,v2,v1) all coplanar -> no segment. 79 // T0(v1,v2,v3), T1(v0,v3,v2), T2(v0,v1,v3) each have 2 zeros 80 // -> each emits the on-plane edge as segment. 3 segments. 81 let s_bottom: *NxSliceSoup = nx_slice_plane(m, b, 0) 82 if s_bottom.verdict != NX_SLICE_OK { return 50 } 83 if s_bottom.n_segments != 3 { return 51 } 84 85 return 0 86}