Metadata-Version: 2.1
Name: FractalArtMaker
Version: 0.1.0
Summary: A module for creating fractal art in Python's turtle module.
Home-page: https://github.com/asweigart/fractalartmaker
Author: Al Sweigart
Author-email: al@inventwithpython.com
License: MIT
Platform: UNKNOWN
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt

# 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.



