mathart

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

rose.lua (2604B)


      1 --[[
      2   Rose Art
      3   "rose.lua"
      4   M. Yamanaka
      5   email: myamanaka@live.com
      6   website: csmyamanaka.com
      7   license: MIT (See included "LICENSE" file for details)
      8 ]]
      9 
     10 local ca = require("lgi").cairo
     11 require("csconv")
     12 
     13 function neonSet(ctx, p, n, r, c)
     14   --[[
     15     draw a set of "neon" points
     16     arguments:
     17       ctx ... cairo context
     18       p   ... point in canvas coordinate system
     19       n   ... number of points
     20       r   ... max radius
     21       c   ... colour
     22   ]]
     23   ctx:set_source_rgb(c[1], c[2], c[3])
     24   for i = 1, n do
     25     ctx:arc(p[i][1], p[i][2], r, 0, math.pi*2)
     26     ctx:fill()
     27   end
     28 
     29   --[[
     30     To give it a "neon" appearance, these points should all
     31     have a white centre
     32   ]]
     33   ctx:set_source_rgb(1, 1, 1)
     34   for i = 1, n do
     35     ctx:arc(p[i][1], p[i][2], r*0.7, 0, math.pi*2)
     36     ctx:fill()
     37   end
     38 end
     39 
     40 function genPts(n, p0, l, s, t)
     41   --[[
     42     Generate a set of points that reside on one continous
     43     function at equal intervals. The resulting set of points
     44     are in canvas coordinates
     45     arguments:
     46       n   ... total number of points
     47       p0  ... initial point in polar coordinates
     48       l   ... the layer of the rose petals on which these pts reside
     49       s   ... the scaling factor for domain conversion
     50       t   ... the translation for domain conversion
     51   ]]
     52   local pts = {}
     53   for i = 1, n do
     54     local u = (i - 1)*(2*math.pi)/n
     55     local th = u/l + p0[2]
     56     local r = p0[1]*0.1*math.abs(math.sin(u*1.5)) + p0[1]
     57     pts[i] = xyCanv(polarXY({r, th}), s, t)
     58   end
     59   return pts
     60 end
     61 
     62 function genFibs(n)
     63   --[[
     64     It is widely known that fibonacci numbers appear in nature.
     65     We will employ these numbers for our designs as well
     66   ]]
     67   local fibs = {0, 1}
     68   for i = 3, n do fibs[i] = fibs[i - 1] + fibs[i - 2] end
     69   return fibs
     70 end
     71 
     72 function rose()
     73   --[[
     74     The "main" function
     75   ]]
     76   
     77   local dim = {1920, 1080}
     78   local fn = "rose.svg"
     79   local ctx = ca.Context.create(ca.SvgSurface.create(fn, dim[1], dim[2]))
     80   
     81   local N = 100 -- set each segment to have 100 points
     82   local P1 = {}
     83   local idx = 1 -- index number for each set
     84   --[[
     85     the use of fibonacci numbers allow for natural looking
     86     patterns
     87   ]]
     88   local fibs = genFibs(7)
     89   for i = 4, 7 do
     90     for j = 0, fibs[i] - 1 do
     91       P1[idx] = genPts(N, {(i - 3)*100, j*2*math.pi/fibs[i]}, fibs[i] + 1, 1, {dim[1]/2, dim[2]/2})
     92       idx = idx + 1
     93     end
     94   end
     95 
     96   --[[
     97     initialize the scene with a black background
     98   ]]
     99   ctx:set_source_rgb(0, 0, 0)
    100   ctx:rectangle(0, 0, dim[1], dim[2])
    101   ctx:fill()
    102   
    103   --[[
    104     Draw all segments
    105   ]]
    106   for i = 1, idx - 1 do neonSet(ctx, P1[i], N, 10, {1.0, 0.1, 0.9}) end
    107 end
    108 
    109 rose()

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