code wiki / _hdl_build / nx_geo_raster.nx
nx_geo_raster.nx source
↩ module page · 76 lines · 2798 B
1// nx_geo_raster.nx -- LIB: GEO-020 RASTER RENDER (integer scanline polygon fill, even-odd rule).
2//
3// THE EXCEED ANGLE (measured): coverage is decided by INTEGER scanline crossings -- for each pixel row
4// we find the polygon-edge x-crossings, sort them, and fill the spans between crossing pairs. ZERO
5// floating point, half-open [lo,hi) edge rule -> a deterministic, gap-free, no-double-fill rasterization
6// (the classic float rasterizer's seam/overlap artifacts at shared edges cannot occur). The same
7// integer cross-style interpolation as the rest of nx_geo. Pixel (row,col) at grid[row*w + col].
8//
9// Convention (matches nx_geo): poly = flat [y0,x0, y1,x1, ...] in PIXEL coords (y=row, x=col).
10// Writes 1 to filled pixels of grid (a w*h byte buffer), returns the filled pixel count. license_tier: ORIGINAL
11import "nx_syscalls.nx"
12
13func geo_raster_fill(poly: *i64, npts: i64, w: i64, h: i64, grid: *u8) -> i64 {
14 var t: i64 = 0
15 while t < w * h { grid[t] = 0 as u8; t = t + 1 }
16
17 let xs: *i64 = sys_mmap(8 * (npts + 2)) as *i64
18 var count: i64 = 0
19 var y: i64 = 0
20 while y < h {
21 // collect edge x-crossings for scanline row y (half-open [lo,hi) in row)
22 var c: i64 = 0
23 var i: i64 = 0
24 var j: i64 = npts - 1
25 while i < npts {
26 var lo: i64 = poly[j * 2]
27 var hi: i64 = poly[i * 2]
28 var xlo: i64 = poly[j * 2 + 1]
29 var xhi: i64 = poly[i * 2 + 1]
30 if lo > hi {
31 let ty: i64 = lo; lo = hi; hi = ty
32 let tx: i64 = xlo; xlo = xhi; xhi = tx
33 }
34 if y >= lo { if y < hi {
35 xs[c] = xlo + (xhi - xlo) * (y - lo) / (hi - lo)
36 c = c + 1
37 } }
38 j = i
39 i = i + 1
40 }
41 // sort crossings ascending (selection sort; c is small)
42 var a: i64 = 0
43 while a < c {
44 var mn: i64 = a
45 var b: i64 = a + 1
46 while b < c {
47 if xs[b] < xs[mn] { mn = b }
48 b = b + 1
49 }
50 let tmp: i64 = xs[a]; xs[a] = xs[mn]; xs[mn] = tmp
51 a = a + 1
52 }
53 // fill spans between crossing pairs
54 var k: i64 = 0
55 while k + 1 < c {
56 var xa: i64 = xs[k]
57 var xb: i64 = xs[k + 1]
58 if xa < 0 { xa = 0 }
59 if xb > w { xb = w }
60 var col: i64 = xa
61 while col < xb {
62 grid[y * w + col] = 1 as u8
63 count = count + 1
64 col = col + 1
65 }
66 k = k + 2
67 }
68 y = y + 1
69 }
70 return count
71}
72
73// read a pixel (1=filled, 0=empty).
74func geo_raster_get(grid: *u8, w: i64, row: i64, col: i64) -> i64 {
75 return grid[row * w + col] as i64
76}