# Version 1.0

# watch out for the file path setting in the Povray class
# which is pre-coded to point to an existing directory (change to suit)

from math import sqrt

class Vector:
    """
    3D vector class (leave z at default 0 for x,y plane vectors)
    """

    def __init__(self,x,y,z=0):
        self.x = x
        self.y = y
        self.z = z

    def __add__(self, other):
        """Add two vectors: Overloads + """
        return Vector(self.x + other.x,
                      self.y + other.y,
                      self.z + other.z)

    def __neg__(self):
        """Negate vector: Overloads unary - """        
        return Vector(-self.x, -self.y, -self.z)

    def __sub__(self, other):
        """Subtract two vectors:  overloads binary - """
        return self + (- other)

    def dot(self,other):
        return sum([self.x * other.x, self.y * other.y,
                   self.z * other.z])

    def __mul__(self, scalar):
        """Grow/shrink (scale) vector by a number (float or int)
        overloads * """
        try:
            assert type(scalar) in [type(1), type(1.0)]
        except:
            return "Scaler must be int or float"
        return Vector(scalar * self.x, scalar * self.y, scalar * self.z)

    __rmul__ = __mul__  # define scalar multiplication on both sides of *

    def length(self):
        """Return length of vector"""
        return sqrt(self.x ** 2 + self.y **2 + self.z **2)

    def xyz(self):
        """Return x,y,z coordinates as a tuple"""        
        return (self.x, self.y, self.z)
    
    def __repr__(self):
        return 'Vector (%s, %s, %s)' % (self.x, self.y, self.z)


class Povray:
    """
    Redesigned from the version in examples1.py to take vector arguments.
    Here the Povray object itself does all the writing to the file.  The
    vector objects don't need to know anything about POV-ray
    """

    filepath = "C:/Documents and Settings/Kirby/My Documents/FreeGeek/PythonicGeom/"
    cylcolor = "Red"
    sphcolor = "Blue"
    
    def __init__(self, filename):        
        self.thefile = open(self.filepath + filename,'w')
        self.cylradius = 0.07
        self.sphradius = 0.07
        self.header()
                
    def edge(self, v0, v1):
        p0 = "<%s, %s, %s>" % v0.xyz()
        p1 = "<%s, %s, %s>" % v1.xyz()
        self.thefile.write("cylinder {%s, %s %s texture{pigment {color %s}}} \n"
                           % (p0, p1, self.cylradius, self.cylcolor))

    def point(self, v0):
        p0 = "<%s, %s, %s>" % v0.xyz()
        self.thefile.write("sphere {%s %s texture{pigment {color %s}}} \n"
                           % (p0, self.sphradius, self.sphcolor))

    def header(self):
        self.thefile.write("""
// Persistence of Vision Ray Tracer Scene Description File
// File: .pov
// Vers: 3.5
// Desc:
// Date:
// Auth: 

include "colors.inc"

// perspective (default) camera
camera {
  location  <0.0, 2.0, -10.0>
  look_at   <0.0, 0.0,  0.0>
  right     x*image_width/image_height
}

// create a regular point light source
light_source {
  0*x                  // light's position (translated below)
  color rgb <1,1,1>    // light's color
  translate <0.0, 2.0, -10.0>
}     

// set a color of the background (sky)
background { color White }
\n""")
                           
    def close(self):
        self.thefile.close()
        
def test():
    myfile = Povray("output.pov")
    v0 = Vector(0,0,0)
    v1 = Vector(3,0,0)
    v2 = Vector(0,4,0)
    myfile.edge(v0,v1)
    myfile.edge(v1,v2)
    myfile.edge(v2,v0)
    myfile.point(v0)
    myfile.point(v1)
    myfile.point(v2)
    myfile.close()

def test1():
    myfile = Povray("output2.pov")
    v0 = Vector(0,0,0)
    v1 = Vector(3,0,0)
    v2 = Vector(0,4,0)
    myfile.edge(v0,v1)
    myfile.edge(v1,v2)
    myfile.edge(v2,v0)
    myfile.point(v0)
    myfile.point(v1)
    myfile.point(v2)    
    m0 = (v0 + v1)* 0.5
    m1 = (v1 + v2)* 0.5
    m2 = (v2 + v0)* 0.5
    myfile.sphradius = 0.1
    myfile.point(m0)
    myfile.point(m1)
    myfile.point(m2)
    myfile.cylcolor = 'Green'
    myfile.edge(m0,m1)
    myfile.edge(m1,m2)
    myfile.edge(m2,m0)
    myfile.close()    
    
def test2():
    myfile = Povray("output3.pov")
    v0 = Vector(0,0,0)
    v1 = Vector(0,2,0)
    v2 = Vector(2,2,0)
    v3 = Vector(2,0,0)
    myfile.edge(v0,v1)
    myfile.edge(v1,v2)
    myfile.edge(v2,v3)
    myfile.edge(v3,v0)
    myfile.point(v0)
    myfile.point(v1)
    myfile.point(v2)
    myfile.point(v3)
    myfile.close()

def test3():
    myfile = Povray("output4.pov")
    v0 = Vector(0,0,0)
    v1 = Vector(0,2,0)
    v2 = Vector(2,2,0)
    v3 = Vector(2,0,0)
    
    v4 = Vector(0,0,2)
    v5 = Vector(0,2,2)
    v6 = Vector(2,2,2)
    v7 = Vector(2,0,2)
    
    myfile.edge(v0,v1)
    myfile.edge(v1,v2)
    myfile.edge(v2,v3)
    myfile.edge(v3,v0)
    
    myfile.edge(v4,v5)
    myfile.edge(v5,v6)
    myfile.edge(v6,v7)
    myfile.edge(v7,v4)

    myfile.edge(v0,v4)
    myfile.edge(v1,v5)
    myfile.edge(v2,v6)
    myfile.edge(v3,v7)
    
    myfile.point(v0)
    myfile.point(v1)
    myfile.point(v2)
    myfile.point(v3)

    myfile.point(v4)
    myfile.point(v5)
    myfile.point(v6)
    myfile.point(v7)
    
    myfile.close


def wackothing1():
    myfile = Povray("wackooutput1.pov")
    v0 = Vector(0,0,0)
    v1 = Vector(0,2,0)
    v2 = Vector(2,2,0)
    v3 = Vector(2,0,0)
    v0 = Vector(0,0,0)
    v1 = Vector(3,0,0)
    v2 = Vector(0,4,0)
    myfile.edge(v0,v1)
    myfile.edge(v1,v2)
    myfile.edge(v2,v3)
    myfile.edge(v3,v0)    
    myfile.point(v0)
    myfile.point(v1)
    myfile.point(v2)
    myfile.point(v3)
    myfile.close()
