# [Edu-sig] Re: Implementing an Lsystem (edu-sig Python project)

Kirby Urner pdx4d@teleport.com
Thu, 06 Jul 2000 17:06:24 -0700

```Note:  This is part 2.  Part 1 is at:
http://www.python.org/pipermail/edu-sig/2000-July/000545.html
============

In the shoptalk of Lsystems, you start with axioms and rules of
production.  An axiom is a string like:

>>> axiom = 'F--F--F'

and your rules of production define substitions, such as:

>>> rules = {}
>>> rules['F'] = 'F+F--F+F'

To apply the rules to an axiom is to scan a string, and
substitute wherever appropriate, e.g. every occurance of 'F' in
the above axiom would be replaced by 'F+F--F+F'.[1]

Since the '-' symbol is not associated with a substition rule,
it would simply pass through as is:

>>> def produce(axiom,rules):
output = ""
for i in axiom:
output = output + rules.get(i,i)
return output

Notice that the dictionary.get() method takes 2 arguments, the
2nd being what to return if the 1st is not a key.  For example,
if i = 'F', then the rule for 'F' will be invoked, but if i =
'-', then '-' will simply pass through to the growing output
string.

>>> produce(axiom,rules)
'F+F--F+F--F+F--F+F--F+F--F+F'
>>> newaxiom = produce(axiom,rules)
>>> produce(newaxiom,rules)
'F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F--F+F--F+F+F+F--
F+F--F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F'

Another example:

>>> rules = {}
>>> rules['A'] = 'B'
>>> rules['B'] = 'AB'
>>> axiom = 'A'

This sets up the example used at:
http://www.csu.edu.au/complex_systems/tutorial2.html

We'll define iterate as a recursive function:

>>> def iterate(n,axiom,rules):
print axiom
if n>0:
axiom = produce(axiom,rules)
return iterate(n-1,axiom,rules)

>>> iterate(7,axiom,rules)
A
B
AB
BAB
ABBAB
BABABBAB
ABBABBABABBAB
BABABBABABBABBABABBAB

Basically, our Lparser class needs to read in a file consisting
of an axiom and some rules, plus other parameters such as how
many times to recursively apply the rules, what the default
angle of rotation is and so on.

Let's look at a real example of an .ls file, included with the

http://www.xs4all.nl/~ljlapre/lparser.htm

#===================================================
#  Crystals.ls         (c) C.J. van der Mark
#
#      Questions about Lparser files to:
#        Internet  cvdmark@xs4all.nl
#           Fido      2:283/203.11
#           PCG       9:526/464.3
#===================================================
15
20
20
I
I=+(40)ffHccI
H=[+fffG]c[-fffG]c[^fffG]c[&fffG]G
G=[dS]e[d]e[d]e[d]e[d]e[d]e[d]e[d]
e=+(90)f-(90)>(-45)
d={[f+(90)f+(90)f+(90)f>(+38)-(105)ff-(151)ff][f&(38)+(15)ff+(151)ff]}
@

Rules are defined by equal signs.  The axiom is given by a
letter alone, after some numbers, in this case I.  As per
http://www.xs4all.nl/~cvdmark/tutor.html, the first 3 numbers
represent:

15    # recursion depth
20    # angle
20    # thickness as % of length

In Python:

>>> rules = {}
>>> rules['I']='+(40)ffHccI'
>>> rules['H']='[+fffG]c[-fffG]c[^fffG]c[&fffG]G'
>>> rules['G']='[dS]e[d]e[d]e[d]e[d]e[d]e[d]e[d]'
>>> rules['e']='+(90)f-(90)>(-45)'
>>>
rules['d']='{[f+(90)f+(90)f+(90)f>(+38)-(105)ff-(151)ff][f&(38)+(15)ff+(151)
ff]}'
>>> axiom = 'I'
>>> iterate(2,axiom,rules)
I
+(40)ffHccI
+(40)ff[+fffG]c[-fffG]c[^fffG]c[&fffG]Gcc+(40)ffHccI

And that's only 2 iterations.  After 15, we'd have a very long
string of commands to feed to our Lturtle.

Let's use the DOS lparser.exe to generate a Povray file
corresponding to Crystals.ls:

lparser -vc -g Crystals

Running in a DOS box, I get the following output in response
to the above input:

L-System Parser/Mutator v4.0
---------------------------------------------------------
Copyright (C)  : RenderStar Technology BV. 1992-1995
Release date   : Dec 27 1995 (386+/DOS)
---------------------------------------------------------
Sizing memory
L-system file  : .\crystals.ls
Recursion depth: 15
Basic angle    : 20
Thickness      : 20
Axiom          : I
Rule           : I=+(40)ffHccI
Rule           : H=[+fffG]c[-fffG]c[^fffG]c[&fffG]G
Rule           : G=[dS]e[d]e[d]e[d]e[d]e[d]e[d]e[d]
Rule           : e=+(90)f-(90)>(-45)
Rule           :
d={[f+(90)f+(90)f+(90)f>(+38)-(105)ff-(151)ff][f&(38)+(15)ff+(1
51)ff]}
Size of string : 41480 chars
Pov file       : output.inc
Objects        : 5761
End

Then the instructions tell me:

The file 'setup1.pov' can be used to connect to the output.inc file
created with lparser -vc. The first 8 colors in the pov rendering
will then match the ones in the viewer.

But I didn't get a very good rendering after all that.  Had to
tweak it quite a bit (monkey around with lighting and camera
angle).  Here's the result:

http://www.inetarena.com/~pdx4d/ocn/graphics/lsystems1.gif

Kirby

ERRATUM:

In my previous post I wrote:

> I was exploring in ActiveWorlds Education Universe today
> (http://edu.activeworlds.com/top.html), and went again to
> Bonnie DeVarco's Virtual High School (VHS), a fave location
> in TheU, one of 133 worlds in Education Universe.

The URL should have just been: http://edu.activeworlds.com/

Notes:

[1]  This example from Tim Wegner, 'Image Lab' (The Waite Group
Press, 1992), pg. 256

```