Draws fractals using L-Systems.
'#
'# L-System Fractal Viewer
'# By Rich Dodson a.k.a. Sushimasta
'# 2006
'#
SuperStrict
SeedRnd MilliSecs()
Type TRule
Global _rules:TList = CreateList()
Field _before:String
Field _after:String
Method Construct:TRule(before:String, after:String)
_rules.AddLast(Self)
_before = before
_after = after
Return Self
EndMethod
Method Destruct()
_rules.Remove(Self)
EndMethod
Function GetRules:TList()
Return _rules
EndFunction
Method GetBefore:String()
Return _before
EndMethod
Method GetAfter:String()
Return _after
EndMethod
EndType
Function Rule(before:String, after:String)
New TRule.Construct(before, after)
EndFunction
'#
'# -------------------------
'# L-System Fractal Design
'# Move the fractal around the screen using the mouse
'# Click the left mouse button to draw the next level of the fractal
'# Don't increase the level too high as the time it takes to compute increases exponentially
'#
'# Length of each line
Const radius:Float = 10.0
'# Angle of each turn
Const angle:Float = 60.0
'# Initial axiom for fractal
Local line:String = "F"
'# Rules for expanding a fractal
Rule("F", "F+F--F+F")
'#
'# Rules are in the form of before -> after where each occurance of before is replaced with after
'# In the above example, each occurance of F is is replaced by F+F--F+F
'# Strings are executed as commands to a Turtle drawer
'#
'# Characters:
'# F - Draw a line with length radius
'# + - Turn left by angle
'# - - Turn right by angle
'# [ - Push current state on to stack
'# ] - Pop current state off of stack
'#
'#
'# For example:
'# F
'# F+F--F+F
'# F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F
'# etc, etc.
'# -------------------------
'#
Graphics(800, 600, 32, 60)
HideMouse()
Local timer:TTimer = CreateTimer(60)
Local advance:Int = 0
Repeat
Select WaitEvent()
Case EVENT_KEYDOWN
Select EventData()
Case KEY_ESCAPE
Exit
EndSelect
Case EVENT_MOUSEDOWN
Select EventData()
Case MOUSE_LEFT
advance :+ 1
EndSelect
Case EVENT_TIMERTICK
If EventSource() = timer
Cls
RunTurtle(line, MouseX(), MouseY(), 0.0)
If KeyDown(KEY_TAB)
DrawText(line, 0, 0)
DrawText(line.length, 0, 20)
EndIf
Flip
If advance
Local nline:String = ""
Local p:Int = 0
While p < line.length
Local c:String = line[p..p + 1]
Local matched:Int = False
For Local rule:TRule = EachIn TRule.GetRules()
Local l:Int = rule.GetBefore().length
If line[p..p + l] = rule.GetBefore()
nline :+ rule.GetAfter()
matched = True
p :+ l
Exit
EndIf
Next
If Not matched
nline :+ c
p :+ 1
EndIf
Wend
line = nline
advance :- 1
EndIf
EndIf
EndSelect
Forever
For Local rule:TRule = EachIn TRule.GetRules()
rule.Destruct()
Next
Function RunTurtle(line:String, x:Float, y:Float, a:Float)
Global stack:Float[] = New Float[256]
Global index:Float = 0
For Local p:Int = 0 Until line.length
Local c:String = line[p..p + 1]
If "A" <= c And c <= "Z"
Local nx:Float = x + radius * Cos(a)
Local ny:Float = y + radius * Sin(a)
DrawLine(x, y, nx, ny)
x = nx
y = ny
Else
Select c
Case "+"
a :- angle
Case "-"
a :+ angle
Case "["
stack[index] = x
stack[index + 1] = y
stack[index + 2] = a
index :+ 3
Case "]"
index :- 3
x = stack[index]
y = stack[index + 1]
a = stack[index + 2]
EndSelect
EndIf
Next
EndFunction
|