A few weeks ago I wrote a little script (code below the fold) to generate the frames of the following animation. It’s an animation of different iterations of Sierpinski’s Carpet.
To generate the carpet, take a square. Divide it into nine squares (3×3) and remove the center one. Then, for each of the remaining 8 squares, repeat ad infinitum.
If you get bored doing it an infinite number of times, take a break and eat Sierpinski’s Cookie.
The Code – SierpinskisCarpenter.py
Sorry for the crappy box this is in. Copy and paste for reading.
-
-
#!/usr/bin/python
-
-
#
-
# SierpinskisCarpenter.py
-
#
-
# Author: Dibson T Hoffweiler <dibson@hoffweiler.com>
-
# WWW: http://www.dibson.net/
-
#
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-
# Version 2, December 2004
-
#
-
# Everyone is permitted to copy and distribute verbatim or modified
-
# copies of this license document, and changing it is allowed as long
-
# as the name is changed.
-
#
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
#
-
# 0. You just DO WHAT THE FUCK YOU WANT TO.
-
#
-
-
import Image
-
-
class SierpinskisCarpenter:
-
-
def __init__(self):
-
""" Prepare the Carpenter """
-
self.color = (0, 0, 255)
-
-
def getCounter(self):
-
""" Return current counter value, increment it. """
-
c = self.counter
-
self.counter += 1
-
return c
-
-
def getFrameFilename(self):
-
""" Return filename for next frame. """
-
return "carpet-frame-%02d-%06d.gif" % (self.itr_start, self.getCounter())
-
-
def getCarpetImage(self, itr, size, init=True):
-
""" Return an image object of Sierpinski’s Carpet
-
-
itr – int – how many iterations deep to go
-
size – int – width of carpet in pixels
-
init – bool – if True, clear counters – must set False when recursing! (default True)
-
"""
-
-
if (init):
-
# Prepare to lay the carpet out
-
self.counter = 0
-
-
if (0 == itr):
-
# No need to iterate, return the part
-
part = Image.new("RGB", (size, size), self.color)
-
return part
-
else:
-
# Get smaller carpet, and paste it in 8 times
-
-
third = size / 3
-
-
partSmall = self.getCarpetImage(itr – 1, third, False)
-
-
im = Image.new("RGB", (size, size), (255, 255, 255))
-
-
# top left
-
tl_start = (0, 0)
-
im.paste(partSmall, tl_start)
-
-
# top center
-
tc_start = (third, 0)
-
im.paste(partSmall, tc_start)
-
-
# top right
-
tr_start = (2 * third, 0)
-
im.paste(partSmall, tr_start)
-
-
# middle right
-
mr_start = (2 * third, third)
-
im.paste(partSmall, mr_start)
-
-
# bottom right
-
br_start = (2 * third, 2 * third)
-
im.paste(partSmall, br_start)
-
-
# bottom center
-
bc_start = (third, 2 * third)
-
im.paste(partSmall, bc_start)
-
-
# bottom left
-
bl_start = (0, 2 * third)
-
im.paste(partSmall, bl_start)
-
-
# middle left
-
ml_start = (0, third)
-
im.paste(partSmall, ml_start)
-
-
return im
-
-
def animateCarpet(self, itr, size, start=None):
-
""" A recursive function to generate an animation of drawing Sierpinski’s Carpet.
-
-
- itr – int – how many iterations to do
-
- size – int – image size will be a square with lengths this many pixels
-
- start – 2dim tuple – top left corner of carpet to draw
-
-
Example:
-
-
sc = SierpinskisCarpenter()
-
itr = 3
-
size = (3 ** itr, 3 ** itr)
-
im = sc.animateCarpet(itr, size)
-
im.show()
-
-
"""
-
-
if (None == start):
-
# Init the animation
-
start = (0,0)
-
self.counter = 0
-
self.im = Image.new("RGB", (size, size), (255, 255, 255))
-
self.itr_start = itr
-
self.im.save(self.getFrameFilename())
-
-
# tab for clean debug output
-
tab = "\t" * itr
-
-
#print tab + "MAKE CARPET ITR %s" % (itr)
-
#print "%sStart %s" % (tab, start)
-
-
if (0 == itr):
-
# LAST ITERATION – PAINT IT!
-
#print "%sPAINTING: Start %s" % (tab, start)
-
self.im.paste(self.color, (start[0], start[1], start[0] + size, start[1] + size))
-
self.im.save(self.getFrameFilename())
-
else:
-
# NEED TO ITERATE, DO ALL 8 SQUARES
-
-
third = size / 3
-
-
# top left
-
tl_start = (start[0], start[1])
-
self.im = self.animateCarpet(itr-1, size/3, tl_start)
-
-
# top center
-
tc_start = (start[0] + third, start[1])
-
self.im = self.animateCarpet(itr-1, size/3, tc_start)
-
-
# top right
-
tr_start = (start[0] + 2 * third, start[1])
-
self.im = self.animateCarpet(itr-1, size/3, tr_start)
-
-
# middle right
-
mr_start = (start[0] + 2 * third, start[1] + third)
-
self.im = self.animateCarpet(itr-1, size/3, mr_start)
-
-
# bottom right
-
br_start = (start[0] + 2 * third, start[1] + 2 * third)
-
self.im = self.animateCarpet(itr-1, size/3, br_start)
-
-
# bottom center
-
bc_start = (start[0] + third, start[1] + 2 * third)
-
self.im = self.animateCarpet(itr-1, size/3, bc_start)
-
-
# bottom left
-
bl_start = (start[0], start[1] + 2 * third)
-
self.im = self.animateCarpet(itr-1, size/3, bl_start)
-
-
# middle left
-
ml_start = (start[0], start[1] + third)
-
self.im = self.animateCarpet(itr-1, size/3, ml_start)
-
-
return self.im
-
-
cm = SierpinskisCarpenter()
-
-
# EXAMPLE: saves 6 iterations of Sierpinski’s Carpet
-
#topItr = 6
-
#size = 3 ** topItr
-
#for itr in range(topItr+1):
-
# im = cm.getCarpetImage(itr, size)
-
# im.save("carpet-%spx-%s.gif" % (size, itr))
-
-
# EXAMPLE: dumps out frames for drawing out carpet
-
#cm.animateCarpet(3, 27)
-
-
