""" leaf.py an example for the Intro Programming course concepts: * recursion * objects * lists of objects within objects * dictionary (in child_color method) * default values * a bit of trig (x,y from length,angle using cos() and sin()) * mod arithmetic (wrapping color values around at 255) * uses Zelle's graphics library * a global variable (window) Jim M | Nov 25 2013 | MIT License """ from graphics import * from math import sin, cos, pi window = GraphWin("leaf.py", 600, 600) window.setCoords(0.0, 0.0, 1.0, 1.0) class Leaf(object): def __init__(self, depth=0, max_depth=5, # recursion management x=0.1, y=0.1, length=0.3, # in window coord units angle=pi/30, # from horizontal red=100, green=50, blue=25, # 0 to 255 = black to white width=25, # in pixels red_delta=20, # child modifications : green_delta=40, # | blue_delta=10, # | angle_delta=pi/15.0, # | length_shrink=0.7, # | width_shrink=0.7 # | ): self.depth = depth self.max_depth = max_depth self.red = red self.green = green self.blue = blue self.width = width self.angle = angle self.length = length self.angle_delta = angle_delta self.red_delta = red_delta self.green_delta = green_delta self.blue_delta = blue_delta self.length_shrink = length_shrink self.width_shrink = width_shrink self.x1 = x # left end self.y1 = y self.x2 = x + length * cos(angle) # right end self.y2 = y + length * sin(angle) self.line = Line(Point(self.x1, self.y1), Point(self.x2, self.y2)) self.line.setOutline(color_rgb(red, green, blue)) self.line.setWidth(width) def child_width(self): if self.width <= 1: return 1 else: return self.width * self.width_shrink def child_color(self): return {'red': (self.red + self.red_delta) % 255, 'green': (self.green + self.green_delta) % 255, 'blue' : (self.blue + self.blue_delta) % 255 } def draw(self): self.line.draw(window) if self.depth < self.max_depth: child_color = self.child_color() self.child = Leaf(depth = self.depth + 1, max_depth = self.max_depth, x = self.x2, y = self.y2, angle = self.angle + self.angle_delta, length = self.length * self.length_shrink, red = child_color['red'], # using a green = child_color['green'], # dictionary blue = child_color['blue'], width = self.child_width(), red_delta = self.red_delta, green_delta = self.green_delta, blue_delta = self.blue_delta, angle_delta = self.angle_delta, length_shrink = self.length_shrink, width_shrink = self.width_shrink ) self.child.draw() class Tree(object): def __init__(self, x=0.1, y=0.1, length=0.3, angle=pi/30): self.branches = [Leaf(x=x,y=y, length=length, angle=angle, max_depth=9), Leaf(x=x,y=y, length=length, angle=angle+pi/10, red_delta=30), Leaf(x=x,y=y, length=length, angle=angle+pi/6, angle_delta=pi/10.0, length_shrink=0.6), Leaf(x=x,y=y, length=length, angle=angle+pi/4, angle_delta=pi/8.0, blue_delta=100) ] for b in self.branches: b.draw() class Forest(object): def __init__(self): self.trees = [Tree(), Tree(x=0.5,y=0.7, length=0.1, angle=pi/2), Tree(x=0.9,y=0.8, length=0.15, angle=pi) ] def main(): f = Forest() wait = input("done? ") if __name__ == '__main__': main()