code wiki / (root) / nx_infill_test.nx

nx_infill_test.nx source

↩ module page · 131 lines · 4681 B

1// nx_infill_test.nx -- scan-line infill on a unit-mm CCW square at 2// multiple densities, hand-computed expected counts and endpoints. 3// 4// Unit square (0,0) - (1mm, 1mm) in Q14: (0,0) - (16384, 16384). 5// Line width = 0.4mm = 6554 Q14. 6// 7// Density 100% -> spacing = 6554 Q14. Scan lines at y = 0, 6554, 8// 13108 (next 19662 > 16384 = out of bbox). 3 segments. 9// Density 50% -> spacing = 13108 Q14. Scan lines at y = 0, 13108. 10// 2 segments. 11// Density 25% -> spacing = 26216 Q14. Scan line at y = 0 only. 12// 1 segment. 13// 14// At each scan line, the square produces ONE crossing pair from 15// x = 0 to x = 16384 (left and right vertical edges of the square). 16// Horizontal edges of the square (top and bottom) are skipped by 17// the straddle test, which is the right behaviour. 18// 19// Closed-form invariants: 20// (a) 100% density horizontal scan -> exactly 3 segments. 21// (b) 50% density horizontal scan -> exactly 2 segments. 22// (c) 25% density horizontal scan -> exactly 1 segment. 23// (d) Every emitted segment is horizontal (y1 == y2). 24// (e) Every emitted segment spans full width (x1=0, x2=16384). 25// (f) Vertical scan (vertical=1) at 50% density -> 2 vertical 26// segments (x1==x2, span full height). 27// (g) density_pct = 0 returns BAD_DENSITY verdict. 28// (h) density_pct = 101 returns BAD_DENSITY verdict. 29// (i) 3-vert polygon (triangle) at 100% density yields > 0 segments. 30// 31// expect_exit: 0 32// license_tier: ORIGINAL 33 34import "nx_syscalls.nx" 35import "nx_polygon.nx" 36import "nx_slice_plane.nx" 37import "nx_infill.nx" 38 39const Q14: i64 = 16384 40const LINE_WIDTH: i64 = 6554 41 42func smoke_seg_x1(s: *NxSliceSoup, i: i64) -> i64 { 43 let p: *i64 = nx_slice_soup_seg_ptr(s, i) 44 return p[0] 45} 46func smoke_seg_y1(s: *NxSliceSoup, i: i64) -> i64 { 47 let p: *i64 = nx_slice_soup_seg_ptr(s, i) 48 return p[1] 49} 50func smoke_seg_x2(s: *NxSliceSoup, i: i64) -> i64 { 51 let p: *i64 = nx_slice_soup_seg_ptr(s, i) 52 return p[2] 53} 54func smoke_seg_y2(s: *NxSliceSoup, i: i64) -> i64 { 55 let p: *i64 = nx_slice_soup_seg_ptr(s, i) 56 return p[3] 57} 58 59func main() -> i64 { 60 let sq: *NxPolygon = nx_polygon_make_square(0, 0, Q14, Q14) 61 62 // --- (a) 100% horizontal --- 63 let s100: *NxSliceSoup = nx_slice_soup_new(64) 64 let v100: i64 = nx_infill_lines(sq, 100, LINE_WIDTH, 0, s100) 65 if v100 != NX_INFILL_OK { return 10 } 66 if s100.n_segments != 3 { return 11 } 67 68 // --- (b) 50% horizontal --- 69 let s50: *NxSliceSoup = nx_slice_soup_new(64) 70 let v50: i64 = nx_infill_lines(sq, 50, LINE_WIDTH, 0, s50) 71 if v50 != NX_INFILL_OK { return 20 } 72 if s50.n_segments != 2 { return 21 } 73 74 // --- (c) 25% horizontal --- 75 let s25: *NxSliceSoup = nx_slice_soup_new(64) 76 let v25: i64 = nx_infill_lines(sq, 25, LINE_WIDTH, 0, s25) 77 if v25 != NX_INFILL_OK { return 30 } 78 if s25.n_segments != 1 { return 31 } 79 80 // --- (d) Horizontal segments: y1 == y2 --- 81 var i: i64 = 0 82 while i < s50.n_segments { 83 if smoke_seg_y1(s50, i) != smoke_seg_y2(s50, i) { return 40 } 84 i = i + 1 85 } 86 87 // --- (e) Full-width span: x1 == 0, x2 == Q14 --- 88 i = 0 89 while i < s50.n_segments { 90 let a: i64 = smoke_seg_x1(s50, i) 91 let b: i64 = smoke_seg_x2(s50, i) 92 // qsort orders them; a should be 0, b should be Q14 93 if a != 0 { return 50 } 94 if b != Q14 { return 51 } 95 i = i + 1 96 } 97 98 // --- (f) Vertical scan --- 99 let sV: *NxSliceSoup = nx_slice_soup_new(64) 100 let vV: i64 = nx_infill_lines(sq, 50, LINE_WIDTH, 1, sV) 101 if vV != NX_INFILL_OK { return 60 } 102 if sV.n_segments != 2 { return 61 } 103 i = 0 104 while i < sV.n_segments { 105 // Vertical: x1 == x2 106 if smoke_seg_x1(sV, i) != smoke_seg_x2(sV, i) { return 62 } 107 // Spans full height 108 let ay: i64 = smoke_seg_y1(sV, i) 109 let by: i64 = smoke_seg_y2(sV, i) 110 if ay != 0 { return 63 } 111 if by != Q14 { return 64 } 112 i = i + 1 113 } 114 115 // --- (g)(h) Bad density --- 116 let sBad: *NxSliceSoup = nx_slice_soup_new(64) 117 if nx_infill_lines(sq, 0, LINE_WIDTH, 0, sBad) != NX_INFILL_ERR_BAD_DENSITY { return 70 } 118 if nx_infill_lines(sq, 101, LINE_WIDTH, 0, sBad) != NX_INFILL_ERR_BAD_DENSITY { return 71 } 119 120 // --- (i) Triangle infill produces segments --- 121 let tri: *NxPolygon = nx_polygon_alloc(3) 122 nx_polygon_add_vert(tri, 0, 0) 123 nx_polygon_add_vert(tri, Q14, 0) 124 nx_polygon_add_vert(tri, 0, Q14) 125 let sTri: *NxSliceSoup = nx_slice_soup_new(64) 126 let vTri: i64 = nx_infill_lines(tri, 100, LINE_WIDTH, 0, sTri) 127 if vTri != NX_INFILL_OK { return 80 } 128 if sTri.n_segments <= 0 { return 81 } 129 130 return 0 131}