Integrated Studies (long)

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>

Teacher Notes: On Tue, Sep 9, 2008 at 12:12 PM, kirby urner <kirby.urner@gmail.com> wrote: << SNIP >>
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.
If you're doing the Oregon Curriculum group theory segments, then you'll recognize a link here to "cyclic notation", a way to encode permutations, e.g. letters A-Z to some other sort thereof. Many textbooks use numbers. So like if I write ((1, 4, 3), (2)), that means 1 -> 4, 2 -> 2, 3 -> 1, 4 -> 3 where -> is an "ascii arrow" meaning "maps to". The J language has a primitive verb for doing cyclic notation: http://jsoftware.com/help/dictionary/dccapdot.htm
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).
This is where exercises with "little lambda" might be fun, Python's light-weight "anonymous function", a tip of the hat to the LISP & Scheme family, which make lambda an animal worthy of worship, i.e. a much bigger deal (but then we have snakes to be proud of).
func = lambda thelist: thelist[1:] + [thelist[0]]
func(['A','B','C','D']) ['B', 'C', 'D', 'A']
Of course naming it func somewhat defeats the whole purpose of keeping it anonymous, not that lambda isn't itself a name, for a greek letter.
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).
VPython lets you build colors with RGB values, so this would be a good time for a segment on that, if students seem clueless. But you've also got the built-in colors to start, so if really beginners, maybe don't bore them with yet more details before letting them dive in, getting their hands "dirty". You could also assign each Polyhedron a default color in the master table, or a separate face, vertex and edge color. Go wild.
from visual import color dir ( color ) ['__builtins__', '__doc__', '__file__', '__name__', 'black', 'blue', 'colorsys', 'cyan', 'green', 'hsv_to_rgb', 'magenta', 'orange', 'red', 'rgb_to_hsv', 'white', 'yellow']
You'd think someone would add to this list in the original package, or maybe I just have an old version. I agree with Arthur that VPython is an important asset, an inspiration for future packages and/or newer versions of itself. Note that in Python 3.0 we have to unpack reload from the imp "suitcase":
from imp import reload
But as of this writing in late 2008, there wasn't a pysqlite driver for Python 3.0.
import sqlpolys Traceback (most recent call last): File "<pyshell#4>", line 1, in <module> import sqlpolys File "/home/kirby/sqlpolys.py", line 1, in <module> from pysqlite2 import dbapi2 as sqlite ImportError: No module named pysqlite2
However, there was APSW (Another Python Sqlite Wrapper) that did have 3.0 capability: http://code.google.com/p/apsw/
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
If you get through all this and they're hungry for more, consider using a string.Template approach to building a POV-Ray file, start adding facets as polygons, do more with vertices etc. You'll find lots in the Oregon Curriculum to help you down this road, if that's the road you choose. http://www.4dsolutions.net/ocn/cp4e.html Or reimplement in APSW as an exercise? Kirby
participants (1)
-
kirby urner