[Edu-sig] Integrated Studies (long)

kirby urner 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[0]] 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
below).

The idea here is enterprising GnuMath teachers using this as tweakable
scaffolding.

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).

Kirby


#===============

from pysqlite2 import dbapi2 as sqlite
from visual import cylinder, color, vector

conn = sqlite.connect("newgeom")
curr = conn.cursor()


def drawpoly(shape):

    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)

        cyl=cylinder(pos=v0, axis=v1-v0,
                     radius= 0.01, color = color.red)

def getedges(shape):

    edgeset = set()  # need to weed out dupes

    SELECT = """
    select faces from polyhedra
    where shortname = ?
    """
    result = curr.execute(SELECT, (shape,))
    num_faces = result.fetchone()[0]

    for i in range(num_faces):
        f = list(getfaces(shape, i))
        edges = [tuple( sorted((i[1],j[1])))
                  for i,j in zip(f, f[1:]+[f[0]]) ]
        for e in edges:
            edgeset.add(e) # tuples hashable

    return edgeset


def getfaces(shape, facet_id):

    SELECT = """
    select vertex_id, label
    from facets
    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 (
	label CHAR,
	x NUMERIC,
	y NUMERIC,
	z NUMERIC);

sqlite> .schema Facets
CREATE TABLE Facets (
	shortname CHAR,
	facet_id NUMERIC,
	vertex_id NUMERIC,
	label CHAR);


Here's the raw contents of the three tables, suitable for importing:

sqlite> select * from polyhedra;
Tetrahedron,tetra,4,6,4,1
Hexahedron,cube,8,12,6,3
Octahedron,octa,6,12,8,4
"Rhombic Dodecahedron",cell,14,24,12,6
Cuboctahedron,cubocta,12,24,14,20

sqlite> select * from vectors;
Z,0.707106781186547,0.707106781186547,0
A,0.353553390593274,0.353553390593274,0.353553390593274
C,-0.353553390593274,0.353553390593274,-0.353553390593274
B,-0.353553390593274,-0.353553390593274,0.353553390593274
E,-0.353553390593274,-0.353553390593274,-0.353553390593274
D,0.353553390593274,-0.353553390593274,-0.353553390593274
G,0.353553390593274,-0.353553390593274,0.353553390593274
F,0.353553390593274,0.353553390593274,-0.353553390593274
I,0,0,0.707106781186547
H,-0.353553390593274,0.353553390593274,0.353553390593274
K,0.707106781186547,0,0
J,0,0.707106781186547,0
M,0,-0.707106781186547,0
L,-0.707106781186547,0,0
O,0,0.707106781186547,0.707106781186547
N,0,0,-0.707106781186547
Q,-0.707106781186547,0,0.707106781186547
P,0.707106781186547,0,0.707106781186547
S,0,0.707106781186547,-0.707106781186547
R,0,-0.707106781186547,0.707106781186547
U,-0.707106781186547,0,-0.707106781186547
T,0.707106781186547,0,-0.707106781186547
W,-0.707106781186547,0.707106781186547,0
V,0,-0.707106781186547,-0.707106781186547
Y,0.707106781186547,-0.707106781186547,0
X,-0.707106781186547,-0.707106781186547,0

sqlite> select * from facets;
tetra,0,0,A
tetra,0,1,B
tetra,0,2,C
tetra,1,0,A
tetra,1,1,C
tetra,1,2,D
tetra,2,0,A
tetra,2,1,D
tetra,2,2,B
tetra,3,0,B
tetra,3,1,C
tetra,3,2,D
cube,0,0,A
cube,0,1,H
cube,0,2,C
cube,0,3,F
cube,1,0,A
cube,1,1,H
cube,1,2,B
cube,1,3,G
cube,2,0,B
cube,2,1,E
cube,2,2,C
cube,2,3,H
cube,3,0,B
cube,3,1,E
cube,3,2,D
cube,3,3,G
cube,4,0,D
cube,4,1,G
cube,4,2,A
cube,4,3,F
cube,5,0,C
cube,5,1,E
cube,5,2,D
cube,5,3,F
octa,0,0,I
octa,0,1,J
octa,0,2,K
octa,1,0,I
octa,1,1,L
octa,1,2,M
octa,2,0,I
octa,2,1,J
octa,2,2,L
octa,3,0,I
octa,3,1,M
octa,3,2,K
octa,4,0,N
octa,4,1,J
octa,4,2,K
octa,5,0,N
octa,5,1,K
octa,5,2,M
octa,6,0,N
octa,6,1,M
octa,6,2,L
octa,7,0,N
octa,7,1,L
octa,7,2,J
cell,0,0,N
cell,0,1,F
cell,0,2,J
cell,0,3,C
cell,1,0,N
cell,1,1,F
cell,1,2,K
cell,1,3,D
cell,2,0,N
cell,2,1,D
cell,2,2,M
cell,2,3,E
cell,3,0,N
cell,3,1,C
cell,3,2,L
cell,3,3,E
cell,4,0,I
cell,4,1,A
cell,4,2,J
cell,4,3,H
cell,5,0,I
cell,5,1,H
cell,5,2,L
cell,5,3,B
cell,6,0,I
cell,6,1,B
cell,6,2,M
cell,6,3,G
cell,7,0,I
cell,7,1,G
cell,7,2,K
cell,7,3,A
cell,8,0,K
cell,8,1,F
cell,8,2,J
cell,8,3,A
cell,9,0,K
cell,9,1,D
cell,9,2,M
cell,9,3,G
cell,10,0,M
cell,10,1,B
cell,10,2,L
cell,10,3,E
cell,11,0,L
cell,11,1,C
cell,11,2,J
cell,11,3,H
cubocta,0,0,O
cubocta,0,1,Q
cubocta,0,2,W
cubocta,1,0,O
cubocta,1,1,Z
cubocta,1,2,P
cubocta,2,0,P
cubocta,2,1,R
cubocta,2,2,Y
cubocta,3,0,R
cubocta,3,1,Q
cubocta,3,2,X
cubocta,4,0,W
cubocta,4,1,S
cubocta,4,2,U
cubocta,5,0,U
cubocta,5,1,X
cubocta,5,2,V
cubocta,6,0,Y
cubocta,6,1,T
cubocta,6,2,V
cubocta,7,0,Z
cubocta,7,1,T
cubocta,7,2,S
cubocta,8,0,O
cubocta,8,1,P
cubocta,8,2,R
cubocta,8,3,Q
cubocta,9,0,O
cubocta,9,1,W
cubocta,9,2,S
cubocta,9,3,Z
cubocta,10,0,Q
cubocta,10,1,W
cubocta,10,2,U
cubocta,10,3,X
cubocta,11,0,P
cubocta,11,1,Z
cubocta,11,2,T
cubocta,11,3,Y
cubocta,12,0,R
cubocta,12,1,X
cubocta,12,2,V
cubocta,12,3,Y
cubocta,13,0,T
cubocta,13,1,S
cubocta,13,2,U
cubocta,13,3,V
sqlite>


More information about the Edu-sig mailing list