"""
 koch_zelle.py

 Problem 8, pg 64 in Zelle's Python Programming text :
 Use a Turtle class to draw a recursive Koch curve fractal.
 Jim M | GPL | Nov 2010
"""

from graphics import GraphWin, Point, Line
from math import pi, sin, cos

class Turtle:
  """ A Turtle is a graphics abstraction;
      see wikipedia's "Turtle Graphics" article for a description.
      This one is based on Zelle's graphics.py module.
      For example, this is how you could draw a square :
        t = Turtle()           # create a window and turtle
        for side in range(4):  # four sides of square :
          t.move(10)           #   draw a line that's 10 units long
          t.turn(90)           #   turn 90 degrees
  """

  degrees2radians = pi / 180.0  # conversion factor

  def __init__(self, windowSize = (400, 400),
               position = (200, 200), direction = 0.0):
    """ Turtle initialization optional parameters :
         windowSize = window size in pixels
         position = (x,y) initial turtle position; (0,0) is bottom left
         direction = initial orientation of turtle; 0.0 is eastwards
    """
    self.window = GraphWin('Turtle', windowSize[0], windowSize[1])
    self.window.setCoords(0, 0, windowSize[0], windowSize[1])
    self._penDown = True
    self.position = position
    self.direction = direction

  def penUp(self):
    """ Set turtle's pen up; i.e. move doesn't draw """
    self._penDown = False

  def penDown(self):
    """ Set turtle's pen down; i.e. move does draw """
    self._penDown = True

  def turn(self, degrees):
    """ Rotate the direction that the turtle is facing. """
    self.direction += degrees

  def move(self, distance):
    """ Move the given distance in the direction the turtle is facing,
        drawing a line if the pen is down.
    """
    x0 = self.position[0]
    y0 = self.position[1]
    x1 = x0 + distance * cos(Turtle.degrees2radians * self.direction)
    y1 = y0 + distance * sin(Turtle.degrees2radians * self.direction)
    if self._penDown:
      Line(Point(x0,y0), Point(x1,y1)).draw(self.window)
    self.position = (x1, y1)
  
  def square(self, length):
    """ Draw a square with a turtle. """
    for i in range(4):
      self.move(length)
      self.turn(90)

  def koch(self, length, recursionDepth):
    """ Recursively draw a Koch curve. """
    if recursionDepth == 0:
      self.move(length)
    else:
      for angle in (0.0, 60.0, -120.0, 60.0):
        self.turn(angle)
        self.koch(length/3.0, recursionDepth - 1)

def main():
  turtle = Turtle(position=(10,10))
  turtle.koch(380, 4)
  wait = input('quit? ')  

main()