Sierpinski Triangle Fractal (Python)

vegaseat 1 Tallied Votes 1K Views Share

Another famous fractal called the Sierpinski Triangle named after Polish mathematician Waclaw Sierpinski. He seemed to have played around with it the most. To state it simple, you start with an equilateral triangle and then form smaller triangles by connecting the midpoints of each of the sides. Some folks shade alternate triangles to pretty up the pattern. We are using the canvas of the Python Image Library (PIL) to draw the triangle and save the final image to a file.

# draw a Sierpinski Triangle (fractal) to a given depth using PIL
# Python Imaging Library from: http://www.pythonware.com/products/pil/
# tested with Python24  by     vegaseat      17sep2006

import Image       # PIL
import ImageDraw   # PIL
import webbrowser  # to show final image

def sierpinski(data, steps, update_image, k):
    '''
    calculates points for sub triangles, uses recursion for steps
    '''
    # draw triangles each step through
    update_image.line((data[0], data[1]))
    update_image.line((data[1], data[2]))
    update_image.line((data[0], data[2]))
    
    # next triangle formed by connecting the midpoints of each of the sides
    x1 = (data[0][0] + data[1][0]) / 2
    y1 = (data[0][1] + data[1][1]) / 2
    
    x2 = (data[1][0] + data[2][0]) / 2
    y2 = (data[1][1] + data[2][1]) / 2
    
    x3 = (data[2][0] + data[0][0]) / 2
    y3 = (data[2][1] + data[0][1]) / 2
    
    # updates data in next recursion
    data2 = ((x1, y1), (x2, y2), (x3, y3))
    
    # loop through until step limit is reached
    k += 1
    if k <= steps:
        # the functions calls itself (recursion)
        sierpinski((data[0], data2[0], data2[2]), steps, update_image, k)
        sierpinski((data[1], data2[0], data2[1]), steps, update_image, k)
        sierpinski((data[2], data2[1], data2[2]), steps, update_image, k)

def draw(image):
    """draws picture/image"""
    return ImageDraw.Draw(image)

# higher steps gives more detail
# test with values of 1 to 10
steps = 6

# the three x,y data points for the starting equilateral triangle
data = ((0, 500), (500, 500), (250, 0))

# picture canvas creation uses size tuple given in data[1]
size = data[1]
picture = Image.new('1', size, color="white")
update_image = draw(picture)

# draw the triangle and calculate next triangle corner coordinates
sierpinski(data, steps, update_image, 0)

# save the final image file and then view with an image viewer
imagename = "sierpinski.png"
picture.save(imagename)

# this uses the default image viewer assigned to your webbrowser
webbrowser.open(imagename)