diff --git a/shape.lua b/shape.lua index 13b66cd74afd81ad26408d9f14d303b9161c6d9c..bf54ef57200041b90ba2e232166a42244ab112a5 100644 --- a/shape.lua +++ b/shape.lua @@ -1,8 +1,10 @@ require "baka-fx.shape.potato" require "baka-fx.shape.circle" +require "baka-fx.shape.star" shape = { potato = potato, - circle = circle + circle = circle, + star = star } \ No newline at end of file diff --git a/shape/circle.lua b/shape/circle.lua index b323cb60e9f0f9cf1fa47c6328a7bf4a6bf86b7f..1514ae61100addc2ab3cce0920a182e3a85d5d50 100644 --- a/shape/circle.lua +++ b/shape/circle.lua @@ -60,4 +60,4 @@ function circle(radius, keypoints, clockwise) end return str - end \ No newline at end of file +end \ No newline at end of file diff --git a/shape/star.lua b/shape/star.lua new file mode 100644 index 0000000000000000000000000000000000000000..f09fd4a6983dec264f34aae9f844a01e88dcff34 --- /dev/null +++ b/shape/star.lua @@ -0,0 +1,140 @@ +--[[ +[Description] +Draws a star with bezier curves. + +[Usage] +star(outradius, inradius) +star(outradius, inradius, branches) +star(outradius, inradius, branches, roundness) +star(outradius, inradius, branches, roundness, clockwise) + +[Arguments] +outradius: outer radius of the star, in pixels +inradius: inner radius of the star, in pixels (default a function of outradius) +branches: number of branches, positive integer >= 2 (default 5) +roundness: roundness of the branches, between 0 and 1 (default 0) +clockwise: drawing direction, boolean (default false) + +[Notes] +The star is drawn so that it always has a branch pointing straight up. +This function does not include drawing tags, only vector commands. +If no inradius is specified and there are 5 or more branches, the inradius +is set to outradius * sin(pi/2 - 2pi/n) / cos(pi/n) where n is the number +of branches. This makes it so the edges of the branches are aligned. +If no inradius is specified and there are less than 5 branches, the inradius +is set to outradius / 2. +--]] +function star(outradius, inradius, branches, roundness, clockwise) + roundness = roundness or 0 + branches = branches or 5 + branches = branches >= 2 and branches or 5 + + local halfpi = math.pi / 2 + local mult = clockwise and -1 or 1 + local alpha = math.pi / branches + + inradius = inradius or (branches < 5 and outradius / 2 + or outradius * math.sin(halfpi - 2 * alpha) / math.cos(alpha)) + + local inpoints = {} + local outpoints = {} + + for i = 1, branches do + local oa = (2*(i-1)) * mult * alpha - halfpi + local ia = oa + mult * alpha + + outpoints[i] = + { + a = oa, + x = outradius * math.cos(oa), + y = outradius * math.sin(oa) + } + + inpoints[i] = + { + a = ia, + x = inradius * math.cos(ia), + y = inradius * math.sin(ia) + } + end + + outpoints[branches+1] = outpoints[1] + inpoints[0] = inpoints[branches] + + local str = "" + + -- No roundness => draw straight lines + if roundness < 0.001 then + str = "m " .. outpoints[1].x .. " " .. outpoints[1].y .. " " + + for i = 1, branches do + local ip = inpoints[i] + local op = outpoints[i+1] + + str = str .. "l " .. ip.x .. " " .. ip.y .. " " + .. "l " .. op.x .. " " .. op.y .. " " + end + + return str + end + + local b = outradius - inradius * math.cos(alpha) + local hi = (b - roundness * (outradius - inradius)) * math.cos(halfpi - 2 * alpha) + local ho = roundness * (outradius - inradius) * math.tan(halfpi - 2 * alpha) + local beta = halfpi - alpha + local l = inradius + (1 - roundness) * (outradius - inradius) + + for i = 1, branches do + local op = outpoints[i] + + local x = l * math.cos(op.a) + local y = l * math.sin(op.a) + + outpoints[i].x = x + outpoints[i].y = y + outpoints[i].h1 = + { + x = x + ho * math.cos(op.a - mult * halfpi), + y = y + ho * math.sin(op.a - mult * halfpi) + } + outpoints[i].h2 = + { + x = x + ho * math.cos(op.a + mult * halfpi), + y = y + ho * math.sin(op.a + mult * halfpi) + } + + local ip0 = inpoints[i-1] + local ip1 = inpoints[i] + + inpoints[i-1].h2 = + { + x = ip0.x + hi * math.cos(ip0.a + mult * beta), + y = ip0.y + hi * math.sin(ip0.a + mult * beta) + } + inpoints[i].h1 = + { + x = ip1.x + hi * math.cos(ip1.a - mult * beta), + y = ip1.y + hi * math.sin(ip1.a - mult * beta) + } + end + + inpoints[branches].h2 = inpoints[0].h2 + inpoints[0].h1 = inpoints[branches].h1 + + str = "m " .. outpoints[1].x .. " " .. outpoints[1].y .. " " + + for i = 1, branches do + local op0 = outpoints[i] + local op1 = outpoints[i+1] + local ip = inpoints[i] + + str = str .. "b " .. op0.h2.x .. " " .. op0.h2.y .. " " + .. ip.h1.x .. " " .. ip.h1.y .. " " + .. ip.x .. " " .. ip.y .. " " + .. "b " .. ip.h2.x .. " " .. ip.h2.y .. " " + .. op1.h1.x .. " " .. op1.h1.y .. " " + .. op1.x .. " " .. op1.y .. " " + end + + return str +end \ No newline at end of file