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 is1.0
) - The next recursive shape’s size value is the current size multiplied by this value.xChange
(default is0.0
) - The next recursive shape’s x-coordinate is the current x-coordinate plus the current size multiplied by this value.yChange
(default is0.0
) - The next recursive shape’s y-coordinate is the current y-coordinate plus the current size multiplied by this value.angleChange
(default is0.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.
Source Distribution
File details
Details for the file FractalArtMaker-0.1.0.tar.gz
.
File metadata
- Download URL: FractalArtMaker-0.1.0.tar.gz
- Upload date:
- Size: 6.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.7.1 importlib_metadata/4.8.2 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | fb390e7838ad34fb6ba521038ab9e668a39874ae16a7ec6971184b848bfa79bc |
|
MD5 | 0aca045f52bf1a5778250867b0ca6711 |
|
BLAKE2b-256 | fd9b481b43861e0c668130dbf96026684edd1a54d709885ce4dedc990a7b15f1 |