from visual import *
from random import random
import time,sys,thread


scene.title = "Simulation"
scene.width = 800
scene.height = 720
scene.x = 20
scene.y = 20
scene.autoscale = 1
scene.up = (0,0,1)
scene.fov = pi/30.0
scene.forward = (0.0,1.0,-1.0)
scene.lights = [vector(.5,.5,.5), vector(-.5,-.5,-.5)]
scene.background = (0,0,0)
scene.uniform = 1
scene.range = 1.5
scene.select()


equatorLine = curve(x=cos(arange(0,2.1*pi,.1565)), y=sin(arange(0,2.1*pi,.1565)), color=(.5,.5,.5))


class Tracer:
    tracerPoints = []
    tracerCurve = curve()

    def __init__(self, tracerLength):
        tracerPoints = [ None ] * tracerLength                               # a vector of null elements, nSpinsX long
        for x in range(tracerLength):
            tracerPoints[x] = [0.0] * 3                             # a vector of zeros nSpinsY long

        self.tracerPoints = tracerPoints
        self.tracerCurve.pos = self.tracerPoints
        
    def stepTracer(self, updatePosition):
        del self.tracerPoints[0]

        self.tracerPoints.append(updatePosition)
        self.tracerCurve.pos = self.tracerPoints

    def getPoints(self):
        return self.tracerPoints




class Spin:
    point = sphere(visible=0)
    line = arrow(visible=0)

    tracer = Tracer(1)
    circle = curve()

    def __init__(self, tracerLength):
        self.tracerLength = tracerLength

        self.point = sphere(visible=0)
        self.line = arrow(visible=0)

        self.tracer = Tracer(tracerLength)
        self.circle = curve() 
        

    def getTracer(self):
        return self.tracer


        
class VisualSphere:
    visualArray = []
    
    def __init__(self, nSpinsX, nSpinsY, tracerLength):
        self.nSpinsX = nSpinsX
        self.nSpinsY = nSpinsY

        visualArray = [ None ] * nSpinsX                               # a vector of null elements, nSpinsX long
        for x in range(nSpinsX):
            visualArray[x] = [0] * nSpinsY                             # a vector of zeros nSpinsY long
            for y in range(nSpinsY):
                visualArray[x][y] = Spin(tracerLength)
               
        self.visualArray = visualArray



    def addPoints(self,numericArray):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].point = sphere(pos=(0.0,0.0,0.0), color=(1-((x+y)%2),.3*(x+y+2)/((x+1)*(y+1)),((x+y)%2)), radius = 0.02)

    def updatePoints(self,numericArray):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].point.pos = numericArray[x][y].spin



    def addVectors(self,numericArray):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].line = arrow(pos=(0.0,0.0,0.0), axis=numericArray[x][y].spin, color=(1-((x+y)%2),.3*(x+y+2.0)/((x+1.0)*(y+1.0)),((x+y)%2)), shaftwidth=0.002)

    def updateVectors(self,numericArray):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].line.axis = numericArray[x][y].spin

                

    def addTracers(self,numericArray):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].tracer.tracerCurve = curve(color=(1-((x+y)%2),.3*(x+y+2.0)/((x+1.0)*(y+1.0)),((x+y)%2)), radius = .003)

    def updateTracers(self,numericArray):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].getTracer().stepTracer(numericArray[x][y].spin)

                    

    def addCircles(self,numericArray):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].circle = curve(x=.1*cos(arange(0,2*pi,.31)), y=.1*sin(arange(0,2*pi,.31)),z=.5, color=(.6,.6,.6), visible=0)
        
                
    def resetVisuals(self):
        for x in range(self.nSpinsX):
            for y in range(self.nSpinsY):
                self.visualArray[x][y].point.visible = 0
                self.visualArray[x][y].tracer.visible = 0
                self.visualArray[x][y].vector.visible = 0
                self.visualArray[x][y].circle.visible = 0 

    def setAxis(self,commonAxis):
        if mag(commonAxis) > 0.0001:
            scene.forward = commonAxis

    def getArray(self):                         # handy, since we dont want to have to know the name of the object's actual variable!
        return self.visualArray





























