login

<     >

2021-04-11 11:23:01 (UTC-03:00)

Marcel Rodrigues <marcelgmr@gmail.com>

add BitMap:polygon()

diff --git a/surf.lua b/surf.lua
index 48751d9..7659cbf 100644
--- a/surf.lua
+++ b/surf.lua
@@ -12,6 +12,11 @@ local bnot = bit.bnot
 local bor, band = bit.bor, bit.band
 local lshift, rshift =  bit.lshift,  bit.rshift
 
+local function round(x)
+    local i, f = math.modf(x + copysign(0.5, x))
+    return i
+end
+
 local BitMap = {}
 BitMap.__index = BitMap
 
@@ -134,7 +139,7 @@ function BitMap:line(x0, y0, x1, y1, v, r)
     end
 end
 
-function BitMap:lines(points, v, r)
+function BitMap:polyline(points, v, r)
     local x0, y0, x1, y1
     x0, y0 = unpack(points[1])
     for i = 2, #points do
@@ -144,6 +149,46 @@ function BitMap:lines(points, v, r)
     end
 end
 
+function BitMap:polygon(points, v)
+    local scans = {}
+    for i = 0, self.h-1 do
+        scans[i] = {}
+    end
+    local x0, y0, x1, y1
+    local ax, ay, bx, by -- same line as above, but enforce ay < by
+    -- collect crossings
+    x0, y0 = unpack(points[1])
+    for i = 2, #points do
+        x1, y1 = unpack(points[i])
+        if y1 ~= y0 then
+            if y0 < y1 then
+                ax, ay, bx, by = x0, y0, x1, y1
+            else
+                ax, ay, bx, by = x1, y1, x0, y0
+            end
+            local slope = (bx-ax) / (by-ay)
+            ay = round(ay)
+            while ay < by do
+                if ay >= 0 and ay < self.h then
+                    table.insert(scans[ay], ax)
+                end
+                ax = ax + slope
+                ay = ay + 1
+            end
+        end
+        x0, y0 = x1, y1
+    end
+    -- fill scanlines
+    for i = 0, self.h-1 do
+        local scan = scans[i]
+        table.sort(scan)
+        for j = 1, #scan, 2 do
+            ax, bx = round(scan[j]), round(scan[j+1])
+            self:hline(ax, i, bx-ax, v)
+        end
+    end
+end
+
 function BitMap:save_pbm(fname)
     local pbm = io.open(fname, "wb")
     pbm:write("P4\n", self.w, " ", self.h, "\n")