Extra Topic: More Fractals
Sierpinski Triangle + Koch Snowflake


Note: extra topics are not in CS Academy, but are required and can appear on any future homework, writing session, quiz, or exam.
Fractals
A fractal is a recursive graphic (that is, a graphic that appears the same at different levels as you zoom into it, so it appears to be made of smaller versions of itself). In theory you can zoom forever into a fractal, but here we will keep things simple and draw fractals only up to a specified level. Our base case will be when we reach that level.
  1. sierpinskiTriangle
    from cmu_graphics import * def onAppStart(app): app.level = 1 app.setMaxShapeCount(5000) def onKeyPress(app, key): if (key in ['up', 'right']) and (app.level < 7): app.level += 1 elif (key in ['down', 'left']) and (app.level > 0): app.level -= 1 def drawSierpinskiTriangle(app, level, x, y, size): # (x,y) is the lower-left corner of the triangle # size is the length of a side # Need a bit of trig to calculate the top point if level == 0: topY = y - (size**2 - (size/2)**2)**0.5 drawPolygon(x, y, x+size, y, x+size/2, topY) else: # Bottom-left triangle drawSierpinskiTriangle(app, level-1, x, y, size/2) # Bottom-right triangle drawSierpinskiTriangle(app, level-1, x+size/2, y, size/2) # Top triangle midY = y - ((size/2)**2 - (size/4)**2)**0.5 drawSierpinskiTriangle(app, level-1, x+size/4, midY, size/2) def redrawAll(app): margin = min(app.width, app.height)//10 x, y = margin, app.height-margin size = min(app.width, app.height) - 2*margin drawSierpinskiTriangle(app, app.level, x, y, size) drawLabel(f'Level {app.level} Fractal', app.width/2, 20, size=40, bold=True) drawLabel('Use arrows to change level', app.width/2, 60, size=20, bold=True) runApp(width=400, height=400)

    Result:


    Side-by-Side Levels:
    from cmu_graphics import * def onAppStart(app): app.level = 1 app.setMaxShapeCount(5000) def onKeyPress(app, key): if (key in ['up', 'right']) and (app.level < 6): app.level += 1 elif (key in ['down', 'left']) and (app.level > 0): app.level -= 1 def drawSierpinskiTriangle(app, level, x, y, size): # (x,y) is the lower-left corner of the triangle # size is the length of a side # Need a bit of trig to calculate the top point if level == 0: topY = y - (size**2 - (size/2)**2)**0.5 drawPolygon(x, y, x+size, y, x+size/2, topY) else: # Bottom-left triangle drawSierpinskiTriangle(app, level-1, x, y, size/2) # Bottom-right triangle drawSierpinskiTriangle(app, level-1, x+size/2, y, size/2) # Top triangle midY = y - ((size/2)**2 - (size/4)**2)**0.5 drawSierpinskiTriangle(app, level-1, x+size/4, midY, size/2) # Add circles around app.level (left side) to show how # level N is made up of 3 level N-1's: if (level == app.level): h = size * 3**0.5/2 cx, cy, r = x+size/2, y-h/3, size/3**0.5 drawOval(cx, cy, 2*r, 2*r, fill=None, border='pink') def drawLevel(app, level, cx): margin = min(app.width, app.height)//10 size = min(app.width, app.height) - 2*margin x, y = cx-size/2, app.height-margin drawSierpinskiTriangle(app, level, x, y, size) drawLabel(f'Level {level} Fractal', cx, 20, size=30, bold=True) drawLabel('Use arrows to change level', cx, 60, size=20, bold=True) def redrawAll(app): drawLevel(app, app.level, app.width/4) drawLevel(app, app.level+1, app.width*3/4) # draw the right arrow between the levels drawLabel(u'\u2192', app.width/2, app.height/2, size=50, bold=True) runApp(width=800, height=400)

  2. kochSnowflake
    # This example uses turtle graphics, not Tkinter import turtle def drawKochSide(length, level): if (level == 1): turtle.forward(length) else: drawKochSide(length/3, level-1) turtle.left(60) drawKochSide(length/3, level-1) turtle.right(120) drawKochSide(length/3, level-1) turtle.left(60) drawKochSide(length/3, level-1) def drawKochSnowflake(length, level): for step in range(3): drawKochSide(length, level) turtle.right(120) def drawKochExamples(): turtle.delay(1) turtle.speed(0) turtle.penup() turtle.goto(-300,100) turtle.pendown() turtle.pencolor('black') drawKochSide(300, 4) turtle.pencolor('blue') drawKochSnowflake(300, 4) turtle.penup() turtle.goto(-250,50) turtle.pendown() turtle.pencolor('red') drawKochSnowflake(200, 5) turtle.done() drawKochExamples()

    Result: