# Flower.py
#
# This program draws a flower growing and blooming
#
# J Cardell, Due Feb 23, 2011, HW 4 CSC 111

from graphics import *
from random import randrange, random
from time import sleep
from math import pi, sin, cos, copysign

def main():
    # Define constants for graphing window
    Xmax = 20           # coordinate axis scaling
    Ymax = 20
    stemX = 0.4 * Xmax  # position along x-axis of flower
    startsz = 0.0125    # starting size factor for stem and bud

    # Create graphing window
    win = GraphWin("Flower", 750, 750)
    win.setBackground('pale green')
    win.setCoords(0, 0, Xmax, Ymax)
    title = Text(Point(Xmax/2, 0.95*Ymax), 'A Fantasy Flower Growing')
    title.setSize(24)
    title.setFill('BlueViolet')
    title.draw(win)

    # Grass: Create grass - extra, you do not need to do this
    nGrs = 500
    for grs in range(nGrs):
        xGrs = random()*Xmax
        yGrs = random()*3
        # for debugging
        # print "x and y grass ",xGrs,yGrs
        pt1 = Point(xGrs, yGrs)
        pt2 = Point(xGrs, yGrs+(random()*2 + 0.5))
        blade = Line(pt1, pt2)
        blade.setFill('DarkGreen')
        blade.setWidth(3)
        blade.draw(win)

    # Flower and Bud: Create a flower just starting to grow
    botPt = Point(stemX, 0)
    stem = Rectangle(botPt, Point(stemX, Ymax*startsz))
    upPt = stem.getP2()
    stem.setFill('dark orchid')
    stem.setOutline('dark blue')
    stem.draw(win)

    budR = Ymax*startsz/2   # the bud radius
    bud = Circle(Point(stemX, startsz), budR)
    bud.setFill('Magenta')
    bud.setOutline('dark cyan')
    bud.draw(win)

    # for loop for flower growing - up and larger
    nStates = 5  # The number of growth spurts for the flower
    grwStem = 2  # determines the growth rate for each iteration
    grwBud = 1.8
    pause = 0.5
    sleep (pause)  # pause the animation for easier observation

    for grw in range(nStates):
        topX = upPt.getX() + 0.05*grw
        topY = upPt.getY()*grwStem
        topPt = Point(topX, topY)
        stem = Rectangle(botPt, topPt)
        upPt = stem.getP2()
        stem.setFill('dark orchid')
        stem.setOutline('dark blue')
        stem = stem.draw(win)

        bud.undraw()
        budR = budR * grwBud
        stemMid = stemX+(topX-stemX)/2
        # for debugging
        # print "X values: ",stemX,topX,stemMid
        ctr = Point(stemX+(topX-stemX)/2, topY+budR)
        bud = Circle(ctr, budR)
        bud.setFill('magenta')
        bud.draw(win)

        sleep (pause)  # pause the animation for easier observation


    # Petals: for loop to add petals
    nPetals = randrange(10, 20)
    ptlSz = 0.75
    ctrX = ctr.getX()
    ctrY = ctr.getY()
    for ptl in range(nPetals):
        # Determine the angular position of the next petal,
        # in radians. Note that using sine and cosine is most
        # applicable for circular flowers
        angl = (2*pi/nPetals) * ptl
        ptlX = ctrX + cos(angl)*budR
        ptlY = ctrY + sin(angl)*budR
        petal = Circle(Point(ptlX, ptlY), ptlSz)

        # Create random RGB, or red green blue, color
        # Inspired by the random color class example
        clr = color_rgb(randrange(256), randrange(256), randrange(256))
        petal.setFill(clr)
        petal.setOutline(clr)
        petal.draw(win)

    # Leaves: add two polygon leaves on the left and right of stem
    leafSz = 2
    leafY = 0.65 * topY
    pt1 = Point(stemMid, leafY)
    pt2 = Point(stemMid-(0.8*leafSz), leafY+leafSz)
    pt3 = Point(stemMid-(2*leafSz), leafY+leafSz)
    pt4 = Point(stemMid-(1.2*leafSz),leafY)
    leafLt = Polygon(pt1, pt2, pt3, pt4, pt1)
    leafLt.setFill('skyblue')
    leafLt.draw(win)

    leafY = leafY * 0.95  # make right hand leaf a bit lower
    pt5 = Point(stemMid, leafY)
    pt6 = Point(stemMid+(0.8*leafSz), leafY+leafSz)
    pt7 = Point(stemMid+(2*leafSz), leafY+leafSz)
    pt8 = Point(stemMid+(1.2*leafSz),leafY)
    leafRt = Polygon(pt5, pt6, pt7, pt8, pt5)
    leafRt.setFill('turquoise')
    leafRt.draw(win)

    # Close the program gracefully
    win.getMouse()
    win.close()


main()
