June 2014

Introduction and basics

This article is not fully finished yet, it will be extended in the future.

3 Interpretation

Previous chapter described how to produce symbols and this chapter shows how to use them to draw some cool stuff! Every symbol can be associated with some action. The set of available actions is given by a processor that is specified by process keyword. For example, all examples in previous chapter were using SymbolPrinter processor that has no actions, it just prints the symbols as text.

3.1 Turtle graphics interpratation

The simplest interpretation of L-system symbols is using Turtle graphics. Turtle graphics interprets symbols as basic commands for virtual pen on 2D canvas (or evein in 3D space). Virtual pen was explained for kids as a turtle walking on a beach drawing to sand with its tail. The pen can move or draw forward, change direction, color or other attributes. It is also possible save or load a state of the pen (using stack data structure). Following list shows all actions of Turtle interpreter (withdrawn from components list).

  • Nothing — Symbol is ignored.

  • GoTo — Moves turtle to given position. Rotation (orientation) is not changed. This method can be called both with coordinates as separate arguments or with array containing coordinates.

  • MoveForward — Moves forward in current direction (without drawing) by distance equal to value of the first parameter.

  • DrawForward — Draws line in current direction with length equal to value of first parameter.

  • DrawCircle — Draws circle with center in current position and radius equal to value of the first parameter.

  • DrawSphere — Draws sphere with center in current position and radius equal to value of the first parameter.

  • TurnLeft — Turns left by value of the first parameter (in degrees) (in X-Y plane, around axis Z).

  • Yaw — Turns left around up vector axis (default Y axis [0, 1, 0]) by value given in the first parameter (in degrees).

  • Pitch — Turns up around right-hand vector axis (default Z axis [0, 0, 1]) by value given in the first parameter (in degrees).

  • Roll — Rolls clock-wise around forward vector axis (default X axis [1, 0, 0]) by value given in the first parameter (in degrees).

  • StartBranch — Saves current state (on stack).

  • EndBranch — Loads previously saved state (returns to last saved position).

  • StartPolygon — Starts to record polygon vertices (do not saves current position as first vertex). If another polygon is opened, its state is saved and will be restored after closing of current polygon.

  • RecordPolygonVertex — Records current position to opened polygon.

  • EndPolygon — Ends current polygon (do not saves current position as last vertex).

Without any further theory let's draw the first fractal using L-systems. Let's start with simple Koch curve. The syntax is hopefully quite self-explanatory for now and will be explained in more detail shortly.

Input

1
2
3
4
5
6
7
8
9
10
11
lsystem KochCurve {
set symbols axiom = F;
set iterations = 3;
interpret F as DrawForward(20);
interpret + as TurnLeft(60);
interpret - as TurnLeft(-60);
rewrite F to F + F - - F + F;
}
process all with SvgRenderer;

Output

Cool, right? Let's dig into details of the Koch curve L-systems a little bit. To see what is happening we can visualize every iteration by setting property interpretEveryIteration to true. As you can see, koch curve starts as a single line represented by symbol F and this symbol is rewritten to a sequence F + F - - F + F. If you dont understand what the F + F - - F + F sequence represents just grab a piece of paper with pencil and try to draw it. Symbol F means draw a line segment and symbolse + and - represents 60 degrees turn left or right respectively. Every line segment gets replaced by a line with a triangle in the middle.

Input

1
2
3
4
5
6
7
8
9
10
11
12
lsystem KochCurve {
set symbols axiom = F;
set iterations = 3;
set interpretEveryIteration = true;
interpret F as DrawForward(20);
interpret + as TurnLeft(60);
interpret - as TurnLeft(-60);
rewrite F to F + F - - F + F;
}
process all with SvgRenderer;

Output

The example can be improved even further by scaling down the line lengths every iteration so the whole image has the same size. If you think about the math a little bit, every line of length x gets rewritten to a line with a triangle where distance between starting and ending points is 3 x. We need to make lines three-times shorter every iteration. This can be achieved in many ways but the simplest way is to use variable currentIteration that represents number of current iteration.

Input

1
2
3
4
5
6
7
8
9
10
11
12
lsystem KochCurve {
set symbols axiom = F;
set iterations = 3;
set interpretEveryIteration = true;
interpret F as DrawForward(300 * 3 ^ -currentIteration);
interpret + as TurnLeft(60);
interpret - as TurnLeft(-60);
rewrite F to F + F - - F + F;
}
process all with SvgRenderer;

Output

This article is not fully finished yet, it will be extended in the future.