mathart

Lua + Cairo scripts that generate art, designs, and patterns
Log | Files | Refs | README | LICENSE

commit 76fe2ff904009bdaf236f5fc7a1d8a349cfe609a
parent 4c1df7c878379b1bd3060e8622d0a88a80e3fc03
Author: M. Yamanaka <myamanaka@live.com>
Date:   Tue, 16 Feb 2021 18:50:33 -0500

makefile + spiral and rose patterns

Diffstat:
AMakefile | 21+++++++++++++++++++++
Acsconv.lua | 43+++++++++++++++++++++++++++++++++++++++++++
Arose.lua | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aspiral.lua | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 238 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,21 @@ +# Math Art Makefile +# M. Yamanaka +# email: myamanaka@live.com +# website: csmyamanaka.com +# license: MIT (See included "LICENSE" file for details) + +CC=lua + +all: rose spiral + +spiral: + $(CC) $@.lua + +rose: + $(CC) $@.lua + +topng: + mogrify -format png *.svg + +clean: + rm -f *.svg *.png diff --git a/csconv.lua b/csconv.lua @@ -0,0 +1,43 @@ + +--[[ + Coordinate Systems Conversion + "csconv.lua" + M. Yamanaka + email: myamanaka@live.com + website: csmyamanaka.com + license: MIT (See included "LICENSE" file for details) +]] + +--[[ + a series of conversions between coordinate systems + canvXY ... canvas to XY coordinate system + arguments: + p ... point in canvas space + s ... scale factor + t ... translation + xyCanv ... XY to canvas coordinate system + arguments: + p ... point in XY coordinate system + s ... scale factor + t ... translatiion + polarXY ... polar to XY coordinate system + arguments: + p ... point in polar coordinate system {r, theta} + xyPolar ... XY to polar coordinate system + arguments: + p ... point in XY coordinate system +]] +function canvXY(p, s, t) return {(p[1] - t[1])/s, (p[2] - t[2])/s} end +function xyCanv(p, s, t) return {s*p[1] + t[1], s*p[2] + t[2]} end +function polarXY(p) return {p[1]*math.cos(p[2]), p[1]*math.sin(p[2])} end +function xyPolar(p) + local th = 0 + if p[1] == 0 and p[2] >= 0 then th = math.pi/2 + elseif p[1] == 0 and p[2] < 0 then th = 3*math.pi/2 + elseif p[1] >=0 and p[2] == 0 then th = 0 + elseif p[1] < 0 and p[2] == 0 then th = math.pi + else th = math.atan(p[2]/p[1]) + end + return {math.sqrt(p[1]*p[1] + p[2]*p[2]), th} +end + diff --git a/rose.lua b/rose.lua @@ -0,0 +1,109 @@ +--[[ + Rose Art + "rose.lua" + M. Yamanaka + email: myamanaka@live.com + website: csmyamanaka.com + license: MIT (See included "LICENSE" file for details) +]] + +local ca = require("lgi").cairo +require("csconv") + +function neonSet(ctx, p, n, r, c) + --[[ + draw a set of "neon" points + arguments: + ctx ... cairo context + p ... point in canvas coordinate system + n ... number of points + r ... max radius + c ... colour + ]] + ctx:set_source_rgb(c[1], c[2], c[3]) + for i = 1, n do + ctx:arc(p[i][1], p[i][2], r, 0, math.pi*2) + ctx:fill() + end + + --[[ + To give it a "neon" appearance, these points should all + have a white centre + ]] + ctx:set_source_rgb(1, 1, 1) + for i = 1, n do + ctx:arc(p[i][1], p[i][2], r*0.7, 0, math.pi*2) + ctx:fill() + end +end + +function genPts(n, p0, l, s, t) + --[[ + Generate a set of points that reside on one continous + function at equal intervals. The resulting set of points + are in canvas coordinates + arguments: + n ... total number of points + p0 ... initial point in polar coordinates + l ... the layer of the rose petals on which these pts reside + s ... the scaling factor for domain conversion + t ... the translation for domain conversion + ]] + local pts = {} + for i = 1, n do + local u = (i - 1)*(2*math.pi)/n + local th = u/l + p0[2] + local r = p0[1]*0.1*math.abs(math.sin(u*1.5)) + p0[1] + pts[i] = xyCanv(polarXY({r, th}), s, t) + end + return pts +end + +function genFibs(n) + --[[ + It is widely known that fibonacci numbers appear in nature. + We will employ these numbers for our designs as well + ]] + local fibs = {0, 1} + for i = 3, n do fibs[i] = fibs[i - 1] + fibs[i - 2] end + return fibs +end + +function rose() + --[[ + The "main" function + ]] + + local dim = {1920, 1080} + local fn = "rose.svg" + local ctx = ca.Context.create(ca.SvgSurface.create(fn, dim[1], dim[2])) + + local N = 100 -- set each segment to have 100 points + local P1 = {} + local idx = 1 -- index number for each set + --[[ + the use of fibonacci numbers allow for natural looking + patterns + ]] + local fibs = genFibs(7) + for i = 4, 7 do + for j = 0, fibs[i] - 1 do + P1[idx] = genPts(N, {(i - 3)*100, j*2*math.pi/fibs[i]}, fibs[i] + 1, 1, {dim[1]/2, dim[2]/2}) + idx = idx + 1 + end + end + + --[[ + initialize the scene with a black background + ]] + ctx:set_source_rgb(0, 0, 0) + ctx:rectangle(0, 0, dim[1], dim[2]) + ctx:fill() + + --[[ + Draw all segments + ]] + for i = 1, idx - 1 do neonSet(ctx, P1[i], N, 10, {1.0, 0.1, 0.9}) end +end + +rose() diff --git a/spiral.lua b/spiral.lua @@ -0,0 +1,65 @@ +--[[ + Spiral Art + "spiral.lua" + M. Yamanaka + email: myamanaka@live.com + website: csmyamanaka.com + license: MIT (See included "LICENSE" file for details) +]] + +local ca = require("lgi").cairo +require("csconv") + +function pebble(ctx, p, r, c) + --[[ + draw a single pebble in canvs coordinate system + arguments: + ctx ... cairo context + p ... point in canvas coordinate system + r ... radius of the pebble + c ... colour + ]] + ctx:set_source_rgb(c[1], c[2], c[3]) + ctx:arc(p[1], p[2], r, 0, math.pi*2) + ctx:fill() +end + +function spiral() + --[[ + The "main" function + The polar coordinate system is used to generate a nice + spiral pattern + ]] + + local dim = {1920, 1080} + --local img = ca.SvgSurface.create("spiral.svg", dim[1], dim[2]) + local fn = "spiral.svg" + local ctx = ca.Context.create(ca.SvgSurface.create(fn, dim[1], dim[2])) + + local pts = {} + local dTh = 5 + local dR = 45 + local sz = 11 + local N = 11 + + --[[ + insert points into the list + ]] + for n = 0, N - 1 do + for i = 1, sz do pts[n*sz + i] = {i*dR, (i - 1)*dTh + n*2*math.pi/N} end + end + + --[[ + initialize the scene with a black background + ]] + ctx:set_source_rgb(0, 0, 0) + ctx:rectangle(0, 0, dim[1], dim[2]) + ctx:fill() + + for i = 1, N*sz do + local v = ((i - 1)%sz) + pebble(ctx, xyCanv(polarXY(pts[i]), 1, {dim[1]/2, dim[2]/2}), v + 5, {0.9*v/sz + 0.1, 0.9*v/sz + 0.1, 0.9*v/sz + 0.1}) + end +end + +spiral()

Generated using stagit (https://codemadness.org/stagit.html)