```"""
Kirby Urner
4D Solutions
First published: Apr 29 2007

Suitable for spatial geometry and/or synergetics students.

Update May 10:  I'd forgotten 8 of the 20 Icosahedron triangles!  Added.
Update May 13:  Added Octahedron, Mite, Coupler

"""

from stickworks import Vector, Edge
from visual import color
from math import sqrt

phi = (sqrt(5) + 1)/2.0

class Polyhedron (object):

# defaults may be overridden

showfaces      = True
showedges      = True
showvertices   = True
# default POV-Ray textures

face_texture   = 'T_Stone14'   # from stones.inc

vertex_texture = 'T_Silver_1A' # from metals.inc

edge_texture   = 'T_Copper_4A' # from metals.inc

def scale(self, scalefactor):
newverts = {}
for v in self.vertices:
newverts[v] = self.vertices[v] * scalefactor
return self.__class__(newverts)

__mul__ = __rmul__ = scale

def translate(self, vector):
newverts = {}
for v in self.vertices:
newverts[v] = self.vertices[v] + vector
return self.__class__(newverts)

def _distill(self):

edges = []
unique = set()

for f in self.faces:
for pair in zip(f , f[1:] + (f[0],)):

for edge in unique:
edges.append( Edge(self.vertices[edge[0]],self.vertices[edge[1]]) )

return edges

def draw(self):
# VPython wireframe view, native to stickworks.py

for e in self.edges:
e.draw()

class Amodule (Polyhedron) :
pass

class Bmodule (Polyhedron) :
pass

class Mite (Polyhedron) :

def __init__(self,
verts  = dict(j = Vector(( 0,  1, 0)),
o = Vector(( 0,  0, 0)),
r = Vector(( 1,  0, 1)),
s = Vector(( 1,  0,-1)))):

# 4 vertices

self.vertices = verts

# 4 faces

self.faces = (('j','o','r'),('j','r','s'),('j','s','o'),('o','r','s'))

self.edges = self._distill()

class Smite (Polyhedron) :
pass

class Coupler (Polyhedron) :

def __init__(self,
verts  = dict(j = Vector(( 0,  1, 0)),
l = Vector(( 0, -1, 0)),
q = Vector((-1,  0, 1)),
r = Vector(( 1,  0, 1)),
s = Vector(( 1,  0,-1)),
t = Vector((-1,  0,-1)))):

# 6 vertices

self.vertices = verts

# 8 faces

self.faces = (('j','q','r'),('j','r','s'),('j','s','t'),('j','t','q'),
('l','q','r'),('l','r','s'),('l','s','t'),('l','t','q'))

self.edges = self._distill()

class Tetrahedron (Polyhedron) :

def __init__(self,
verts  = dict(a = Vector((-1, -1, 1)),
b = Vector((-1,  1, -1)),
c = Vector((1, 1, 1)),
d = Vector((1, -1, -1)))):
"""
Imagine a cube centered at the origin and with
a positive octant vertex at (1,1,1).  Inscribe
a regular tetrahedron as six face diagonals therein.
"""
# 4 vertices

self.vertices = verts

# 4 faces

self.faces = (('a','b','c'),('a','c','d'),
('a','d','b'),('b','d','c'))

self.edges = self._distill()

class Cube (Polyhedron):

def __init__(self, verts = dict( a = Vector((-1, -1, 1)),
b = Vector((-1,  1, -1)),
c = Vector((1, 1, 1)),
d = Vector((1, -1, -1)),
e = Vector((1,  1, -1)),
f = Vector((1, -1,  1)),
g = Vector((-1, -1, -1)),
h = Vector((-1, 1, 1)))):

# 8 vertices

self.vertices = verts

# 6 faces

self.faces = (('a','f','c','h'),('h','c','e','b'),
('b','e','d','g'),('g','d','f','a'),
('c','f','d','e'),('a','h','b','g'))

self.edges = self._distill()

class Octahedron (Polyhedron):

def __init__(self, verts = dict( i = Vector(( 0, 0, 1)),
j = Vector(( 0, 1, 0)),
k = Vector(( 0, 0,-1)),
l = Vector(( 0,-1, 0)),
m = Vector(( 1, 0, 0)),
n = Vector((-1, 0, 0)))):

# 6 vertices

self.vertices = verts

# 8 faces

self.faces = (('i','l','m'),('i','m','j'),('i','j','n'),('i','n','l'),
('k','l','m'),('k','m','j'),('k','j','n'),('k','n','l'))

self.edges = self._distill()

class Dodecahedron (Polyhedron):
pass

class Icosahedron (Polyhedron):

def __init__(self, verts = dict(
# 12 vertices at the corners of 3 mutually

# orthogonal golden rectangles

xya=Vector(( phi/2, 0.5, 0.0)), # phi rectangle in xy

xyb=Vector(( phi/2,-0.5, 0.0)),
xyc=Vector((-phi/2,-0.5, 0.0)),
xyd=Vector((-phi/2, 0.5, 0.0)),
#-----------------------------

xza=Vector((-0.5, 0.0, phi/2)), # Phi rectangle in xz

xzb=Vector(( 0.5, 0.0, phi/2)),
xzc=Vector(( 0.5, 0.0,-phi/2)),
xzd=Vector((-0.5, 0.0,-phi/2)),
#-----------------------------

yza=Vector(( 0.0, phi/2, 0.5)), # Phi rectangle in yz

yzb=Vector(( 0.0, phi/2,-0.5)),
yzc=Vector(( 0.0,-phi/2,-0.5)),
yzd=Vector(( 0.0,-phi/2, 0.5)),
)):

# 12 vertices

self.vertices = verts

# 20 equiangular triangles

self.faces = (
('xza','xzb','yzd'),
('yzd','xzb','xyb'),
('xyb','xzb','xya'),
('xya','yza','xzb'),
('xzb','yza','xza'),

('xzd','xzc','yzb'),
('yzb','xzd','xyd'),
('xyd','xzd','xyc'),
('xyc','xzd','yzc'),
('yzc','xzd','xzc'),

('xyd','yzb','yza'),
('yza','yzb','xya'),
('xya','yzb','xzc'),
('xzc','xya','xyb'),
('xyb','xzc','yzc'),
('yzc','xyb','yzd'),
('yzd','yzc','xyc'),
('xyc','yzd','xza'),
('xza','xyc','xyd'),
('xyd','xza','yza')
)

self.edges = self._distill()

self.rectangles = (
('xya','xyb','xyc','xyd'),
('xza','xzb','xzc','xzd'),
('yza','yzb','yzc','yzd'))

def goldrects(self):
Edge.color = green
for r in self.rectangles:
c0,c1,c2,c3 = [self.vertices[i] for i in r]
Edge(c0,c1).draw()
Edge(c1,c2).draw()
Edge(c2,c3).draw()
Edge(c3,c0).draw()

class Cuboctahedron (Polyhedron):
pass

def test():
"""
The Concentric Hierarchy by R. Buckminster Fuller
"""
Edge.color = color.orange
tetra = Tetrahedron() * 0.5
tetra.draw()

Edge.color = color.green
cube = Cube() * 0.5
cube.draw()

Edge.color = color.red
cube = Octahedron()
cube.draw()

Edge.color = color.cyan
ico = Icosahedron() * sqrt(2)
ico.draw()

def test2():
"""
Coupler in a Cube (canonical volumes 1 and 3 respectively)
"""

Edge.color = color.orange
tetra = Tetrahedron()
tetra.draw()

Edge.color = color.blue
coupler = Mite()
coupler.draw()

#Edge.color = color.blue

#coupler = Coupler()

#coupler.draw()

Edge.color = color.green
cube = Cube()
cube.draw()

if __name__ == '__main__':
test()
# test2()

```
`# code highlighted using py2html.py version 0.8`