You are on page 1of 29

Computer Science 111

Fundamentals of Programming I
Advanced Turtle Graphics

Recursive Patterns in Art


The 20th century Dutch artist Piet Mondrian painted a
series of pictures that displayed abstract, rectangular
patterns of color
Start with a single colored rectangle
Subdivide the rectangle into two unequal parts (say, 1/3
and 2/3) and paint these in different colors
Repeat this process until an aesthetically appropriate
moment is reached

Level 1: A Single
Filled Rectangle

Level 2: Split at the Aesthetically


Appropriate Spot

Level 3: Continue the


Same Process with Each Part

Level 4

Level 5

Level 6

Level 7

Level 8

Level 9

Design a Recursive Function


The function expects a Turtle, the corner points
of a rectangle, and the current level as arguments
If the level is greater than 0
Draw a filled rectangle with the given corner points

Calculate the corner points of two new rectangles within the


current one and decrement the level by 1
Call the function recursively to draw these two rectangles

Program Structure
from turtle import Turtle
import random
def drawRectangle(t, x1, y1, x2, y2):
red = random.randint(0, 255)
green = random.randint(0, 255)
blue = random.randint(0, 255)
t.pencolor(red, green, blue)
# Code for drawing goes here
# Definition of the recursive mondrian function goes here

t = Turtle()
x = 50
y = 50
mondrian(t, -x, y, x, -y, 3)

The mondrian Function


def mondrian(t, x1, y1, x2, y2, level):
if level > 0:
drawRectangle(t, x1, y1, x2, y2)
vertical = random.randint(1, 2)
if vertical == 1:
# Vertical split
mondrian(t, x1, y1, (x2 - x1) // 3 + x1, y2,
level - 1)
mondrian(t, (x2 - x1) // 3 + x1, y1, x2, y2,
level - 1)

else:

# Horizontal split

mondrian(t, x1, y1, x2, (y2 - y1) // 3 + y1,


level - 1)
mondrian(t, x1, (y2 - y1) // 3 + y1, x2, y2,
level - 1)

Recursive Patterns in Nature


A fractal is a mathematical object that
exhibits the same pattern when it is
examined in greater detail
Many natural phenomena, such as
coastlines and mountain ranges, exhibit
fractal patterns

The C-curve
A C-curve is a fractal pattern
A level 0 C-curve is a vertical line segment
A level 1 C-curve is obtained by bisecting a level
0 C-curve and joining the sections at right angles
A level N C-curve is obtained by joining two
level N - 1 C-curves at right angles

Level 0 and Level 1


(50,50)

(50,50)

(0,0)

(50,-50)

(50,-50)

drawLine(50, -50, 50, 50)


drawLine(50, -50, 0, 0)
drawLine(0, 0, 50, 50)

Bisecting and Joining


(50,50)

(50,50)

(0,0)

(50,-50)

drawLine(50, -50, 50, 50)

(50,-50)

0 = (50 + 50 + -50 - 50) // 2


0 = (50 + -50 + 50 - 50) // 2
drawLine(50, -50, 0, 0)
drawLine(0, 0, 50, 50)

Generalizing
(50,50)

(50,50)

(0,0)

(50,-50)

drawLine(x1, y1, x2, y2)

(50,-50)

xm = (x1 + x2 + y1 ym = (x2 + y1 + y2 drawLine(x1, y1, xm,


drawLine(xm, ym, x2,

y2) // 2
x1) // 2
ym)
y2)

Recursing
(50,50)

(50,50)

(0,0)

(50,-50)

drawLine(x1, y1, x2, y2)

Base case

(50,-50)

xm = (x1 +
ym = (x2 +
cCurve(x1,
CCurve(xm,

x2 + y1
y1 + y2
y1, xm,
ym, x2,

Recursive step

- y2) // 2
- x1) // 2
ym)
y2)

The cCurve Function


def cCurve(t, x1, y1, x2, y2, level):
if level == 0:
drawLine(t, x1, y1, x2, y2)
else:
xm = (x1 + x2 + y1 - y2) // 2
ym = (x2 + y1 + y2 - x1) // 2
cCurve(t, x1, y1, xm, ym, level - 1)
cCurve(t, xm, ym, x2, y2, level - 1)

Note that recursive calls occur before any C-curve is drawn


when level > 0

Program Structure
from turtle import Turtle

def drawLine(t, x1, y1, x2, y2):


"""Draws a line segment between the endpoints."""
t.up()
t.goto(x1, y1)
t.down()
t.goto(x2, y2)
# Definition of the recursive cCurve function goes here
for level in range(0, 10):
t = Turtle()
cCurve(t, 50, -50, 50, 50, level)

Draws 10 C-curves of increasing levels of detail

Call Tree for ccurve(0)


A call tree diagram shows the number of calls of a
function for a given argument value
ccurve

ccurve(0) uses one call, the top-level one

Call Tree for ccurve(1)

ccurve

ccurve

ccurve

ccurve(1) uses three calls, a top-level one and two


recursive calls

Call Tree for ccurve(2)


ccurve(2) uses 7 calls, a top-level one and 6
recursive calls
ccurve

ccurve

ccurve

ccurve

ccurve

ccurve

ccurve

Call Tree for ccurve(n)


ccurve(n) uses 2n+1 - 1 calls, a top-level one and
2n+1 - 2 recursive calls
ccurve

ccurve

ccurve

ccurve

ccurve

ccurve

ccurve

Call Tree for ccurve(2)


The number of line segments drawn equals the
number of calls on the frontier of the tree (2n)
ccurve

ccurve

ccurve

ccurve

ccurve

ccurve

ccurve

Summary
A recursive algorithm passes the buck repeatedly to the
same function
Recursive algorithms are well-suited for solving problems
in domains that exhibit recursive patterns
Recursive strategies can be used to simplify complex
solutions to difficult problems

You might also like