L-System Fractal Viewer

Community Forums/Showcase/L-System Fractal Viewer

rdodson41(Posted 2006) [#1]
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



GfK(Posted 2006) [#2]
Executable? Screenshots?

I can't be bothered to mess about running code without really knowing what it does.


rdodson41(Posted 2006) [#3]
Gfk, it really doesn't take much effor to press control-c and control-v, but if you don't want to then you wont be able to see the neat fractals that this can make pretty easily.


Torrente(Posted 2006) [#4]
Gor those of you who don't know what L-Systems are:
pic1
pic2
Those are from a Lindenmeyer System program that I wrote a while ago, perhaps I'll release it in time.

Your code is very simple and easy to understand, I like the way you implemented the stacks.


GfK(Posted 2006) [#5]
Gfk, it really doesn't take much effor to press control-c and control-v
you're right, it doesn't. But a lot of people won't look if you don't post screenshots at least. Plus by posting code only, you're stopping people that don't have BlitzMax from seeing it.

Your call, though. :)


rdodson41(Posted 2006) [#6]
Very nice Torrente.

@Gfk - I could post a MacOSX executable but then even fewer people would be able to use my program. And I don't have anywhere on the net to put any screenshots. So if you're interested, then you can run the program.

Here some more examples to play around with:
'# Tree
Const radius:Float = 10.0
Const angle:Float = 60.0

Local line:String = "F"
Rule("F", "F[+F]F[-F]F")

'# C Curve
Const radius:Float = 10.0
Const angle:Float = 45.0

Local line:String = "F"
Rule("F", "+F--F+")

'# Hilbert Curve
Const radius:Float = 10.0
Const angle:Float = 90.0

Local line:String = "x"
Rule("x", "-yF+xFx+Fy-")
Rule("y", "+xF-yFy-Fx+")

By the way, Torrente, what language did you write your l-system program in?
I made a nice l-system program in java for a school project.


Torrente(Posted 2006) [#7]
Mine was in BlitzMax, and the editor for them was in C#.
In the editor, you would specify the starting string, rules, size, and a few other variables, which would output a text file that you could load up into the BlitzMax program and view.


rdodson41(Posted 2006) [#8]
Yeah I made a similar program in java, I just made it all into one program, but it had the same idea.


Grey Alien(Posted 2006) [#9]
Thanks for the screenshots Torrente.