# By K. Urner, 4D Solutions
# Last modified: Feb 29, 2000

import povray
import coords
import functions
import primes
import series
import rand
import time
import turtles

def mkpacking(n):
    # main (open, write, close)
    myfile = povray.Povray("tripack4.pov")
    myfile.sphradius = 0.05
    myfile.sphcolor = "Green"
    pascalpack(n,myfile)
    # functions.xyzaxes(myfile,1.5)
    myfile.close()
    
def tripack(n,myfile):
    # output a triangular sphere packing
    # as a povray file with n rows
    diameter = 2.0 * myfile.sphradius
    vertdrop = (3**0.5)/2.0 * diameter
    y_int = coords.Vector((       0,vertdrop,0))
    x_int = coords.Vector((diameter,       0,0))
    v1 = y_int * (n-1) # start at top, work down
    for i in range(1,n+1):
        v2 = v1
        for j in range(i):
            myfile.point(v2)
            # shift right by sphere diameter
            v2 = v2 + x_int
        # end of row: drop down, shift left
        v1 = v1 - y_int - coords.Vector((diameter/2.0,0,0))

def geoboard(n,myfile):
    # output a triangular sphere packing
    # as a povray file with n rows
    diameter = 2.0 * myfile.sphradius
    vertdrop = (3**0.5)/2.0 * diameter
    y_int = coords.Vector((       0,vertdrop,0))
    x_int = coords.Vector((diameter,       0,0))
    # start at top, work down
    v1 = y_int * (n-1) * 0.5 
    myfile.sphradius = myfile.sphradius/5.0 # small for drawing    
    for i in range(1,n+1):
        v2 = v1
        for j in range(i):
            myfile.point(v2)
            # shift right by sphere diameter
            v2 = v2 + x_int
        # end of row: drop down, shift left
        v1 = v1 - y_int - coords.Vector((diameter/2.0,0,0))

    myfile.sphradius = myfile.sphradius * 5.0 # back to normal

def randtri(n,myfile):
    # draw descending randomized left/right edges
    # in a tripacking
    diameter = 2.0 * myfile.sphradius
    vertdrop = (3**0.5)/2.0 * diameter
    vectorset = {}
    v1 = coords.Vector(( diameter/2.0,-vertdrop,0.0)) 
    v2 = coords.Vector((-diameter/2.0,-vertdrop,0.0))
    oturtle = turtles.Turtle([v1,v2],myfile)
    oturtle.color = "Orange"
    # start at top, work down
    oturtle.penup()   # stop tracing path
    oturtle.goto(coords.Vector((0,vertdrop,0)) * n * 0.5)
    oturtle.pendown() # start tracing path
    print vertdrop
    print v1.coords      
    for i in range(n):
        oturtle.randomwalk(1)
        
def pascalpack(n,myfile):
    # output a triangular sphere packing
    # as a povray file with 0,1,2...n rows
    starttime = time.time()
    global entries
    entries = {}
    diameter = 2.0 * myfile.sphradius
    vertdrop = (3**0.5)/2.0 * diameter
    y_int = coords.Vector((       0,vertdrop,0))
    x_int = coords.Vector((diameter,       0,0))
    v1 = y_int * (n-1) * 0.5 # start at top, work down
    for i in range(1,n+2):
        print i-1 # display row/level 
        v2 = v1
        for j in range(i):
            rtnval = testpass4(i-1,j,n)
            if   rtnval == 1: myfile.sphcolor = "Orange"
            elif rtnval == 2: myfile.sphcolor = "Blue"
            elif rtnval == 3: myfile.sphcolor = "Green"
            elif rtnval == 4: myfile.sphcolor = "Red"
            else: myfile.sphcolor = "Black"
            myfile.point(v2)
            # shift right by sphere diameter
            v2 = v2 + x_int
        # end of row: drop down, shift left
        v1 = v1 - y_int - coords.Vector((diameter/2.0,0,0))
    endtime = time.time()
    print "Total seconds elapsed: ", endtime-starttime

def testpass1(i,j,n):
    entry = series.pascal(i,j)
    return primes.iseven(entry)

def testpass2(i,j,n):
    entry = series.pascal(i,j)
    return primes.isprime(entry)

def testpass3(i,j,n):
    # Pascal's Triangle -- color coded for near-primes
    if primes.isprime(entry):
        rtnval = 1
    else:
        neg1  = primes.isprime(entry-1)
        pos1  = primes.isprime(entry+1)    
        if neg1:  rtnval = 2
        if pos1:  rtnval = 3       
        if neg1 and pos1: rtnval = 4  # overrides previous values
    return rtnval

def testpass4(r,c,n):
    # Pascal's Tetrahedron -- color coded for near-primes
    rtnval=0
    ijk = series.getijk(n,r,c)
    ijk.sort()
    index = str(ijk)
    if entries.has_key(index):
        return entries[index]   # return from cache if seen before  

    entry = series.pasctet(n,r,c)

    if primes.isprime(entry):
        rtnval = 1
    else:
        neg1  = primes.isprime(entry-1)
        pos1  = primes.isprime(entry+1)
        
        if neg1:  rtnval = 2
        if pos1:  rtnval = 3       
        if neg1 and pos1: rtnval = 4  # overrides previous values

    entries[index] = rtnval           # cache results
    return rtnval