# L-System Explorer: another experiment with procedural plants and gsub

(Updated) The inspiration for the code below is the book identified below and the Wikipedia articles on simulated growth of plants and L-systems that cite it as a source. An example of its output is below:

``````
--
-- L-System Explorer
--
-- With acknowledgements to "The Algorithmic Beauty of Plants" by
-- Przemyslaw Prusinkiewicz and Aristid Lindenmayer
-- http://algorithmicbotany.org/papers/

supportedOrientations(LANDSCAPE_ANY)
function setup()
-- Set up L-System
l = L("X", {X = "F-[[X]+X]+F[+FX]-X", F = "FF"}, 5, 22.5)
-- Other L-Systems:
-- l = L("F", {F = "FF-[-F+F+F]+[+F-F-F]"}, 5, 22.5)
-- l = L("X", {X = "F-[[X]+X]+F[+FX]-X", F = "FF"}, 5, 22.5)
-- l = L("X", {X = "F[+X][-X]FX", F = "FF"}, 5, 25.7)
-- l = L("X", {X = "F[+X]F[-X]+X", F = "FF"}, 5, 20)
l.color = color(50, 140, 28)

sTime = ElapsedTime
step = 1
count = 1
maxCount = 7

bm = mesh()
bm.vertices = {vec2(1, 1), vec2(WIDTH, 1), vec2(1, HEIGHT),
vec2(1, HEIGHT), vec2(WIDTH, 1), vec2(WIDTH, HEIGHT)}
local c1 = color(199, 200, 159)
local c2 = color(203, 214, 89)
bm.colors = {c2, c2, c1, c1, c2, c1}
textMode(CORNER)
font("Inconsolata")
end

function draw()
if ElapsedTime - sTime > step and count < maxCount then
l:grow()
sTime = ElapsedTime
count = count + 1
end
background(0)
bm:draw()
fill(0)
local h = HEIGHT - 30
for k, v in pairs(l.rules) do
local r = k.." -> "..v
text(r, 10, h)
h = h - 30
end

translate(WIDTH/2, 0)
l:draw()
end

L = class()

function L:init(root, rules, length, angle)
self.state = root
self.rules = rules
self.length = length
self.angle = angle
self.color = color(255)
local pattern = "(["
for k, v in pairs(rules) do
pattern = pattern..k
end
self.pattern = pattern.."])"
end

function L:draw()
local stack = {}
pushMatrix()
pushStyle()
stroke(self.color)
strokeWidth(1)
noSmooth()
local tx, ty, ta = 0, 0, 90
local l = self.length
local a = self.angle
for i = 1, #self.state do
local ntx, nty, nta
local c =self.state:sub(i, i)
if c == "F" then
nta = ta
ntx = tx + l * math.cos(nar)
nty = ty + l * math.sin(nar)
line(tx, ty, ntx, nty)
elseif c == "-" then
nta = (ta - a) % 360
ntx, nty = tx, ty
elseif c == "+" then
nta = (ta + a) % 360
ntx, nty = tx, ty
elseif c == "[" then
stack[#stack + 1] = {tx, ty, ta}
ntx, nty, nta = tx, ty, ta
elseif c == "]" then
ntx, nty, nta = unpack(stack[#stack])
table.remove(stack)
else
ntx, nty, nta = tx, ty, ta
end
tx, ty, ta = ntx, nty, nta
end
popStyle()
popMatrix()
end

function L:grow()
local function f(...)
return self.rules[arg[1]]
end
self.state = self.state:gsub(self.pattern, f)
end

``````

Elsewhere on the Codea Forum, @Herwig and @Bri_G have also posted L-system based code, here and here. This code is shorter, because it makes use of Lua’s powerful `string.gsub()` library function.

The rules of the L-system are represented by a Lua table (referred to in the Codea class `L` by the by the field `rules`). For example, the two rules:

``````
X -> F-[[X]+X]+F[+FX]-X
F -> FF

``````

are represented by the table constructed as:

``````
{
X = "F-[[X]+X]+F[+FX]-X",
F = "FF"
}

``````

You are a code generating machine!

Thank you @Reefwing - I’ll take that as a compliment. I have updated my original post to include further references and explanations.

If anybody should follow the experiments that I post to this forum, they will see that they are only snippets. My current interest is to explore what short but, hopefully, intelligible code can produce.

So, I’d like to take this code and have it generate a mesh object…should be simple to do that…it’s leaves that I don’t know (yet) how to generate. I think the Bloom project will help with that…

It was a compliment @mpilgrem - I’m amazed at how much code you are able to produce on a variety of subjects.

@mpilgrem I’m getting curious as to your background. There’s quite a lot of mathematics behind some of these things you’re doing.