login

<     >

2021-04-11 16:50:27 (UTC-03:00)

Marcel Rodrigues <marcelgmr@gmail.com>

add unfold() and circle()

diff --git a/poly.lua b/poly.lua
index dc0fd02..569c974 100644
--- a/poly.lua
+++ b/poly.lua
@@ -5,6 +5,8 @@ double hypot(double x, double y);
 ]]
 local hypot = ffi.C.hypot
 
+local sqrt2 = math.sqrt(2)
+
 local function dashed(points, pattern)
     local x0, y0, x1, y1
     local cx, cy
@@ -53,13 +55,10 @@ end
 
 -- convert bezier curve {{ax, ay}, {bx, by}, {cx, cy}} to polyline
 local function bezier(curve)
-    local h
+    local a, b, c, h
+    local ax, ay, bx, by, cx, cy
     local dx, dy, ex, ey, fx, fy
-    local a, b, c = unpack(curve)
-    local ax, ay = unpack(a)
-    local bx, by = unpack(b)
-    local cx, cy = unpack(c)
-    local points = {{ax, ay}}
+    local points = {}
     local stack = {curve}
     while #stack > 0 do
         a, b, c = unpack(table.remove(stack))
@@ -80,4 +79,66 @@ local function bezier(curve)
     return points
 end
 
-return {dashed=dashed, bezier=bezier}
+-- convert a sequence of linked Bézier curves to a polyline
+local function unfold(control_points)
+    local s, a, b
+    local px, py, qx, qy, rx, ry
+    s = control_points[1]
+    b = control_points[2]
+    local points = {s}
+    local sub
+    if b[3] then
+        table.insert(points, b)
+        s = b
+    end
+    for i = 3, #control_points do
+        a = b
+        b = control_points[i]
+        if a[3] then
+            if b[3] then
+                table.insert(points, b)
+                s = b
+            end
+        else
+            if b[3] then
+                px, py, _ = unpack(s)
+                qx, qy, _ = unpack(a)
+                rx, ry, _ = unpack(b)
+                sub = bezier({{px, py}, {qx, qy}, {rx, ry}})
+                for i, p in ipairs(sub) do
+                    table.insert(points, p)
+                end
+                s = b
+            else
+                px, py, _ = unpack(s)
+                qx, qy, _ = unpack(a)
+                rx, ry, _ = unpack(b)
+                rx, ry = (qx+rx)/2, (qy+ry)/2
+                sub = bezier({{px, py}, {qx, qy}, {rx, ry}})
+                for i, p in ipairs(sub) do
+                    table.insert(points, p)
+                end
+                s = {rx, ry, true}
+            end
+        end
+    end
+    return points
+end
+
+local function circle(x, y, r)
+    local a = r * (sqrt2-1)
+    return {
+        {x  , y+r, true},
+        {x+a, y+r, false},
+        {x+r, y+a, false},
+        {x+r, y-a, false},
+        {x+a, y-r, false},
+        {x-a, y-r, false},
+        {x-r, y-a, false},
+        {x-r, y+a, false},
+        {x-a, y+r, false},
+        {x  , y+r, true}
+    }
+end
+
+return {dashed=dashed, unfold=unfold, circle=circle}