Title: | Functions to Explore L-Systems (Lindenmayer Systems) |
---|---|
Description: | L-systems or Lindenmayer systems are parallel rewriting systems which can be used to simulate biological forms and certain kinds of fractals. Briefly, in an L-system a series of symbols in a string are replaced iteratively according to rules to give a more complex string. Eventually, the symbols are translated into turtle graphics for plotting. Wikipedia has a very good introduction: en.wikipedia.org/wiki/L-system This package provides basic functions for exploring L-systems. |
Authors: | Bryan Hanson [aut, cre] |
Maintainer: | Bryan Hanson <[email protected]> |
License: | GPL (>= 3) |
Version: | 0.1.14 |
Built: | 2024-11-19 04:40:10 UTC |
Source: | https://github.com/bryanhanson/lindenmayer |
Functions to Explore L-Systems (Lindenmayer Systems)
Lindenmayer or L-systems are parallel rewriting systems which can be used to simulate biological forms and certain kinds of fractals. Briefly, in an L-system a series of symbols in a string are replaced iteratively according to rules to give a more complex string. Eventually, the symbols are translated into turtle graphics for plotting. Wikipedia has a very good introduction: https://en.wikipedia.org/wiki/L-system This package provides basic functions for exploring L-systems.
Bryan A. Hanson
This function takes input strings, previously created with Lsys
,
translates them into 2D turtle graphics instructions, and then plots the results.
drawLsys(string = NULL, drules = NULL, st = c(5, 50, 0), stepSize = 1, ang = 90, which = length(string), shrinkFactor = NULL, ...)
drawLsys(string = NULL, drules = NULL, st = c(5, 50, 0), stepSize = 1, ang = 90, which = length(string), shrinkFactor = NULL, ...)
string |
A character vector giving the strings containing the turtle graphics
instructions. Created by |
drules |
A data frame containing columns "symbols" and "action". These contain the input
symbols and the corresponding drawing action. The symbol column is in the
character set used by
See the examples. Note that the "action" entry always uses these symbols, though not all of them need be used. |
st |
A numeric vector of length 3 giving the screen coordinates where the start of the curve should be placed. The screen is 100 x 100 with the lower left corner as 0,0. The third element is the initial drawing angle in degrees. |
stepSize |
Numeric. The length of the drawing step. |
ang |
Numeric. The angle in degrees when a change in direction is requested. |
which |
Integer. The entries in |
shrinkFactor |
A numeric vector of the same length as |
... |
Additional parameters to be passed to the |
None; side effect is a plot.
Remember that if retAll = TRUE
, Lsys
returns
the initial string plus the results of all iterations. In this case, if you want
the 5th iteration, you should specify which = 6
since
the initial string is in string[1]
.
require('grid') # Modified Koch curve rkoch1 <- data.frame(inp = c("F"), out = c("F+F-F-F+F"), stringsAsFactors = FALSE) k1 <- Lsys(init = "F", rules = rkoch1, n = 3) dkoch <- data.frame(symbol = c("F", "f", "+", "-", "[", "]"), action = c("F", "f", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = k1, stepSize = 3, st = c(10, 50, 0), drules = dkoch) grid.text("Modified Koch Curve (n = 3)", 0.5, 0.25) # Classic Koch snowflake rkoch2 <- data.frame(inp = c("F"), out = c("F-F++F-F"), stringsAsFactors = FALSE) k2 <- Lsys(init = "F++F++F", rules = rkoch2, n = 4) drawLsys(string = k2, stepSize = 1, ang = 60, st = c(10, 25, 0), drules = dkoch) grid.text("Classic Koch Snowflake (n = 4)", 0.5, 0.5) # Sierpinski Triangle rSierp <- data.frame(inp = c("A", "B"), out = c("B-A-B", "A+B+A"), stringsAsFactors = FALSE) s <- Lsys(init = "A", rules = rSierp, n = 6) dSierp <- data.frame(symbol = c("A", "B", "+", "-", "[", "]"), action = c("F", "F", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = s, stepSize = 1, ang = 60, st = c(20, 25, 0), drules = dSierp) grid.text("Sierpinski Triangle (n = 6)", 0.5, 0.1) # Islands & Lakes islands_rules <- data.frame(inp = c("F", "f"), out = c("F+f-FF+F+FF+Ff+FF-f+FF-F-FF-Ff-FFF", "ffffff"), stringsAsFactors = FALSE) islands <- Lsys(init = "F+F+F+F", rules = islands_rules, n = 2) draw_islands <- data.frame(symbol = c("F", "f", "+", "-", "[", "]"), action = c("F", "f", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = islands, step = 1, ang = 90, st = c(70, 35, 90), drules = draw_islands, gp = gpar(col = "red", fill = "gray")) # A primitive tree (aka Pythagoras Tree) prim_rules <- data.frame(inp = c("0", "1"), out = c("1[+0]-0", "11"), stringsAsFactors = FALSE) primitive_plant <- Lsys(init = "0", rules = prim_rules, n = 7) draw_prim <- data.frame(symbol = c("0", "1", "+", "-", "[", "]"), action = c("F", "F", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = primitive_plant, stepSize = 1, ang = 45, st = c(50, 5, 90), drules = draw_prim, which = 7) grid.text("Primitive Tree (n = 6)", 0.5, 0.75) # A more realistic botanical structure # Some call this a fractal tree, I think it is more like seaweed # Try drawing the last iteration (too slow for here, but looks great) fractal_tree_rules <- data.frame(inp = c("X", "F"), out = c("F-[[X]+X]+F[+FX]-X", "FF"), stringsAsFactors = FALSE) fractal_tree <- Lsys(init = "X", rules = fractal_tree_rules, n = 7) draw_ft <- data.frame(symbol = c("X", "F", "+", "-", "[", "]"), action = c("f", "F", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = fractal_tree, stepSize = 2, ang = 25, st = c(50, 5, 90), drules = draw_ft, which = 5, gp = gpar(col = "chocolate4", fill = "honeydew")) grid.text("Fractal Seaweed (n = 4)", 0.25, 0.25)
require('grid') # Modified Koch curve rkoch1 <- data.frame(inp = c("F"), out = c("F+F-F-F+F"), stringsAsFactors = FALSE) k1 <- Lsys(init = "F", rules = rkoch1, n = 3) dkoch <- data.frame(symbol = c("F", "f", "+", "-", "[", "]"), action = c("F", "f", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = k1, stepSize = 3, st = c(10, 50, 0), drules = dkoch) grid.text("Modified Koch Curve (n = 3)", 0.5, 0.25) # Classic Koch snowflake rkoch2 <- data.frame(inp = c("F"), out = c("F-F++F-F"), stringsAsFactors = FALSE) k2 <- Lsys(init = "F++F++F", rules = rkoch2, n = 4) drawLsys(string = k2, stepSize = 1, ang = 60, st = c(10, 25, 0), drules = dkoch) grid.text("Classic Koch Snowflake (n = 4)", 0.5, 0.5) # Sierpinski Triangle rSierp <- data.frame(inp = c("A", "B"), out = c("B-A-B", "A+B+A"), stringsAsFactors = FALSE) s <- Lsys(init = "A", rules = rSierp, n = 6) dSierp <- data.frame(symbol = c("A", "B", "+", "-", "[", "]"), action = c("F", "F", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = s, stepSize = 1, ang = 60, st = c(20, 25, 0), drules = dSierp) grid.text("Sierpinski Triangle (n = 6)", 0.5, 0.1) # Islands & Lakes islands_rules <- data.frame(inp = c("F", "f"), out = c("F+f-FF+F+FF+Ff+FF-f+FF-F-FF-Ff-FFF", "ffffff"), stringsAsFactors = FALSE) islands <- Lsys(init = "F+F+F+F", rules = islands_rules, n = 2) draw_islands <- data.frame(symbol = c("F", "f", "+", "-", "[", "]"), action = c("F", "f", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = islands, step = 1, ang = 90, st = c(70, 35, 90), drules = draw_islands, gp = gpar(col = "red", fill = "gray")) # A primitive tree (aka Pythagoras Tree) prim_rules <- data.frame(inp = c("0", "1"), out = c("1[+0]-0", "11"), stringsAsFactors = FALSE) primitive_plant <- Lsys(init = "0", rules = prim_rules, n = 7) draw_prim <- data.frame(symbol = c("0", "1", "+", "-", "[", "]"), action = c("F", "F", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = primitive_plant, stepSize = 1, ang = 45, st = c(50, 5, 90), drules = draw_prim, which = 7) grid.text("Primitive Tree (n = 6)", 0.5, 0.75) # A more realistic botanical structure # Some call this a fractal tree, I think it is more like seaweed # Try drawing the last iteration (too slow for here, but looks great) fractal_tree_rules <- data.frame(inp = c("X", "F"), out = c("F-[[X]+X]+F[+FX]-X", "FF"), stringsAsFactors = FALSE) fractal_tree <- Lsys(init = "X", rules = fractal_tree_rules, n = 7) draw_ft <- data.frame(symbol = c("X", "F", "+", "-", "[", "]"), action = c("f", "F", "+", "-", "[", "]"), stringsAsFactors = FALSE) drawLsys(string = fractal_tree, stepSize = 2, ang = 25, st = c(50, 5, 90), drules = draw_ft, which = 5, gp = gpar(col = "chocolate4", fill = "honeydew")) grid.text("Fractal Seaweed (n = 4)", 0.25, 0.25)
This is the central function for rewriting an initial string of symbols (the axiom) into a new string using production rules. Production rules are very simple: if the symbol is A, turn it into something. If it is B, turn it into something else. Production rules typically contain instructions about moving while drawing, moving w/o drawing, changing direction, or storing the current state for re-use later.
Lsys(init = NULL, rules = NULL, n = 5, retAll = TRUE, verbose = 1L)
Lsys(init = NULL, rules = NULL, n = 5, retAll = TRUE, verbose = 1L)
init |
A character string giving variables (symbols) to use as the initial string Also known as the axiom. |
rules |
A data frame containing columns "inp" and "out". These contain the input
variables and the corresponding replacement string. See the examples in
|
n |
An integer giving the number of cycles or iterations desired. |
retAll |
Logical. If |
verbose |
An integer giving the level of information desired as the calculation
proceeds. |
The job of this function is to take an input "axiom" and apply the "production
rules" and other paramters to create a new string of drawing instructions. The
"language" or character set of the axiom and production rules are arbitary, and
the internet and literature contains many different examples. The same fractal
could be drawn using completely different sets of symbols. The string produced
by this function is processed by drawLsys
. See there for further
explanation and examples.
If retAll = FALSE
, a character vector of length 1 giving the string
at the end processing. Otherwise, a character vector of length n + 1
containing init
plus the results at the end of each iteration.
drawLsys
for examples, including plotting.