nx_geom_test.nx source
↩ module page · 144 lines · 5214 B
1// nx_geom_test.nx -- smoke for V4 geometric primitives.
2
3import "syscalls.nx"
4import "nx_image.nx"
5import "nx_features.nx"
6import "nx_geom.nx"
7
8func main() -> i64 {
9 // === Test 1: integer sqrt ===
10 if nx_math_isqrt(0) != 0 { return 1 }
11 if nx_math_isqrt(1) != 1 { return 2 }
12 if nx_math_isqrt(4) != 2 { return 3 }
13 if nx_math_isqrt(9) != 3 { return 4 }
14 if nx_math_isqrt(100) != 10 { return 5 }
15 if nx_math_isqrt(10000) != 100 { return 6 }
16 // sqrt(50) = 7.07... -> floor = 7
17 if nx_math_isqrt(50) != 7 { return 7 }
18
19 // === Test 2: trig table self-consistency ===
20 let cos_t: *i64 = (sys_mmap(36 * 8)) as *i64
21 let sin_t: *i64 = (sys_mmap(36 * 8)) as *i64
22 nx_geom_fill_trig(cos_t, sin_t)
23 // cos(0) = 1024, sin(0) = 0
24 if cos_t[0] != 1024 { return 10 }
25 if sin_t[0] != 0 { return 11 }
26 // cos(90) = 0, sin(90) = 1024
27 if cos_t[18] != 0 { return 12 }
28 if sin_t[18] != 1024 { return 13 }
29 // cos(45) = sin(45) -- both should be 724
30 if cos_t[9] != 724 { return 14 }
31 if sin_t[9] != 724 { return 15 }
32 // Pythagorean check: cos^2 + sin^2 ~= Q^2 (allow +-2% slop)
33 // for theta=30: cos=887, sin=512 -> 887^2 + 512^2 = 786769 + 262144 = 1048913
34 // Q^2 = 1024*1024 = 1048576, diff = 337 -> 0.03% off, perfect
35 let p_sum: i64 = cos_t[6] * cos_t[6] + sin_t[6] * sin_t[6]
36 if p_sum < 1030000 { return 16 }
37 if p_sum > 1070000 { return 17 }
38
39 // === Test 3: Hough line on a vertical line at x=16 in 32x32 image ===
40 let img1: *Image = nx_image_alloc(32, 32, 1)
41 var y: i64 = 0
42 while y < 32 {
43 nx_image_set(img1, 16, y, 0, 255)
44 y = y + 1
45 }
46 // Vertical line: theta=0 degrees, rho=16.
47 // Each pixel votes; should accumulate ~32 votes at (theta=0, rho=16).
48 let lines1: *HoughLines = nx_geom_hough_line(img1, 20, 10)
49 // Should find at least one line.
50 if lines1.n_lines == 0 { return 20 }
51 // Top line should be at theta=0, rho=16 (vertical line).
52 var found_vert: i64 = 0
53 var li: i64 = 0
54 while li < lines1.n_lines {
55 if lines1.thetas[li] == 0 {
56 // rho should be ~16 (allow +-2 due to discretization)
57 if lines1.rhos[li] >= 14 {
58 if lines1.rhos[li] <= 18 {
59 if lines1.votes[li] >= 20 {
60 found_vert = 1
61 }
62 }
63 }
64 }
65 li = li + 1
66 }
67 if found_vert != 1 { return 21 }
68
69 // === Test 4: Hough line on a horizontal line at y=16 ===
70 let img2: *Image = nx_image_alloc(32, 32, 1)
71 var x2: i64 = 0
72 while x2 < 32 {
73 nx_image_set(img2, x2, 16, 0, 255)
74 x2 = x2 + 1
75 }
76 let lines2: *HoughLines = nx_geom_hough_line(img2, 20, 10)
77 if lines2.n_lines == 0 { return 30 }
78 // Horizontal line: theta=90 degrees, rho=16.
79 var found_horz: i64 = 0
80 var li2: i64 = 0
81 while li2 < lines2.n_lines {
82 if lines2.thetas[li2] == 90 {
83 if lines2.rhos[li2] >= 14 {
84 if lines2.rhos[li2] <= 18 {
85 found_horz = 1
86 }
87 }
88 }
89 li2 = li2 + 1
90 }
91 if found_horz != 1 { return 31 }
92
93 // === Test 5: line-orientation histogram ===
94 let hist: *i64 = (sys_mmap(36 * 8)) as *i64
95 nx_geom_line_orientation_hist(lines2, hist)
96 // Bin 18 (theta=90) should have votes; bin 0 should be ~0.
97 if hist[18] < 20 { return 40 }
98
99 // === Test 6: Hough circle on a circle of radius 6 centered at (16,16) in 32x32 ===
100 let img3: *Image = nx_image_alloc(32, 32, 1)
101 // Rasterize circle using Bresenham-ish discrete points.
102 var ang: i64 = 0
103 while ang < 360 {
104 // Use cos_t/sin_t for 5-degree resolution.
105 let ai: i64 = ang / 10
106 // We have 36 angles for 0..175. For 180..355, mirror.
107 var cx_off: i64 = 0
108 var cy_off: i64 = 0
109 if ai < 36 {
110 cx_off = (6 * cos_t[ai]) / 1024
111 cy_off = (6 * sin_t[ai]) / 1024
112 }
113 if ai >= 36 {
114 // angles 180..355 -> negate both
115 let ai2: i64 = ai - 36
116 cx_off = -(6 * cos_t[ai2]) / 1024
117 cy_off = -(6 * sin_t[ai2]) / 1024
118 }
119 let px: i64 = 16 + cx_off
120 let py: i64 = 16 + cy_off
121 if px >= 0 { if px < 32 { if py >= 0 { if py < 32 {
122 nx_image_set(img3, px, py, 0, 255)
123 }}}}
124 ang = ang + 10
125 }
126 // Compute gradients on the rasterized circle.
127 let gx: *ImageS64 = nx_image_sobel_x(img3)
128 let gy: *ImageS64 = nx_image_sobel_y(img3)
129 let cir: *HoughCircles = nx_geom_hough_circle_r(img3, gx, gy, 6, 3, 10)
130 if cir.n_circles == 0 { return 50 }
131 // Should find a center near (16, 16).
132 var found_center: i64 = 0
133 var ci: i64 = 0
134 while ci < cir.n_circles {
135 let dx: i64 = cir.cxs[ci] - 16
136 let dy: i64 = cir.cys[ci] - 16
137 let d2: i64 = dx * dx + dy * dy
138 if d2 <= 9 { found_center = 1 } // within 3 pixels
139 ci = ci + 1
140 }
141 if found_center != 1 { return 51 }
142
143 return 0
144}