"""
Author: Kirby Urner, 4D Solutions, Sept. 15 2005
Last modified: Sept. 17 2005
Version #: 1.3
Developed for a Saturday Academy class (PSU, Portland)[1]
In a curriculum context, some parts are left unfinished, plus
even this version is suggestive of possible enhancements,
e.g. the Camera and Header APIs could be far more developed.
[1] this is during a time after SA had moved to PSU from OGI
"""
class Vector(object):
color = 'Red'
def __init__(self, xyz):
self.xyz = xyz
def write(self):
basic = "cylinder {<0,0,0>, <%s,%s,%s>, 0.1" % self.xyz
return "%s %s" % (basic, "pigment { color %s } no_shadow }" % self.color)
def __repr__(self):
return "Vector <%s, %s, %s>" % self.xyz
def __mul__(self, scalar):
xyz = tuple([scalar * i for i in self.xyz])
return Vector(xyz)
def __add__(self, other):
xyz = tuple([ i+j for i,j in zip(self.xyz, other.xyz)])
return Vector(xyz)
def _get_xyz(self):
return '<%s, %s, %s>' % self.xyz
def _get_length(self):
return pow(sum([i**2 for i in xyz]), 0.5)
coords = property(_get_xyz)
length = property(_get_length)
class Edge(object):
color = 'Red'
def __init__(self, v0, v1):
self.v0 = v0
self.v1 = v1
def __repr__(self):
return "Edge %s, %s" % (self.v0.coords, self.v1.coords)
def write(self):
basic = "cylinder {%s, %s, 0.1" % (self.v0.coords, self.v1.coords)
return "%s %s" % (basic, "pigment { color %s } no_shadow }" % self.color)
class Vertex(object):
color = 'Red'
radius = 0.1
def __init__(self, v0):
self.v0 = v0
def __repr__(self):
return "Sphere %s, radius = %s" % (self.v0.coords, self.radius)
def write(self):
basic = "sphere {%s, %s" % (self.v0.coords, self.radius)
return "%s %s" % (basic, "pigment { color %s } no_shadow}" % self.color)
class Polyhedron(object):
color = 'Red'
def __init__(self, vertsdict, faces):
self.verts = vertsdict
self.faces = faces
self.edges = self.__get_edges()
def __repr__(self):
return "Polyhedron: %s vertices, %s edges, %s faces" \
% (len(self.verts), len(self.edges), len(self.faces))
def __get_edges(self):
"""
take a list of face-tuples and distill
all the unique edges,
e.g. ((1,2,3)) => ((1,2),(2,3),(3,1))
e.g. icosahedron has 20 faces and 30 unique edges
( = cubocta 24 + tetra's 6 edges to squares per
jitterbug)
"""
uniqueset = set()
for f in self.faces:
edgetries = zip(f, f[1:]+ (f[0],))
for e in edgetries:
e = tuple(sorted(e))
uniqueset.add(e)
return tuple(uniqueset)
def write(self, name):
"""
generate the edges and vertices in POV-Ray
scene description language
"""
lines = ['#declare %s = union {' % name]
for e in self.edges:
edge = Edge( self.verts[e[0]], self.verts[e[1]] )
edge.color = self.color
lines.append(edge.write())
for v in self.verts.values():
sphere = Vertex(v)
sphere.color = self.color
lines.append(sphere.write())
lines.append("}")
lines.append("object {%s}\n" % name)
return '\n'.join(lines)
def __mul__(self, scalar):
newvectors = {}
for v in self.verts:
newvectors[v] = self.verts[v] * scalar
return Polyhedron(newvectors, self.faces)
class Header (object):
bgcolor = "color Gray50"
lightloc0 = "<300, 300, -1000>"
lightloc1 = "<-300, 300, -1000>"
lightcolor = "White"
@staticmethod
def write():
return """
#include "colors.inc"
background { %(bgcolor)s }
light_source{ %(lightloc0)s %(lightcolor)s }
light_source{ %(lightloc1)s %(lightcolor)s }
""" % Header.__dict__
class Camera (object):
look_at = 0
location = '<0, .1, -25>'
@staticmethod
def write():
return """
camera {
location %(location)s
look_at %(look_at)s
}
""" % Camera.__dict__
def buildicosa():
"""
Build an icosahedron from three mutually perpendicular
golden rectangles
"""
phi = (1 + pow(5,0.5))/2.0
verts = {
1:Vector((-phi, 0, -1)),
2:Vector((-phi, 0, 1)),
3:Vector(( phi, 0, 1)),
4:Vector(( phi, 0, -1)),
5:Vector(( -1, phi, 0)),
6:Vector(( 1, phi, 0)),
7:Vector(( 1, -phi, 0)),
8:Vector(( -1, -phi, 0)),
9:Vector(( 0, 1, phi)),
10:Vector(( 0, -1, phi)),
11:Vector(( 0, -1, -phi)),
12:Vector(( 0, 1, -phi))}
faces = ((5,6,9),(5,9,2),(5,2,1),(5,1,12),(5,12,6),
(1,11,12),(11,12,4),(12,4,6),(4,6,3),(6,3,9),
(3,9,10),(9,10,2),(10,2,8),(2,8,1),(8,1,11),
(7,11,4),(7,4,3),(7,3,10),(7,10,8),(7,8,11))
return verts, faces
def main():
icosa = Polyhedron(*buildicosa())
icosa.color = 'Orange'
Header.bgcolor = 'Black'
Header.lightloc1 = '<0, 0, 0>'
Camera.location = '<2, 4, -3>'
f = file('icosa.pov','w')
print >> f, Header.write()
print >> f, Camera.write()
print >> f, icosa.write("bigicosa")
icosasmall = icosa * 0.8
icosasmall.color = 'Green'
print >> f, icosasmall.write("smallicosa")
f.close()
if __name__ == '__main__':
main()
# code highlighted using py2html.py version 0.8