David Schmudde / Nov 08 2018

Fractals: Working

1.5s
from numpy import *
from matplotlib import pyplot as plt

def mandelbrot( h,w, maxit=40): #20
        '''
        Returns an image of the Mandelbrot fractal of size (h,w).
        '''
        y,x = ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ]
        #y,x = ogrid[ -0.25:0.25:h*1j, -1.8:-1.3:w*1j ]
        #y,x = ogrid[ -0.05:0.05:h*1j, -1.5:-1.4:w*1j ]
        c = x+y*1j
        z = c
        divtime = maxit + zeros(z.shape, dtype=int)

        for i in xrange(maxit):
                z  = z**2 + c
                diverge = z*conj(z) > 2**2            # who is diverging
                div_now = diverge & (divtime==maxit)  # who is diverging now
                divtime[div_now] = i + 100                 # note when
                z[diverge] = 2                        # avoid diverging too much

        return divtime

#plt.figure()
fig = plt.subplots(1,figsize=(20,20))
#s = "The Mandelbrot Set ([-2.0,0.8]x[-0.4,1.4], iterations = 40)"
#s = "The Mandelbrot Set ([-1.8,-1.3]x[-0.25,0.25], iterations = 40)"
s = "The Mandelbrot Set ([-1.5,-1.4]x[-0.05,0.05], iterations = 40)" #"+str(maxit)+")"
plt.title(s)
plt.imshow(mandelbrot(1000,1000)) 
plt.axis('off')
plt.savefig("/results/temp.png")
# plt.show("/results/img.png")
pip install argparse
3.0s
from numpy import *
from matplotlib import pyplot as plt

def mandelbrot( h,w, maxit=40): #20
        '''
        Returns an image of the Mandelbrot fractal of size (h,w).
        '''
        y,x = ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ]
        #y,x = ogrid[ -0.25:0.25:h*1j, -1.8:-1.3:w*1j ]
        #y,x = ogrid[ -0.05:0.05:h*1j, -1.5:-1.4:w*1j ]
        c = x+y*1j
        z = c
        divtime = maxit + zeros(z.shape, dtype=int)
        for i in xrange(maxit):
                z  = z**2 + c
                diverge = z*conj(z) > 2**2            # who is diverging
                div_now = diverge & (divtime==maxit)  # who is diverging now
                divtime[div_now] = i  +100                # note when
                z[diverge] = 2                        # avoid diverging too much

        return divtime
def mandelbrot2( h,w,a=-2.,b=.8,c=-1.4,d=1.4, maxit=40): #20
        '''
        Returns an image of the Mandelbrot fractal of size (h,w).
        '''
        y,x = ogrid[ c:d:h*1j, a:b:w*1j ]
        # y,x = ogrid[ -0.25:0.25:h*1j, -1.8:-1.3:w*1j ]
        #y,x = ogrid[ -0.05:0.05:h*1j, -1.5:-1.4:w*1j ]
        c = x+y*1j
        z = c
        divtime = maxit + zeros(z.shape, dtype=int)
        for i in xrange(maxit):
                z  = z**2 + c
                diverge = z*conj(z) > 2**2            # who is diverging
                div_now = diverge & (divtime==maxit)  # who is diverging now
                divtime[div_now] = i  +100                # note when
                z[diverge] = 2                        # avoid diverging too much

        return divtime

plt.figure(figsize=(20,20))
plt.imshow(mandelbrot2(1000,1000)) 
#s = "The Mandelbrot Set ([-2.0,0.8]x[-1.4,1.4], iterations = 40)"
#s = "The Mandelbrot Set ([-1.8,-1.3]x[-0.25,0.25], iterations = 40)"
s = "The Mandelbrot Set ([-1.5,-1.4]x[-0.05,0.05], iterations = 40)" 

plt.title(s)
plt.axis('off')

plt.imshow(mandelbrot2(1000,1000,-1.,-.6,0.,0.4)) 
s = "The Mandelbrot Set ([0,0.4]x[-1.,-0.6], iterations = 40)"
plt.title(s)
plt.axis('off')
plt.savefig("/results/temp2.png")
13.5s
import numpy as np
import matplotlib.pylab as plt
import random

def gasket(pa, pb, pc, level):
    x=(random.random(),random.random(),random.random())
    if level == 0:
        plt.fill([pa[0], pb[0], pc[0]], [pa[1], pb[1], pc[1]], color=x,alpha=0.9) 
        plt.hold(True)
    else:
        gasket(pa, (pa + pb) / 2., (pa + pc) / 2., level - 1) 
        gasket(pb, (pb + pa) / 2., (pb + pc) / 2., level - 1) 
        gasket(pc, (pc + pa) / 2., (pc + pb) / 2., level - 1)
        plt.hold(True)
        plt.fill([(pa[0] + pb[0]) / 2.,(pb[0] + pc[0]) / 2.,(pa[0] + pc[0]) / 2.],
                 [(pa[1] + pb[1]) / 2.,(pb[1] + pc[1]) / 2.,(pa[1] + pc[1]) / 2.],color=x,alpha=0.9)

A = np.array([0,28]) 
B = np.array([29,7])
C = np.array([18.5,-27])
D = np.array([-17.5,-27.5]) 
E = np.array([-29,6.5]) 
L = np.array([-7,6.5])
K = np.array([7,7])
M = np.array([11.5,-6])
N = np.array([0.5,-14.5])
O = np.array([-11,-6.5])
origin = np.array([0,-3])

level = 5
fig, ax = plt.subplots(1,figsize=(20,20)) 
gasket(A, L, K, level) 
gasket(B, K, M, level)
gasket(C, M, N, level)
gasket(D, N, O, level)
gasket(E, O, L, level)
gasket(origin, L, K, level)
gasket(origin, K, M, level)
gasket(origin, M, N, level)
gasket(origin, N, O, level)
gasket(origin, O, L, level)
plt.hold(False)
plt.title("A Randomly Colored Sierpinski Star (iterations = 5)")
ax.set_xlim(0,1.2) 
ax.set_ylim(0,1.2) 
plt.axis('equal')
plt.axis('off')
plt.savefig("/results/temp3.png")
0.6s
import matplotlib.pylab as plt
import numpy as np
import math

def koch(a,b,iterations):

    a1=a[0]
    a2=a[1]
    
    b1=b[0]
    b2=b[1]
    
    theta = np.arctan((b2-a2)/(b1-a1))
    length = np.sqrt((a1-b1)**2+(a2-b2)**2)
    
    c1 = (2*a1+b1)/3.
    c2 = (2*a2+b2)/3.
    c = [c1,c2]
    
    d1 = (a1+2*b1)/3.
    d2 = (a2+2*b2)/3.
    d = [d1,d2]
    
    if c1 >= a1:
        m1 = c1 + (length/3.)*math.cos(theta+math.pi/3.)
        m2 = c2 + (length/3.)*math.sin(theta+math.pi/3.)
    else:
        m1 = c1 + (length/3.)*math.cos(theta-2*math.pi/3.)
        m2 = c2 + (length/3.)*math.sin(theta-2*math.pi/3.)
    m = [m1,m2]
    
    c = np.array(c)
    d = np.array(d)
    m = np.array(m)
    
    points = []
    
    if iterations == 0:
        points.extend([a,b])
    elif iterations == 1:
        points.extend([a, c, m, d, b])
    else:
        points.extend(koch(a,c,iterations-1))
        points.extend(koch(c,m,iterations-1))
        points.extend(koch(m,d,iterations-1))
        points.extend(koch(d,b,iterations-1))  
                        
    return points



fig = plt.figure(figsize=(15,5))

plt.subplot(2,3,1).set_title("Koch Line (iterations = 0)")
points = koch(a=np.array([0, 0]),b=np.array([1,0]),iterations=0)
ptsx=[]
ptsy=[]
for i in range(len(points)):
    ptsx.append(points[i][0])
    ptsy.append(points[i][1])
plt.plot(ptsx, ptsy, '-')
plt.axis('equal')
plt.axis('off')

plt.subplot(2,3,2).set_title("Koch Line (iterations = 1)")
points = koch(a=np.array([0, 0]),b=np.array([1,0]),iterations=1)
ptsx=[]
ptsy=[]
for i in range(len(points)):
    ptsx.append(points[i][0])
    ptsy.append(points[i][1])
plt.plot(ptsx, ptsy, '-')
plt.axis('equal')
plt.axis('off')

plt.subplot(2,3,3).set_title("Koch Line (iterations = 2)")
points = koch(a=np.array([0, 0]),b=np.array([1,0]),iterations=2)
ptsx=[]
ptsy=[]
for i in range(len(points)):
    ptsx.append(points[i][0])
    ptsy.append(points[i][1])
plt.plot(ptsx, ptsy, '-')
plt.axis('equal')
plt.axis('off')

plt.subplot(2,3,4).set_title("Koch Line (iterations = 3)")
points = koch(a=np.array([0, 0]),b=np.array([1,0]),iterations=3)
ptsx=[]
ptsy=[]
for i in range(len(points)):
    ptsx.append(points[i][0])
    ptsy.append(points[i][1])
plt.plot(ptsx, ptsy, '-')
plt.axis('equal')
plt.axis('off')


plt.subplot(2,3,5).set_title("Koch Line (iterations = 4)")
points = koch(a=np.array([0, 0]),b=np.array([1,0]),iterations=4)
ptsx=[]
ptsy=[]
for i in range(len(points)):
    ptsx.append(points[i][0])
    ptsy.append(points[i][1])
plt.plot(ptsx, ptsy, '-')
plt.axis('equal')
plt.axis('off')

plt.subplot(2,3,6).set_title("Koch Line (iterations = 5)")
points = koch(a=np.array([0, 0]),b=np.array([1,0]),iterations=5)
ptsx=[]
ptsy=[]
for i in range(len(points)):
    ptsx.append(points[i][0])
    ptsy.append(points[i][1])
plt.plot(ptsx, ptsy, '-')
plt.axis('equal')
plt.axis('off')




plt.figure(figsize=(25,7))

plt.title("Koch Line (iterations = 6)")
points = koch(a=np.array([0, 0]),b=np.array([1,0]),iterations=6)
ptsx=[]
ptsy=[]
for i in range(len(points)):
    ptsx.append(points[i][0])
    ptsy.append(points[i][1])
plt.plot(ptsx, ptsy, '-')
plt.axis('equal')
plt.axis('off')
plt.savefig("/results/temp4.png")
5.4s
import matplotlib.pyplot as plt
import argparse
import math

def L_system(level, initial_state, trgt, rplcmnt, trgt2, rplcmnt2):
    state = initial_state
   
    for counter in range(level):
        state2 = ''
        for character in state:
            if character == trgt:
                state2 += rplcmnt
            elif character == trgt2:
                state2 += rplcmnt2
            else:
                state2 += character
        state = state2
    return state

def L(angle,coords,jump):
    return angle + math.radians(45)
def R(angle,coords,jump):
    return angle - math.radians(45)
def l(angle,coords,jump):
    return angle + math.radians(45)
def r(angle,coords,jump):
    return angle - math.radians(45)

def F(angle, coords, jump):
    coords.append(
        (coords[-1][0] + jump * math.cos(angle),
         coords[-1][1] + jump * math.sin(angle)))
    return angle

def G(angle,coords,jump):
    coords.append(
        (coords[-1][0] + cosin[angle],
            coords[-1][1] +sines[angle]))
    return angle

decode = dict(L=L, R=R, F=F, G=G,l=l,r=r)

def levyc(steps, length=200, startPos=(0,0)):
    starting= 'R'*steps+'FX'
    pathcodes = L_system(steps,  'F', 'F', 'rFllFr', '', '')
    jump = float(length) / (math.sqrt(2) ** steps)
    coords = [startPos]
    angle = 0
    for move in pathcodes:
        if move == 'F' or move =='r' or move== 'l' or move == 'R':
            angle= decode[move](angle,coords,jump)
    return coords



totalwidth=100
iterations = 0

fig = plt.figure(figsize=(17,10))
points = levyc(iterations,totalwidth,(-totalwidth/2,0))

plt.subplot(2,3,1).set_title("Levy's C Curve (iterations = 0)")
    
plt.plot([p[0] for p in points], [p[1] for p in points], '-',lw=3,color='darkgreen')
plt.axis('equal')
plt.axis('off')

iterations = 1

plt.subplot(2,3,2).set_title("Levy's C Curve (iterations = 1)")

points = levyc(iterations,totalwidth,(-totalwidth/2,0))
plt.plot([p[0] for p in points], [p[1] for p in points], '-',lw=3,color='darkgreen')
plt.axis('equal')
plt.axis('off')

iterations = 2

plt.subplot(2,3,3).set_title("Levy's C Curve (iterations = 2)")

points = levyc(iterations,totalwidth,(-totalwidth/2,0))
plt.plot([p[0] for p in points], [p[1] for p in points], '-',lw=3,color='darkgreen')
plt.axis('equal')
plt.axis('off')

iterations = 3

plt.subplot(2,3,4).set_title("Levy's C Curve (iterations = 3)")

points = levyc(iterations,totalwidth,(-totalwidth/2,0))
plt.plot([p[0] for p in points], [p[1] for p in points], '-',lw=3,color='darkgreen')
plt.axis('equal')
plt.axis('off')

iterations = 4

plt.subplot(2,3,5).set_title("Levy's C Curve (iterations = 4)")

points = levyc(iterations,totalwidth,(-totalwidth/2,0))
plt.plot([p[0] for p in points], [p[1] for p in points], '-',lw=3,color='darkgreen')
plt.axis('equal')
plt.axis('off')

iterations = 5

plt.subplot(2,3,6).set_title("Levy's C Curve (iterations = 5)")

points = levyc(iterations,totalwidth,(-totalwidth/2,0))
plt.plot([p[0] for p in points], [p[1] for p in points], '-',lw=3,color='darkgreen')
plt.axis('equal')
plt.axis('off')

iterations = 20

plt.figure(figsize=(20,16))

points = levyc(iterations,totalwidth,(-totalwidth/2,0))
plt.plot([p[0] for p in points], [p[1] for p in points], '-',color='olivedrab')
plt.axis('equal')
plt.axis('off')

plt.title("Levy's C Curve (iterations = 20)")

plt.savefig("/results/levy.png")

1.
Planet Fractal

#apt update
#apt-get install -y python-pil
pip install --upgrade pip
pip install Pillow
0.2s
# Random Planet Generator Using 3D Plasma Fractal
# and Voxel-based Ray Tracing for rendering
# (Instead of generating 2D Plasma Fractal and projecting onto sphere,
# it generates 3D Plasma Fractal (cube) and cuts sphere from it.)
# FB - 20160125
import math
import random
# import Image
from PIL import Image
imgx = 256; imgy = 256; imgz = 256
image = Image.new("RGB", (imgx, imgy))
pixels = image.load()
print "Creating voxels..."
# each voxel can have RGB color
voxelRGB = [[[(0, 0, 0) for x in range(imgx)] for y in range(imgy)] for z in range(imgz)]
# each voxel can have an opacity coefficient 0 or 1 (for simplicity)
opacity = [[[0 for x in range(imgx)] for y in range(imgy)] for z in range(imgz)]
eye = (imgx / 2.0, imgy / 2.0, -imgz / 2.0)
mx = imgx - 1; my = imgy - 1; mz = imgz - 1
f = 5.0 # roughness

def rnd():
    return (random.random() - .5) * f

def putvoxel(x, y, z, r, g, b):
    global voxelRGB, opacity
    x = int(round(x)); y = int(round(y)); z = int(round(z))
    voxelRGB[z][y][x] = (int(round(r)), int(round(g)), int(round(b)))
    opacity[z][y][x] = 1

def getvoxel(x, y, z):
    return voxelRGB[int(round(z))][int(round(y))][int(round(x))]

def CreatePlasmaCube(): # using non-recursive Diamond-square Algorithm
    global voxelRGB, opacity
    # corners
    for kz in range(2):
        for ky in range(2):
            for kx in range(2):
                putvoxel(mx * kx, my * ky, mz * kz, \
                    random.randint(0, 255), \
                    random.randint(0, 255), \
                    random.randint(0, 255))

    j = -1
    while True:
        j += 1; j2 = 2 ** j
        jx = float(mx) / j2; jy = float(my) / j2; jz = float(mz) / j2
        if jx < 1 and jy < 1 and jz < 1: break
        for m in range(j2):
            z0 = m * jz; z1 = z0 + jz; z = z0 + jz / 2.0        
            for i in range(j2):
                y0 = i * jy; y1 = y0 + jy; y = y0 + jy / 2.0        
                for k in range(j2):
                    x0 = k * jx; x1 = x0 + jx; x = x0 + jx / 2.0
                
                    a = getvoxel(x0, y0, z0); b = getvoxel(x1, y0, z0)
                    c = getvoxel(x0, y1, z0); d = getvoxel(x1, y1, z0)
                    e = getvoxel(x0, y0, z1); f = getvoxel(x1, y0, z1)
                    g = getvoxel(x0, y1, z1); h = getvoxel(x1, y1, z1)

                    # center
                    putvoxel(x, y, z, \
                        (a[0] + b[0] + c[0] + d[0] + e[0] + f[0] + g[0] + h[0]) / 8.0, \
                        (a[1] + b[1] + c[1] + d[1] + e[1] + f[1] + g[1] + h[1]) / 8.0, \
                        (a[2] + b[2] + c[2] + d[2] + e[2] + f[2] + g[2] + h[2]) / 8.0)

                    # centers of 6 faces
                    putvoxel(x, y, z0, \
                        (a[0] + b[0] + c[0] + d[0]) / 4.0, \
                        (a[1] + b[1] + c[1] + d[1]) / 4.0, \
                        (a[2] + b[2] + c[2] + d[2]) / 4.0)
                    putvoxel(x, y, z1, \
                        (e[0] + f[0] + g[0] + h[0]) / 4.0, \
                        (e[1] + f[1] + g[1] + h[1]) / 4.0, \
                        (e[2] + f[2] + g[2] + h[2]) / 4.0)
                    putvoxel(x, y0, z, \
                        (a[0] + b[0] + e[0] + f[0]) / 4.0, \
                        (a[1] + b[1] + e[1] + f[1]) / 4.0, \
                        (a[2] + b[2] + e[2] + f[2]) / 4.0)
                    putvoxel(x, y1, z, \
                        (c[0] + d[0] + g[0] + h[0]) / 4.0, \
                        (c[1] + d[1] + g[1] + h[1]) / 4.0, \
                        (c[2] + d[2] + g[2] + h[2]) / 4.0)
                    putvoxel(x0, y, z, \
                        (a[0] + c[0] + e[0] + g[0]) / 4.0, \
                        (a[1] + c[1] + e[1] + g[1]) / 4.0, \
                        (a[2] + c[2] + e[2] + g[2]) / 4.0)
                    putvoxel(x1, y, z, \
                        (b[0] + d[0] + f[0] + h[0]) / 4.0, \
                        (b[1] + d[1] + f[1] + h[1]) / 4.0, \
                        (b[2] + d[2] + f[2] + h[2]) / 4.0)

                    # centers of 12 edges
                    putvoxel(x, y0, z0, \
                        (a[0] + b[0]) / 2.0 + jx * rnd(), \
                        (a[1] + b[1]) / 2.0 + jx * rnd(), \
                        (a[2] + b[2]) / 2.0 + jx * rnd())
                    putvoxel(x0, y, z0, \
                        (a[0] + c[0]) / 2.0 + jy * rnd(), \
                        (a[1] + c[1]) / 2.0 + jy * rnd(), \
                        (a[2] + c[2]) / 2.0 + jy * rnd())
                    putvoxel(x1, y, z0, \
                        (b[0] + d[0]) / 2.0 + jy * rnd(), \
                        (b[1] + d[1]) / 2.0 + jy * rnd(), \
                        (b[2] + d[2]) / 2.0 + jy * rnd()) 
                    putvoxel(x, y1, z0, \
                        (c[0] + d[0]) / 2.0 + jx * rnd(), \
                        (c[1] + d[1]) / 2.0 + jx * rnd(), \
                        (c[2] + d[2]) / 2.0 + jx * rnd())
                    putvoxel(x, y0, z1, \
                        (e[0] + f[0]) / 2.0 + jx * rnd(), \
                        (e[1] + f[1]) / 2.0 + jx * rnd(), \
                        (e[2] + f[2]) / 2.0 + jx * rnd())
                    putvoxel(x0, y, z1, \
                        (e[0] + g[0]) / 2.0 + jy * rnd(), \
                        (e[1] + g[1]) / 2.0 + jy * rnd(), \
                        (e[2] + g[2]) / 2.0 + jy * rnd())
                    putvoxel(x1, y, z1, \
                        (f[0] + h[0]) / 2.0 + jy * rnd(), \
                        (f[1] + h[1]) / 2.0 + jy * rnd(), \
                        (f[2] + h[2]) / 2.0 + jy * rnd()) 
                    putvoxel(x, y1, z1, \
                        (g[0] + h[0]) / 2.0 + jx * rnd(), \
                        (g[1] + h[1]) / 2.0 + jx * rnd(), \
                        (g[2] + h[2]) / 2.0 + jx * rnd())
                    putvoxel(x0, y0, z, \
                        (a[0] + e[0]) / 2.0 + jz * rnd(), \
                        (a[1] + e[1]) / 2.0 + jz * rnd(), \
                        (a[2] + e[2]) / 2.0 + jz * rnd())
                    putvoxel(x1, y0, z, \
                        (b[0] + f[0]) / 2.0 + jz * rnd(), \
                        (b[1] + f[1]) / 2.0 + jz * rnd(), \
                        (b[2] + f[2]) / 2.0 + jz * rnd())
                    putvoxel(x0, y1, z, \
                        (c[0] + g[0]) / 2.0 + jz * rnd(), \
                        (c[1] + g[1]) / 2.0 + jz * rnd(), \
                        (c[2] + g[2]) / 2.0 + jz * rnd())
                    putvoxel(x1, y1, z, \
                        (d[0] + h[0]) / 2.0 + jz * rnd(), \
                        (d[1] + h[1]) / 2.0 + jz * rnd(), \
                        (d[2] + h[2]) / 2.0 + jz * rnd())

# cx, cy, cz: center; r: radius (in voxels)
def CreateSphere(cx, cy, cz, r):
    global voxelRGB, opacity
    # sphere is set of voxels which have distance = r to center
    for z in range(imgz):
        for y in range(imgy):
            for x in range(imgx):
                dx = x - cx
                dy = y - cy
                dz = z - cz
                d = math.sqrt(dx * dx + dy * dy + dz * dz)
                if abs(d - r) > 1.0:
                    voxelRGB[z][y][x] = (0, 0, 0)
                    opacity[z][y][x] = 0

# Ray Tracer (traces the ray and returns an RGB color)
def RayTrace(rayX, rayY, rayZ, dx, dy, dz):
    while True:
        rayX += dx; rayY += dy; rayZ += dz # move the ray by 1 voxel
        rayXint = int(round(rayX)); rayYint = int(round(rayY)); rayZint = int(round(rayZ))
        # if ray goes outside of the voxel-box
        if rayXint < 0 or rayXint > imgx - 1 \
            or rayYint < 0 or rayYint > imgy - 1 \
            or rayZint < 0 or rayZint > imgz - 1:
            return (0, 0, 0)
        # if ray hits an object
        if opacity[rayZint][rayYint][rayXint] == 1:
            return voxelRGB[rayZint][rayYint][rayXint]

def CreateScene():
    print "Creating scene..."
    CreatePlasmaCube()
    # CreateSphere(imgx / 2.0, imgy / 2.0, imgz / 2, min(imgx / 2.0, imgy / 2.0, imgz / 2))

def RenderScene():
    print "Rendering scene..."
    for ky in range(imgy):
        print str(100 * ky / (imgy - 1)).zfill(3) + "%"
        for kx in range(imgx):
            dx = kx - eye[0]
            dy = ky - eye[1]
            dz = 0.0 - eye[2]
            d = math.sqrt(dx * dx + dy * dy + dz * dz)
            dx = dx / d; dy = dy / d; dz = dz / d # ray unit vector
            pixels[kx, ky] = RayTrace(kx, ky, 0, dx, dy, dz)

# MAIN
CreateScene()
#RenderScene()
#image.save("RandomPlanet.png", "PNG")

2.
Turtle Graphics Dependencies

apt update
apt-get -y install build-essential python-qt4
gcc -v
pip install --upgrade pip
pip install Twisted turtle
0.2s
import turtle
import math
t = turtle.Pen()
t.tracer(100)

TOTAL_SIZE     = 10
BRANCH_ANGLE   = 50 # old 50
LEAN_ANGLE     = 2
SCALING_FACTOR_CHILDREN = 0.32 # old 0.31
SCALING_FACTOR_MAIN     = 0.9
BREAK_CASE = 1
SEGMENT_RATIOS = [0.3, 0.6]


'''
1 = 80(0.31^n)
1/80 = 0.31^n
n = log_0.31(x/80)
'''


def crazy(n): return math.log(n/80.0)/math.log(SCALING_FACTOR_CHILDREN)

def fern(size, angle):
    """Draw a fern.

    size  -- the size of the current fern (arbitrary units)
    angle -- the fern's leaning direction. -1 signifies left lean, 1 signifies
             right lean.

    """
    if size > BREAK_CASE:

        oldWidth = t.width()
        t.width(crazy(BREAK_CASE) - crazy(size))
        
        # draw the right branch
        t.forward(size * SEGMENT_RATIOS[0])
        t.right(BRANCH_ANGLE * angle)

        # we draw the new child fern; note that the angle is now reversed
        fern(size * SCALING_FACTOR_CHILDREN, -angle)
        t.left(BRANCH_ANGLE * angle)

        # draw the left branch
        t.forward(size * SEGMENT_RATIOS[1])
        t.left(BRANCH_ANGLE * angle)
        # we draw the new child fern; the angle is the same as this one
        fern(size * SCALING_FACTOR_CHILDREN, angle)
        t.right(BRANCH_ANGLE * angle)

        # draw the continuation of the current branch
        # we create the leaning effect by turning slightly in our lean direction
        t.right(LEAN_ANGLE * angle)
        fern(size * SCALING_FACTOR_MAIN, angle)
        t.left(LEAN_ANGLE * angle)

        # and backtrace all the way to the start of the fern!
        t.backward(size * sum(SEGMENT_RATIOS))

        t.width(oldWidth)

t.up(); t.goto(0, -340); t.down()
t.left(90)
t.color("darkgreen")

fern(90, 1)  #90, 1

t.tracer(1)
raw_input()