RedLTurtle turtle graphics for RedLSystem



plotting with Pen.  after Flake - "The Computational Beauty of Nature"


see also: RedLSystem


class methods:

*new(lsystem, length, theta, scale, noise)

lsystem - an instance of RedLSystem or a string.

length - line segment length in pixels.  default 40.

theta - angle in degrees.  default 20.

scale - the amount to scale all moving commands ($F, $G, $|) in percent.  default 1.

noise - the amount of uniform noise to add to all angles in radians.  default 0.


instance methods:

draw

start drawing the l-system or string at current Pen position.

defaultCommands

return a dictionary of default (character: function) pairs.

$F: draw forward

$G: go forward

$+: turn right by theta

$-: turn left by theta

$[: push state

$]: pop state

$|: draw forward scaled by depth

an integer before each character repeats that command n times.

addCommand(chr, func)

make up new rules by putting a character: function pair into command dictionary.

arguments passed in to function: depth, depthLength, index

makeWindow(bounds, initAngle)

creates a window and draw the l-system or string.  mainly for testing.

initAngle sets the initial Pen rotation in radians.  default is 0.


instance variables:

<>lsystem

either a RedLSystem or a string.  for strings depth and thereby $| scaling is ignored.

for l-systems (the preferred way) the depth is calculated ($| scaling by generation).

<>length

<>theta

<>scale

<>noise

<>commands

dictionary of current commands.

<>preCommandAction

a general function that gets evaluated right before each command (character in the production array).

arguments passed in to function: depth, depthLength, index



//--simple example using string

RedLTurtle("FF+F").makeWindow;

RedLTurtle("FF+F[+F[+F]]").makeWindow;


//--same string but different length, angle and scale factor

RedLTurtle("FF+F[+F[+F]]", 40, -90, 0.3).makeWindow;


//--adding your own commands

t= RedLTurtle("FF+sFsFsF");

t.commands; //list default commands

t.addCommand($s, {Pen.translate(50, 0)}); //$s will shift 50 px to the right

t.makeWindow;



//--in combo with RedLSystem (the preferred way)

(

l= RedLSystem("B", ($B: "F[-B]+B", $F: "FF"));

6.do{l.next};

RedLTurtle(l, scale:0.94.pow(l.generation)).makeWindow;

)


//--koch curve

(

l= RedLSystem("F", ($F: "F-F++F-F"));

5.do{l.next};

RedLTurtle(l, 40, 60, 0.91.pow(l.generation)).makeWindow(Rect(100, 200, 800, 600), 0.5pi, Point(0.5, 0));

)


//--big h

(

l= RedLSystem("[F]--F", ($F: "|[+F][-F]"));

9.do{l.next};

RedLTurtle(l, 200, 90, 0.65).makeWindow;

)


//--bent big h

(

l= RedLSystem("[F]--F", ($F: "|[+F][-F]"));

9.do{l.next};

RedLTurtle(l, 200, 80, 0.65).makeWindow;

)


//--two y

(

l= RedLSystem("[F]4-F", ($F: "|[+F][-F]"));

9.do{l.next};

RedLTurtle(l, 200, 45, 0.65).makeWindow;

)


//--twig

(

l= RedLSystem("F", ($F: "|[-F][+F]"));

7.do{l.next};

RedLTurtle(l, 200, 20, 0.65, 0.2).makeWindow;

)


//--weed 1

(

l= RedLSystem("F", ($F: "F[-F]F[+F]F"));

6.do{l.next};

RedLTurtle(l, 40, 25, 0.6, 0.2).makeWindow(initTranslate: Point(0.5, 0));

)


//--weed 2

(

l= RedLSystem("F", ($F: "|[-F]|[+F]F"));

7.do{l.next};

RedLTurtle(l, 200, 25, 0.65, 0.2).makeWindow(initTranslate: Point(0.5, 0));

)


//--weed 3

(

l= RedLSystem("F", ($F: "|[-F]|[+F][-F]F"));

5.do{l.next};

RedLTurtle(l, 800, 20, 0.45, 0.2).makeWindow(initTranslate: Point(0.5, 0));

)


//--bush 1

(

l= RedLSystem("F", ($F: "FF+[+F-F-F]-[-F+F+F]"));

5.do{l.next};

RedLTurtle(l, 80, 25, 0.65, 0.1).makeWindow(initTranslate: Point(0.5, 0));

)


//--bush 2

(

l= RedLSystem("F", ($F: "|[+F]|[-F]+F"));

7.do{l.next};

RedLTurtle(l, 600, 20, 0.5, 0.1).makeWindow(initTranslate: Point(0.5, 0));

)


//--tree 1

(

l= RedLSystem("F", ($F: "|[3-F][3+F]|[--F][++F]|F"));

6.do{l.next};

RedLTurtle(l, 400, 20, 0.5, 0.1).makeWindow(initTranslate: Point(0.5, 0.1));

)


//--tree 2

(

l= RedLSystem("F", ($F: "|[5+F][7-F]-|[4+F][6-F]-|[3+F][5-F]-|F"));

4.do{l.next};

RedLTurtle(l, 300, 8, 0.5, 0.1).makeWindow(initTranslate: Point(0.5, 0.1));

)


//--tree 3

(

l= RedLSystem("F", ($F: "|[--F][+F]-F"));

7.do{l.next};

RedLTurtle(l, 400, 20, 0.65, 0.1).makeWindow(initTranslate: Point(0.5, 0));

)


//--carpet

(

l= RedLSystem("F-F-F-F", ($F: "F[F]-F+F[--F]+F-F"));

4.do{l.next};

RedLTurtle(l, 4, 90, 1).makeWindow(initTranslate: Point(2/3, 1/3));

)


//--sierpinski square

(

l= RedLSystem("F-F-F-F", ($F: "FF[-F-F-F]F"));

4.do{l.next};

RedLTurtle(l, 4, 90, 1).makeWindow(initTranslate: Point(2/3, 1/3));

)


//--rug

(

l= RedLSystem("F-F-F-F", ($F: "F[-F-F]FF"));

4.do{l.next};

RedLTurtle(l, 4, 90, 1).makeWindow(initTranslate: Point(2/3, 1/3));

)


//--koch island

(

l= RedLSystem("F++F++F", ($F: "F-F++F-F"));

4.do{l.next};

RedLTurtle(l, 5, 60, 1).makeWindow(initTranslate: Point(1/3, 1/3));

)


//--quadric koch island

(

l= RedLSystem("F-F-F-F", ($F: "F-F+F+FF-F-F+F"));

4.do{l.next};

RedLTurtle(l, 1, 90, 1).makeWindow(initTranslate: Point(2/3, 1/3));

)


//--square spikes

(

l= RedLSystem("F18-F18-F18-F", ($F: "F17-F34+F17-F"));

5.do{l.next};

RedLTurtle(l, 60, 5, 0.94.pow(l.generation)).makeWindow(initTranslate: Point(0.75, 0.25));

)


//--sierpinski gasket

(

l= RedLSystem("F--F--F", ($F: "F--F--F--GG", $G: "GG"));

6.do{l.next};

RedLTurtle(l, 5, 60, 1).makeWindow(initAngle: 0.5pi, initTranslate: Point(2/3, 1/3));

)


//--sierpinski maze

(

l= RedLSystem("F", ($F: "[GF][+G3-F][G+G+F]", $G: "GG"));

6.do{l.next};

RedLTurtle(l, 5, 60, 1).makeWindow(initAngle: 1.5pi, initTranslate: Point(1/3, 1/3));

)


//--sierpinski arrowhead

(

l= RedLSystem("F", ($F: "[-G+++F][-G+F][GG--F]", $G: "GG"));

6.do{l.next};

RedLTurtle(l, 5, 60, 1).makeWindow(initAngle: 0.5pi, initTranslate: Point(2/3, 1/3));

)


//--penrose snowflake

(

l= RedLSystem("F4-F4-F4-F4-F", ($F: "F4-F4-F10-F++F4-F"));

4.do{l.next};

RedLTurtle(l, 60, 18, 0.65).makeWindow(initTranslate: Point(0.75, 1/3));

)


//--penrose tile

(

l= RedLSystem("[X]++[X]++[X]++[X]++[X]", ($W: "YF++ZF4-XF[-YF4-WF]++", $X: "+YF--ZF[3-WF--XF]+", $Y: "-WF++XF[3+YF++ZF]-", $Z: "--YF4+WF[+ZF4+XF]--XF", $F: ""));

5.do{l.next};

RedLTurtle(l, 20, 36, 1).makeWindow;

)


//--dragon curve

(

l= RedLSystem("F", ($F: "[+F][+G--G4-F]", $G: "-G++G-"));

11.do{l.next};

RedLTurtle(l, 5, 45, 1).makeWindow(initAngle: 0.5pi, initTranslate: Point(0.5, 0.5));

)




(

l= RedLSystem("F", ($F: "F[+F--F]+F"));

6.do{l.next};

RedLTurtle(l, 40, 10, 0.9, 0.1).makeWindow;

)


(

l= RedLSystem("F", ($F: "F[-FFF--F]+F"));

5.do{l.next};

RedLTurtle(l, 20, 20, 0.99, 0.1).makeWindow.view.background_(Color.red);

)


//--custom preCommand action

(

var size;

l= RedLSystem("F", ($F: "F[-BF-B[-F]-F]++F"));

5.do{l.next};

size= l.asString.size;

t= RedLTurtle(l, 60, 66.67, 1, 0.1);

t.preCommandAction= {|depth, depthLength, index|

var c= index/size;

Pen.strokeColor= Color.grey(c, c);

Pen.stroke; //stroke needed because of colour change

};

t.makeWindow;

)