[Edu-sig] Integrated Studies (long)
kirby.urner at gmail.com
Tue Sep 9 21:12:54 CEST 2008
Polyhedra, Python, and SQL
I'm archiving all the data and source code sufficient to start
outputting colorful polyhedra to screen, using the aforementioned 26
"points of interest" A-Z, and a Facets table giving each polyhedron's
faces by going around in sequence, in terms of these 26 labels, the
x,y,z coordinates supplied in a Vectors table.
For example, a Tetrahedron ABCD has facets [(A,B,C), (A,C,D), (A,D,B),
(B,C,D)]. Ordering matters within a facet (we're hopping around a
face, like a fenced yard with fence posts), so the Facets table has a
vertex_id column to keep them in order, within facet_id. You'll find
an ORDER BY vertex_id in the source code below.
The code below takes the name of a shape and uses the newgeom database to:
(a) pull up the facets, given the short name of a polyhedron
(b) distill unique edges from those facets and
(c) draw those edges to a VPython window.
Why "distill unique edges"? Because going around each face
effectively gives each edge twice. For example, our Tetrahedron
(above) has edges (A,B), (B,C), (C,A) per the first face (A,B,C).
Those edges will come up again as we distill (A,C), (C,D) and (D,A)
from the next face and so on.
By keeping all edge-tuples internally alphabetical, we keep (C,A) and
(A,C) from appearing unique, and therefore might use the 'set' data
structure to weed out the duplicates (trying to add (A,C) a second
time has no effect).
One way to distill edges from say face (A,B,C) is to zip ((A,B,C) ,
(B,C,A)) i.e. put the first vertex last in a second copy of the face,
to get pairs (A,B), (B,C) and (C,A) as above, but sorting
alphabetically, turning (C,A) into (A,C).
You'll see a list comprehension in getedges that does precisely this.
f[1:]+[f] is the syntax for turning a list into a rotated version
of itself i.e. if f = [A, B, C] then the result is [B, C, A] (see
The idea here is enterprising GnuMath teachers using this as tweakable
Even a beginning student can start changing the color, reloading the
module, and redrawing a polyhedron, all interactively via the shell
(remember to restart after closing the VPython window, automatic in
IDLE, but not in Wing 101, which I'm currently using).
There's a lot going on here, i.e. this is a dense packing of a lot of
ideas, meaning student should find it rewarding and relevant, plus the
eye candy is pretty fun (even better with enhancements).
from pysqlite2 import dbapi2 as sqlite
from visual import cylinder, color, vector
conn = sqlite.connect("newgeom")
curr = conn.cursor()
edges = getedges(shape)
for a, b in edges:
SELECT = """
select x,y,z from vectors where label = ?
x,y,z = curr.execute(SELECT, (a,)).fetchone()
v0 = vector(x,y,z)
x,y,z = curr.execute(SELECT, (b,)).fetchone()
v1 = vector(x,y,z)
radius= 0.01, color = color.red)
edgeset = set() # need to weed out dupes
SELECT = """
select faces from polyhedra
where shortname = ?
result = curr.execute(SELECT, (shape,))
num_faces = result.fetchone()
for i in range(num_faces):
f = list(getfaces(shape, i))
edges = [tuple( sorted((i,j)))
for i,j in zip(f, f[1:]+[f]) ]
for e in edges:
edgeset.add(e) # tuples hashable
def getfaces(shape, facet_id):
SELECT = """
select vertex_id, label
where facet_id = ? and shortname = ?
order by vertex_id"""
return curr.execute(SELECT, (facet_id, shape))
Here are the three table schemas, amenable to tweaking (per type, keys etc.):
sqlite> .schema Polyhedra
CREATE TABLE Polyhedra (
greekname CHAR PRIMARY KEY,
shortname CHAR NOT NULL,
vertices NUMERIC NOT NULL,
edges NUMERIC NOT NULL,
faces NUMERIC NOT NULL,
volume NUMERIC NOT NULL);
sqlite> .schema Vectors
CREATE TABLE Vectors (
sqlite> .schema Facets
CREATE TABLE Facets (
Here's the raw contents of the three tables, suitable for importing:
sqlite> select * from polyhedra;
sqlite> select * from vectors;
sqlite> select * from facets;
More information about the Edu-sig