Skip to content

Highly customizable tool for generating pngs and gifs of fractals and other patterns created by Lindenmayer systems.

License

Notifications You must be signed in to change notification settings

discretegames/TurtLSystems

Repository files navigation

Python version support

Intro | Installation | Usage | L-System Instructions | Examples | Links

TurtLSystems is a Python 3 package for drawing L-systems via turtle graphics with easy ways to output png images and gif animations of the patterns generated. L-systems or Lindenmayer systems are a simple string rewriting systems where every character in an initial start string is repeatedly overwritten with a predetermined replacement. This can lead to very elaborate patterns that create fractals or mimic nature.

Sierpinski arrowhead curve example gif

See more examples below.

Quick Start

Do pip install TurtLSystems then run the following Python to draw a Sierpinski triangle:

from TurtLSystems import *
draw()
wait()

Installation (supports Python 3.6+)

Make sure you have Python installed then run this command in a terminal:

pip install TurtLSystems

If that doesn't work try one of the following lines:

pip3 install TurtLSystems
python -m pip install TurtLSystems
python3 -m pip install TurtLSystems
py -m pip install TurtLSystems

For png and gif output the Ghostscript conversion tool is required. It can be downloaded here. Ghostscript is what takes the .eps files generated by turtle graphics and turns them into pngs which are then made into gifs.

The Python imaging library Pillow (PIL) is also required for png and gif output but it will be installed automatically when you install TurtLSystems.

TurtLSystems on PyPI | TurtLSystems on GitHub | Ghostscript Download

Usage

TurtLSystems has only four functions, init, draw, wait, and lsystem, and only the draw function is strictly necessary.

The code that generated the blue gif of the Sierpinski arrowhead curve above is simply:

from TurtLSystems import *
draw('A', 'A B-A-B B A+B+A,', 5, 60, 7, 2, (200, 220, 255), None, (36, 8, 107),
     heading=60, red_increment=2, gif='example.gif', max_frames=250, duration=30)

A typical program might look like:

from TurtLSystems import init, draw, wait
init(...)  # fill in args
draw(...)  # fill in args
wait()

To ignore the errors that get thrown when exiting the window while the turtle is drawing use try/except with Exit:

from TurtLSystems import init, draw, wait, Exit
try:
    init(...)  # fill in args
    draw(...)  # fill in args
    wait()
except Exit:
    pass

init Function

Initializes global TurtLSystems properties. Calling this is optional and only needed when customization is desired. If used it should only be called once and placed before all calls to draw and wait.

Returns nothing.

Arguments

Name
Default
Description
Type
window_size
(0.75, 0.75)
The size of the window. Use integers for pixel dimensions. Use floats for a percentage of the screen size.
Tuple[int | float, int | float]
window_title
"TurtLSystems"
The title of the window.
str
background_color
(0, 0, 0)
The background color of the window. A 0-255 rgb tuple. May be changed later by draw calls.
Tuple[int, int, int]
background_image
None
The file path to a background image for the window.
str | None
window_position
None
The top and left screen coordinates of the window, or None for centered.
Tuple[int | None, int | None] | None
canvas_size
None
The size of the drawing canvas when an area larger than the window size is desired.
Tuple[int | None, int | None] | None
ghostscript
None
The path to or command name of ghostscript. When None, an educated guess of the path is made on Windows and 'gs' is used on Mac/Linux. Ghostscript is the image conversion tool required for png and gif output.
str | None
logo_mode
False
Whether the turtle graphics coordinates mode is 'standard' or 'logo'. Defaults to standard. In standard mode an angle of 0 points rightward and positive angles go counterclockwise. In logo mode an angle of 0 points upward and positive angles go clockwise.
bool
delay
None
The turtle graphics animation delay in milliseconds. None for default value.
int | None
silent
False
Whether to silence all messages and warnings produced by TurtLSystems.
bool

If you have issues where png or gif output is cut off and doesn't match what is shown in the window, try increasing the canvas size to much larger than needed like init(canvas_size(2000, 2000)). I experienced this issue in Linux Mint and am not sure why it happened.

draw Function

Opens a turtle graphics window and draws an L-system pattern based on the arguments provided. When called multiple times all patterns are drawn to the same canvas.

All 54 arguments are optional but start and rules are the most important because they define the L-system, and level defines how many expansion steps take place. On an expansion step, every character in start is replaced with what it maps to in rules (or left unchanged if not present) resulting in a new start string. The characters of start after the last expansion are the instructions the turtle follows to draw a pattern. See the lsystem function documentation for specifics on what each character does as an instruction.

Call draw() by itself to see an example Sierpinski triangle pattern.

In the descriptions below, "on X" is short for "when the character X is encountered in the L-system string".

Returns a 2-tuple of the final L-system string and the turtle graphics Turtle object used to draw the pattern (Tuple[str, turtle.Turtle]).

Positional Arguments

Name
Default
Description
Type
start
'F+G+G'
The initial string or axiom of the L-system. Level 0.
str
rules
'F F+G-F-G+F G GG'
Dictionary that maps characters to what they are replaced with in the L-system expansion step. May also be a string where whitespace separated pairs of substrings correspond to the character and its replacement. For example {'A': 'AB', 'B': 'B+A'} and 'A AB B B+A' represent the same rules.
Dict[str, str] | str
level
4
The number of L-system expansion steps to take, i.e. how many times to apply rules to start.
int
angle
120
The angle to turn by on + or -. In degrees by default but the circle arg can change that.
float
length
20
The distance in pixels to move forward by on letters. The length step.
float
thickness
1
The line width in pixels. May be any non-negative number.
float
color
(255, 255, 255)
The line color. A 0-255 rgb tuple or None to hide all lines. Reselected on 0.
Tuple[int, int, int] | None
fill_color
(128, 128, 128)
The fill color for {} polygons, @ dots, and turtle shapes. A 0-255 rgb tuple or None to hide all fills. Reselected on 1.
Tuple[int, int, int] | None
background_color
None
The background color of the window. A 0-255 rgb tuple or None to leave unchanged.
Tuple[int, int, int] | None
asap
False
When True the draw will happen as fast as possible, ignoring speed arg and the delay arg of init.
bool

Customization Arguments

Name
Default
Description
Type
colors
None
When an iterable such as a list, color and fill_color are ignored and the first 10 colors of the list become the colors that are selected on 0 through 9. Each may be a 0-255 rgb tuple or None for no color. The list of defaults below is used to fill out anything missing if less than 10 colors are given. When colors is None, color and fill_color are used replace slots 0 and 1 respectively.
Iterable[Tuple[int, int, int] | None] | None
position
(0, 0)
The initial (x, y) position of the turtle.
Tuple[float, float]
heading
0
The initial angle the turtle points in.
float
scale
1'
A factor to scale the size of the pattern by. May be negative. Specifically, length, position, and length_increment are multiplied by scale and thickness and thickness_increment are multiplied by abs(scale).
float
prefix
''
An L-system string that does not undergo expansion prepended to the fully expanded start string.
str
suffix
''
An L-system string that does not undergo expansion appended to the fully expanded start string
str
max_chars
None
The maximum number of characters in the final L-system string (prefix + expanded start + suffix) to follow the instructions for, or None for no limit.
int | None
max_draws
None
The maximum number of "draw" operations to do or None for no limit. A "draw" operation is something that draws to the canvas, namely lines from uppercase letters, dots from @, and finished polygons from }.
int | None

Default Colors:

  • 0 0 = (255, 255, 255) white
  • 1 1 = (128, 128, 128) gray
  • 2 2 = (255, 0, 0) red
  • 3 3 = (255, 128, 0) orange
  • 4 4 = (255, 255, 0) yellow
  • 5 5 = (0, 255, 0) green
  • 6 6 = (0, 255, 255) cyan
  • 7 7 = (0, 0, 255) blue
  • 8 8 = (128, 0, 255) purple
  • 9 9 = (255, 0, 255) magenta

Turtle Arguments

Name
Default
Description
Type
speed
'fastest'
The speed of the turtle. An integer from 1 to 10 for slowest to fastest or 0 for the fastest possible. Strings 'slowest', 'slow', 'normal', 'fast', and 'fastest' correspond to 1, 3, 6, 10, and 0 respectively.
int | str
show_turtle
False
Whether the turtle is shown or not.
bool
turtle_shape
'classic'
The shape of the turtle. Can be 'classic', 'arrow', 'turtle', 'circle', 'square', or 'triangle'.
str
circle
360
The number of degrees to consider a full circle as having. Use 2*math.pi to work in radians.
float

Increment Arguments

Name
Default
Description
Type
angle_increment
15
The amount to increment or decrement angle by on ) or (.
float
length_increment
5
The amount to increment or decrement length by on ^ or %.
float
length_scalar
2
The amount to multiply or divide length by on * or /.
float
thickness_increment
1
The amount to increment or decrement the thickness by on > or <. Thickness won't go below 0.
float
red_increment
1
The amount to increment or decrement the red channel of the line or fill color by on , or .. Channel will stay in the range [0, 255]. This can be a float to allow for gradual changes.
float
green_increment
1
The amount to increment or decrement the green channel of the line or fill color by on ; or :. Channel will stay in the range [0, 255]. This can be a float to allow for gradual changes.
float
blue_increment
1
The amount to increment or decrement the blue channel of the line or fill color by on ? or !. Channel will stay in the range [0, 255]. This can be a float to allow for gradual changes.
float

Text Arguments

Name
Default
Description
Type
text
None
A string of text to add to the canvas. Patters are drawn on top of it. None for no text.
str | None
text_color
(255, 255, 255)
The color of the text. A 0-255 rgb tuple or None to hide the text.
Tuple[int, int, int] | None
text_position
(0, -200)
The (x, y) position of the text.
Tuple[int, int]
text_align
'center'
The alignment of the text. Either 'left', 'center', or 'right'.
str
font
'Arial
The font name of the text.
str
font_size
16
The font size of the text. Measured in points if positive or in pixels if negative.
int
font_style
'normal'
The styling to apply to the font of the text. 'normal', 'bold', 'italic', 'underline' and 'overstrike' are all possibilities and can be combined like 'bold italic'.
str

Png and Gif Frame Arguments

Name
Default
Description
Type
png
None
The file path of where to save the final drawing as a png image, or None for no png output. A file extension is not required.
str | None
padding
10
The amount of padding in pixels to frame the drawing with on all sides in png and gif output. Negative values are valid. When None, no padding happens and the entire canvas area is saved. Note that padding very large blank areas can be slow.
int | None
transparent
False
When True, the background of png and gif output is transparent rather that the window background color.
bool
antialiasing
4
An integer 1, 2, or 4 that specifies how jagged pixel edges will be in png and gif output. 1 for the most jagged, 4 for the least jagged. Note that the window canvas does not respect this option.
int
output_scale
1
A factor to scale png and gif dimensions by. Vector graphics are used so there is no quality loss from scaling up, though padding may take longer.
float

Gif Arguments

Name
Default
Description
Type
gif
None
The file path of where to save the drawing as a gif animation, or None for no gif output. A file extension is not required.
str | None
frame_every
1
When an integer, this is the number of "draw" operations to wait for between recording of gif frames. A "draw" operation is something that draws to the canvas, namely lines from uppercase letters, dots from @, and finished polygons from }. When a collection such as a string, frames are recorded whenever L-system characters in the collections are encountered.
int | Collection[str]
max_frames
100
The maximum number of frames of the gif or None for no limit. Useful to prevent accidental creation of very long gifs.
int | None
duration
20
The duration in milliseconds of each gif frame. Should be 20 or above and divisible by 10.
int
pause
500
The amount of additional time in milliseconds to pause on the last frame of the gif.
int
defer
0
The amount of additional time in milliseconds to add to the first frame of the gif.
int
loops
None
The number of times the gif loops or 0 or None for no limit.
int | None
reverse
False
Whether to reverse the frames of the gif.
bool
alternate
False
When True, the central gif frames are copied and appended in reverse to the end of the gif, making it cycle forwards and backwards. For example, a sequence 01234 would become 01234321.
bool
growth
False
When True, the gif consist of frames made from the final patterns of every expansion of the start string, from level 0 to level inclusive. frame_every and max_frames are ignored in this mode.
bool

Advanced Arguments

Name
Default
Description
Type
tmpdir
None
The path to a directory to put all .eps and .png files in during the generation of png and gif output. Useful if you need the gif frames as pngs. When None these files are put in a temporary place and deleted.
str | None
callback
None
When not None, a function that is called for every character in the L-system string the turtle encounters. Two arguments are given, the current character and the Turtle object. If True is returned the turtle stops.
Callable[[str, turtle.Turtle], bool | None] | None
skip_init
False
Whether to skip calling init when it hasn't been called already.
bool

wait Function

Keeps window open. Calling this is optional. If used it should only be called once and be placed after all calls to draw.

Returns nothing.

Name
Default
Description
Type
exit_on_click
True
Whether the window can be closed by clicking anywhere.
bool
skip_init
False
For advanced use. Whether to skip calling init when it hasn't been called already.
bool

lsystem Function

Expands the L-system string start according to rules level number of times, returning the resulting string.

The draw function calls this internally. You do you not need to call it unless you want to.

The types and descriptions of start, rules, and level in this function match exactly what they are in the draw function.

L-System Instructions

Every non-whitespace printable ASCII character in an L-system string is an instruction as follows:

A-Z     Move forward by length step, drawing a line.
a-z     Move forward by length step, not drawing a line.
+       Turn positively by turning angle.
-       Turn negatively by turning angle.
|       Make a half turn (turn by 180°).
&       Swap meaning of + and -.
`       Swap meaning of uppercase and lowercase.
@       Draw a fill color dot with radius max(2*thickness, 4+thickness).
{       Start a polygon.
}       Finish a polygon, filling it with fill color.
[       Push current turtle state onto the stack (position, heading, colors, etc).
]       Pop current turtle state off the stack, if not empty.
$       Clear stack.
)       Increment turning angle by angle_increment.
(       Decrement turning angle by angle_increment.
~       Reset turning angle back to its initial value.
*       Multiply length step by length_scalar.
/       Divide length step by length_scalar.
^       Increment length step by length_increment.
%       Decrement length step by length_increment.
_       Reset length step back to its initial value.
>       Increment line thickness by thickness_increment.
<       Decrement line thickness by thickness_increment. Won't go below 0.
=       Reset line thickness back to its initial value.
'       Reset heading back to its initial value.
"       Reset position back to its initial value.
0-9     Change color to the color at this index of colors list.
,       Increment current color's 0-255 red channel by red_increment.
.       Decrement current color's 0-255 red channel by red_increment.
;       Increment current color's 0-255 green channel by green_increment.
;       Decrement current color's 0-255 green channel by green_increment.
?       Increment  current color's 0-255 blue channel by blue_increment.
!       Decrement  current color's 0-255 blue channel by blue_increment.
#       The next 0123456789.,:;!? apply to fill color rather than line color.
\       Stop executing all instructions immediately.

Any characters not mentioned are ignored and have no effect. Many of the instructions are based on Paul Bourke's 1991 L-System User Notes.

Examples

The draw(...) line of code in each example should be used as the middle line here:

from TurtLSystems import draw, wait
draw(...)
wait()

Sierpinski Triangle

draw('F+G+G', 'F F+G-F-G+F G GG', 5, 120, 10, color=(255, 255, 0), asap=True, png='sierpinski')

Sierpinski triangle example

Sierpinski Arrowhead Curve

draw('A', 'A B-A-B B A+B+A', 5, 60, 10, color=(255, 0, 0), asap=True, heading=60, png='arrowhead')

Sierpinski arrowhead curve example

Koch Snowflake

draw('F--F--F', 'F F+F--F+F', 5, 60, 1.5, color=(0, 128, 255), asap=True, heading=60, png='koch')

Koch snowflake example

Koch Anti-Snowflake

draw('F++F++F', 'F F+F--F+F', 5, 60, 1.5, color=(0, 0, 255), asap=True, png='antikoch')

Koch anti-snowflake example

Square Koch Curve

draw('F', 'F F+F-F-F+F', 5, 90, 3, color=(0, 255, 255), asap=True, png='squarekoch')

Square Koch curve example

Dragon Curve

draw('F', 'F F+G G F-G', 12, 90, 5, color=(255, 0, 255), asap=True, png='dragon')

Dragon curve example

Fractal Tree

draw('A', 'A B[-A]+A B BB', 7, 45, 3, color=(255, 128, 0), asap=True, heading=90, png='tree')

Fractal tree example

Fractal Plant

draw('X', 'X F+[[X]-X]-F[-FX]+X F FF', 5, 20, 5, color=(0, 255, 0), asap=True, heading=88, png='plant')

Fractal plant example


Generalized versions of all the examples above and more are available in examples.py which can be imported and run with:

from TurtLSystems.examples import *
sierpinski_triangle()
# sierpinski_arrowhead()
# square_koch_curve()
# koch_snowflake()
# koch_snowflake(anti=True)
# dragon_curve()
# cantor_set()
# tree()
# plant()
# gradient()

Simply uncomment the desired examples and run the file. The exact examples present in this readme can be found all in one place here.

Links

TurtLSystems PyPI Package Page

TurtLSystems GitHub Repo

TurtLSystems License

L-Systems Wikipedia

Ghostscript

Pillow