## `plot::Lsys` -- graphical primitive for a Lindenmayer system

#### Introduction

`plot::Lsys``(deg, start, rule...)` represents a Lindenmayer system with turning degree `deg`, starting word `start` and rule set `rule...`.

#### Creating Elements

`plot::Lsys(deg, start, rule...)`

#### Parameters

`deg` | - | the degree by which the turtle turns left or right, an arithmetical expression
`start` | - | the starting word of the system, a string
`rule` | - | a rule of the system, an equation

#### Related Domains

`plot::Scene`, `plot::Turtle`

#### Related Functions

`plot`

#### Details

- Objects generated by `plot::Lsys` represent Lindenmayer systems. Lindenmayer systems are a means to describe the growth of plants and may be used to create beautiful recursive drawings.
- A Lindenmayer system (A,R,s) is quite similar to a usual context-free grammar. One has a finite set A of characters (the alphabet), a map R : A →A* and a non-empty starting word s, an element of A*. (A* are the words with characters from A.) For each a ∈A the pair (a,R(a)) is called a rule and is written as a →b1 b2 ...bn where R(a) = b1 b2 ...bn ∈A*. a is the left hand side and b1 b2 ...bn the right hand side of the rule.

  A Lindenmayer system describes a language L, a subset of A*. The language is defined as follows:

  - s is an element of L.
  - Let w be an element of L, let w be the word where each character a of w has been replaced by R(a). Then w is in L.
  The language L can be created as follows: From the starting word s = s0 the word s1 is created (by replacing all characters by right hand sides of the corresponding rules). From s1 the word s2 is created, from that s3 and so on. Call si the i-th generation of the starting word s.
- The interesting part of the story is the interpretation of the words si of the language L. Here a creature called turtle enters the picture, it helps to visualize the words of the language. A turtle is a drawing device which understands few simple commands. Given a word of the language L each character of the word is interpreted as a command for the turtle. The word turns into a picture with the help of the turtle.

  A turtle has a position in the plane, a direction and a colour. It understands only few commands: Move forward and draw a line, move without drawing, turn left, turn right, change your colour. Further a turtle may remember its current state (position, direction and colour) by pushing it onto a stack and change its state to a former one by popping it off from the stack. For each character of the alphabet A one of these turtle commands may be defined. A character may also have no command, causing the turtle to do nothing.

- `plot::Lsys` allows the definition of Lindenmayer systems and the plotting of words defined by the system. The domain `plot::Turtle` creates turtles, it may be useful for other purposes than plotting words of Lindenmayer systems.
- Regarding the definition of a Lindenmayer system:
  - The starting word `start` is interpreted as the starting word of the Lindenmayer system, each character in the string represents a character of the system.
  - Each rule must be of the form `lhs = rhs` where the left hand side `lhs` must be a string of lenght 1. The right hand side `rhs` must be a string, a turtle command or a colour value.

    A left hand side is interpreted as single character of the Lindenmayer system. A right hand side which is a string is interpreted as the word which replaces the left hand character. Each character in the string represents a character of the system.

    A right hand side which is a turtle command or a colour value desribe how a word generated by the Lindenmayer system is to be interpreted by the turtle. A turtle command or a colour value changes the actual state of the turtle and moves it around.

    A turtle command may be one of the identifiers `Move`, `Line`, `Left`, `Right`, `Push` or `Pop`. These commands cause the turtle to move without drawing, to draw a line, to turn left or right and to push or pop its current state. A colour value must be a list of three numbers `[r,g,b]` defining new red-, green- and blue colour values of the turtle. The colour values must be in the range between 0 and 1 like the colour values in the other plot commands.

  The following default rules for the turtle commands exist:
  - `"F" = Line`
  - `"f" = Move`
  - `"+" = Left`
  - `"-" = Right`
  - `"[" = Push`
  - `"]" = Pop`
  These rules are used if no other rules for the turtle commands are defined.
- In order to do a turtle plot defined by a Lindenmayer system one further needs to specify which generation of the starting word of the system is to be plotted. The default generation is the fifth one. One may use the systems `"generations"` attribute to change the generation, see below.
- A certain generation of a Lindenmayer system `l` can be displayed via the call `plot(l)`, or used with other graphical primitives of the `plot` library.
- An object of `plot::Lsys` has type `"graphprim"`, i.e., if `o` is such an object, then the result of `type(o)` is the string `"graphprim"`.
- A so-called attribute of a graphical primitive is a named entry of the object which can be accessed via the slot operator `::`.

  Each attribute has the property ``read'', i.e., the value of an attribute `attr` of a graphical primitive `o` can be read with `o::attr`. If the attribute also has the ``write'' property, then the value of the attribute can be changed with `o::attr := new_value`.

  The following attributes are available for a Lindenmayer system:

  attribute | meaning | properties
  `generations` | The generation of the system which is to be plotted, a positive integer. | read/write

  See the help page of `plot::Curve2d` for examples for working with attributes of graphical primitives.

#### Result of Evaluation

Evaluating an object of type `plot::Lsys` returns itself.

#### Method getPlotdata: create the plot data of a Lindenmayer system

- `getPlotdata(dom l)`
- - Returns a list of an inner list, where the inner list is a plot description of `l` in a `plot2d` and `plot3d` conforming syntax, respectively, i.e., it has the form `[Mode = List, [polygon(...)], ...]`.
  - The plot data returned are the plot data of the turtle defined by the actual generation of the system.
  - This method is called from `plot::Scene` to build the plot data of the graphical scene.

#### Method slot: read and write attributes and plot options

- `slot(dom l, string slotname)`
- - Reads the value of the slot `slotname` of `l`. `slotname` may be the name of an attribute. See the tables of available plot attributes above.
  - If `slotname` is an invalid attribute, then an error message is issued.
  - This method overloads the system function `slot`, i.e., one may use it in the form `l::slotname_id` (here, `slotname_id` must be the identifier corresponding to the string `slotname`), or in functional notation `slot(l, slotname)`.
- `slot(dom l, string slotname, any val)`
- - Changes the value of the attribute with the name `slotname` to the value `val`.
  - If there is no attribute with the name `slotname`, or if `val` is not an admissible value for `slotname`, then a warning message is issued. In this case, the value of `slotname` remains unchanged.
  - This method overloads the system function `slot`, i.e., one may use it in the form `l::slotname_id := val` (here, `slotname_id` must be the identifier corresponding to the string `slotname`), or in functional notation `slot(l, slotname, val)`.

#### Method print: print a Lindenmayer system

- `print(dom l)`
- - This method returns an unevaluated expression of the form `plot::Lsys(deg, start, rule...)`. It is used to print objects of `plot::Lsys` to the screen.
  - See the system function `print` for details.

#### Example 1

We simply list some examples without any interpretation:

    >> L := plot::Lsys(90, "F-F-F-F", "F"="F-F+F+FF-F-F+F"):
       L::generations := 4:
       plot(L, Axes = None)

    >> L := plot::Lsys(90, "F-F-F-F", "F"="FF-F--F-F"):
       L::generations := 4:
       plot(L, Axes = None)

    >> L := plot::Lsys(90, "F-F-F-F", "F"="FF-F+F-F-FF"):
       L::generations := 4:
       plot(L, Axes = None)

    >> L := plot::Lsys(90, "L", "L"="L+R+", "R"="-L-R", "L"=Line, "R"=Line):
       L::generations := 10:
       plot(L, Axes = None)

    >> L := plot::Lsys(60, "R", "L"="R+L+R", "R"="L-R-L", "L"=Line, "R"=Line):
       L::generations := 7:
       plot(L, Axes = None)

    >> L := plot::Lsys(20, "L", "L"="R[+L]R[-L]+L", "R"="RR", "L"=Line, "R"=Line):
       L::generations := 6:
       plot(L, Axes = None)

    >> L := plot::Lsys(20, "L", "L"="BR[+HL]BR[-GL]+HL", "R"="RR",
                       "L"=Line, "R"=Line,
                       "B"=RGB::Brown, "H"=RGB::ForestGreen,
                       "G"=RGB::SpringGreen):
       L::generations := 6:
       plot(L, Axes = None)

    >> L := plot::Lsys(60, "F++F++F", "F"="F-F++F-F"):
       L::generations := 5:
       plot(L, Axes = None)

#### Changes

- used to be called `Lsys`
- Adapted to comply with the `plot` library.

Do you have questions or comments?
Copyright © SciFace Software GmbH & Co. KG 2000