A module for creating fractal art in Python's turtle module.

## Project description

# fractalartmaker

A module for creating fractal art in Python's `turtle`

module.

This module is explored in the book "The Recursive Book of Recursion" by Al Sweigart from No Starch Press.

You can purchase this book directly from the publisher at https://nostarch.com/recursive-book-recursion or read it online at https://inventwithpython.com/recursion/

# Quickstart

To view some example fractals, run the following from the interactive shell:

```
>>> import fractalartmaker
>>> fractalartmaker.fast() # draw the fractals quickly
>>> fractalartmaker.example(1) # pass 1 to 9
```

# Making Fractals

The Fractal Art Maker's algorithm has two major components: a shape-drawing function and the recursive `drawFractal()`

function.

The shape-drawing function draws a basic shape. The Fractal Art Maker program comes with the two shape-drawing functions, `fractalartmaker.drawFilledSquare()`

and `fractalartmaker.drawTriangleOutline()`

, but you can also create your own. We pass a shape-drawing function to the `fractalartmaker.drawFractal()`

function as an argument.

The `fractalartmaker.drawFractal()`

function also has a parameter indicating changes to the size, position, and angle of the shapes between recursive calls to `fractalartmaker.drawFractal()`

.

The `fractalartmaker.drawFractal()`

function uses a shape-drawing function passed to it to draw the individual parts of the fractal. This is usually a simple shape, such as a square or triangle. The beautiful complexity of the fractals emerges from `fractalartmaker.drawFractal()`

recursively calling this function for each individual component of the whole fractal.

Here's the two shape-drawing functions that come in the `fractalartmaker`

module:

```
def drawFilledSquare(size, depth):
size = int(size)
# Move to the top-right corner before drawing:
turtle.penup()
turtle.forward(size // 2)
turtle.left(90)
turtle.forward(size // 2)
turtle.left(180)
turtle.pendown()
# Alternate between white and gray (with black border):
if depth % 2 == 0:
turtle.pencolor('black')
turtle.fillcolor('white')
else:
turtle.pencolor('black')
turtle.fillcolor('gray')
# Draw a square:
turtle.begin_fill()
for i in range(4): # Draw four lines.
turtle.forward(size)
turtle.right(90)
turtle.end_fill()
def drawTriangleOutline(size, depth):
size = int(size)
# Move the turtle to the top of the equilateral triangle:
height = size * math.sqrt(3) / 2
turtle.penup()
turtle.left(90) # Turn to face upwards.
turtle.forward(height * (2/3)) # Move to the top corner.
turtle.right(150) # Turn to face the bottom-right corner.
turtle.pendown()
# Draw the three sides of the triangle:
for i in range(3):
turtle.forward(size)
turtle.right(120)
```

The shape-drawing functions for the Fractal Art Maker have two parameters: `size`

and `depth`

. The size parameter is the length of the sides of the square or triangle it draws. The shape-drawing functions should always use arguments to `turtle.forward()`

that are based on `size`

so that the lengths will be proportionate to size at each level of recursion. Avoid code like `turtle.forward(100)`

or `turtle.forward(200)`

; instead, use code that is based on the `size`

parameter, like `turtle.forward(size)`

or `turtle.forward(size * 2)`

. In Python's `turtle`

module, `turtle.forward(1)`

moves the turtle by one unit, which is not necessarily the same as one pixel.

The shape-drawing functions' second parameter is the recursive depth of `fractalartmaker.drawFractal()`

. Your shape-drawing function can ignore this argument, but using it can cause interesting variations to the basic shape. For example, the `fractalartmaker.drawFilledSquare()`

shape-drawing function uses depth to alternate between drawing white squares and gray squares. Keep this in mind if you'd like to create your own shape-drawing functions for the Fractal Art Maker program, as they must accept a `size`

and `depth`

argument.

The `fractalartmaker.drawFractal()`

function has three required parameters and one optional one: `shapeDrawFunction`

, `size`

, `specs`

, and optionally `maxDepth`

. The `shapeDrawFunction`

parameter expects a function, like `fractalartmaker.drawFilledSquare`

or `fractalartmaker.drawTriangleOutline`

. The `size`

parameter expects the starting size passed to the drawing function. Often, a value between `100`

and `500`

is a good starting size, though this depends on the code in your shape-drawing function, and finding the right value may require experimentation.

The `specs`

parameter expects a list of dictionaries that specify how the recursive shapes should change their size, position, and angle as `drawFractal()`

recursively calls itself. These specifications are described later in this section. To prevent `drawFractal()`

from recursing until it causes a stack overflow, the `maxDepth`

parameter holds the number of times `drawFractal()`

should recursively call itself. By default, `maxDepth`

has a value of `8`

, but you can provide a different value if you want more recursive shapes or fewer.

The recursive calls to `drawFractal()`

are based on the specification in the `specs`

list’s dictionaries. For each dictionary, `drawFractal()`

makes one recursive call to `drawFractal()`

. If specs is a list with one dictionary, every call to `drawFractal()`

results in only one recursive call to `drawFractal()`

. If specs is a list with three dictionaries, every call to `drawFractal()`

results in three recursive calls to `drawFractal()`

.

The dictionaries in the specs parameter provide specifications for each recursive call. Each of these dictionaries has the keys `sizeChange`

, `xChange`

, `yChange`

, and `angleChange`

. These dictate how the size of the fractal, the position of the turtle, and the heading of the turtle change for a recursive `drawFractal()`

call.

`sizeChange`

(default is`1.0`

) - The next recursive shape’s size value is the current size multiplied by this value.`xChange`

(default is`0.0`

) - The next recursive shape’s x-coordinate is the current x-coordinate plus the current size multiplied by this value.`yChange`

(default is`0.0`

) - The next recursive shape’s y-coordinate is the current y-coordinate plus the current size multiplied by this value.`angleChange`

(default is`0.0`

) - The next recursive shape’s starting angle is the current starting angle plus this value.

Let’s take a look at the specification dictionary for the Four Corners fractal, which is drawn when you call `fractalartmaker.example(1)`

. The call to `drawFractal()`

for the Four Corners fractal passes the following list of dictionaries for the `specs`

parameter:

```
fractalartmaker.drawFractal(fractalartmaker.drawFilledSquare, 350,
[{'sizeChange': 0.5, 'xChange': -0.5, 'yChange': 0.5},
{'sizeChange': 0.5, 'xChange': 0.5, 'yChange': 0.5},
{'sizeChange': 0.5, 'xChange': -0.5, 'yChange': -0.5},
{'sizeChange': 0.5, 'xChange': 0.5, 'yChange': -0.5}], 5)
```

The `specs`

list has four dictionaries, so each call to `drawFractal()`

that draws a square will, in turn, recursively call `drawFractal()`

four more times to draw four more squares.

To determine the size of the next square to be drawn, the value for the `sizeChange`

key is multiplied by the current size parameter. The first dictionary in the specs list has a `sizeChange`

value of `0.5`

, which makes the next recursive call have a size argument of `350 * 0.5`

, or `175`

units. This makes the next square half the size of the previous square. A `sizeChange`

value of `2.0`

would, for example, double the size of the next square. If the dictionary has no `sizeChange`

key, the value defaults to `1.0`

for no change to the size.

If you look at the three other dictionaries in the `specs`

list, you’ll notice they all have a `sizeChange`

value of `0.5`

. The difference between them is that their `xChange`

and `yChange`

values place them in the other three corners of the current square. As a result, the next four squares are drawn centered on the four corners of the current square.

The dictionaries in the `specs`

list for this example don’t have an `angleChange`

value, so this value defaults to `0.0`

degrees. A positive `angleChange`

value indicates a counterclockwise rotation, while a negative value indicates a clockwise rotation.

Take a look at the code in the module's `example()`

function for more examples.

The `fractalartmaker`

module also has a `fractalartmaker.fast()`

function you can call to make the fractals draw quickly, and a `fractalartmaker.clear()`

to clear the turtle drawing window.

## Project details

## Release history Release notifications | RSS feed

## Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.