Tiny L-System
Tiny LSystem Demo
F - forward with drawing
b - forward without drawing
+ - increase angle
- - decrease angle
[ - save state in stack
] - return to previous state
♥0 |
Line 179 |
Modified 2013-09-01 00:52:48 |
MIT License
archived:2017-03-10 13:21:10
ActionScript3 source code
/**
* Copyright smirnov48 ( http://wonderfl.net/user/smirnov48 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/gFSw
*/
/**
* Tiny LSystem Demo
*
* F - forward with drawing
* b - forward without drawing
* + - increase angle
* - - decrease angle
* [ - save state in stack
* ] - return to previous state
*/
package {
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class TinyLSystemDemo extends Sprite {
private var view:int = 0;
private var tinyLSystem:TinyLSystem;
public function TinyLSystemDemo() {
var timer:Timer = new Timer(4000);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
onTimer(null);
}
private function onTimer(event:TimerEvent):void {
if (tinyLSystem) {
removeChild(tinyLSystem);
tinyLSystem = null;
}
tinyLSystem = new TinyLSystem();
switch (view++) {
case 0:
/* Koch Snowflake */
tinyLSystem.setLength(0.4);
tinyLSystem.setAngle(Math.PI/3);
tinyLSystem.setAxiom("F++F++F");
tinyLSystem.setRule("F", "F-F++F-F");
tinyLSystem.setIterations(5);
break;
case 1:
/* Island */
tinyLSystem.setLength(2);
tinyLSystem.setAxiom("F+F+F+F");
tinyLSystem.setRule("F", "F+F-F-FFF+F+F-F");
tinyLSystem.setIterations(3);
break;
case 2:
/* Chain */
tinyLSystem.setLength(2);
tinyLSystem.setAxiom("F+F+F+F");
tinyLSystem.setRule("F", "F+b-F-FFF+F+b-F");
tinyLSystem.setRule("b", "bbb");
tinyLSystem.setIterations(3);
break;
case 3:
/* Dragon Curve */
tinyLSystem.setLength(4);
tinyLSystem.setAxiom("FX");
tinyLSystem.setRule("X", "X+YF+");
tinyLSystem.setRule("Y", "-FX-Y");
tinyLSystem.setIterations(12);
break;
case 4:
/* Snowflake */
tinyLSystem.setLength(1);
tinyLSystem.setAngle(Math.PI/3);
tinyLSystem.setAxiom("[F]+[F]+[F]+[F]+[F]+[F]");
tinyLSystem.setRule("F", "F[+FF][-FF]FF[+F][-F]FF");
tinyLSystem.setIterations(3);
view = 0;
break;
}
addChild(tinyLSystem);
tinyLSystem.draw();
tinyLSystem.x = stage.stageWidth/2;
tinyLSystem.y = stage.stageHeight/2;
}
}
}
import flash.display.Sprite;
internal class TinyLSystem extends Sprite {
private var length:Number = 2;
private var angle:Number = Math.PI/2;
private var iterations:int = 5;
private var axiom:String = 'F';
private var rules:Array = new Array();
private var sequence:String;
public function setLength(len:Number):void {
length = len;
}
public function setAngle(a:Number):void {
angle = a;
}
public function setAxiom(str:String):void {
axiom = str;
}
public function setRule(token:String, replacement:String):void {
rules.push({token:token, replacement:replacement});
}
public function setIterations(i:int):void {
iterations = i;
}
public function draw():void {
computeResultSequence();
var turtle:Turtle = new Turtle(this);
turtle.setStepLength(length);
turtle.setRotationAngle(angle);
for (var i:int = 0; i < sequence.length; i++) {
var command:String = sequence.charAt(i);
turtle.processCommand(command);
}
}
private function computeResultSequence():void {
sequence = axiom;
for (var i:int = 0; i < iterations; i++) {
var temp:String = '';
for (var k:int = 0; k < sequence.length; k++) {
var token:String = sequence.charAt(k);
var wasInRules = false;
for (var j:int = 0; j < rules.length; j++) {
if (rules[j].token == token) {
temp += rules[j].replacement;
wasInRules = true;
break;
}
}
if (!wasInRules) {
temp += token;
}
}
sequence = temp;
}
}
}
internal class Turtle {
public var stack:Array = new Array();
private var length:Number = 2;
private var angle:Number = Math.PI/2;
private var canvas:Sprite;
private var curAngle:Number = 0;
private var x:Number = 0;
private var y:Number = 0;
public function Turtle (canvas:Sprite) {
this.canvas = canvas;
canvas.graphics.lineStyle(0,0x000000);
canvas.graphics.moveTo(x,y);
}
public function setStepLength(length:Number):void {
this.length = length;
}
public function setRotationAngle(angle:Number):void {
this.angle = angle;
}
public function processCommand(command:String):void {
switch (command) {
case 'F':
x += Math.cos(curAngle) * length;
y += Math.sin(curAngle) * length;
canvas.graphics.lineTo(x,y);
break;
case 'b':
x += Math.cos(curAngle) * length;
y += Math.sin(curAngle) * length;
canvas.graphics.moveTo(x,y);
break;
case '+':
curAngle += angle;
break;
case '-':
curAngle -= angle;
break;
case '[':
stack.push(new State(x,y,curAngle));
break;
case ']':
var prev:State = stack.pop() as State;
x = prev.x;
y = prev.y;
canvas.graphics.moveTo(x,y);
curAngle = prev.angle;
break;
default :
/* Nothing */
}
}
}
internal class State {
public var x:Number;
public var y:Number;
public var angle:Number;
public function State(x:Number, y:Number, angle:Number){
this.x = x;
this.y = y;
this.angle = angle;
}
}