Polymath 101 (2 of 2)
 poly1.html and poly2.html reproduce posts to the misc.education newsgroup, March 17,18 1999. I fixed a typo in the Cube edges table, which in the original was corrected in part II. One or two other typos fixed as well. Background reading: ``` From: urner@alumni.Princeton.EDU (Kirby Urner) Newsgroups: misc.education Subject: Re: Curriculum excerpt: Polymath 101 Date: Fri, 19 Mar 1999 06:35:35 GMT CURRICULUM EXCERPT: POLYMATH 101 OOP GEOMETRY: POLYS IN JAVA INSTRUCTOR: K. URNER -------------------------------------------------------------- An earlier segment provides information about quadray coordinates, used thoughout this segment. The volumes relate to the concentric hierarchy, familiarity with which is also assumed. -------------------------------------------------------------- A Java implementation of the foregoing poly definitions, in terms of their vertices and edges (vertex pairs), could take many forms. The Cube class below initializes an array of Edge objects, using pairs of vertices. Somehow, this Cube already knows what an Edge is, and even the meanings of vertex objects A-G. Given our Cube extends Polys, we might logically look for clues in the Polys class definition. class Cube extends Polys { /* CUBE (volume = 3) ==== Vertices Edges A 1 0 0 0 (A,F)(A,G)(A,H) B 0 1 0 0 (B,E)(B,G)(B,H) C 0 0 1 0 (C,E)(C,F)(C,H) D 0 0 0 1 (D,E)(D,F)(D,G) E 0 1 1 1 F 1 0 1 1 G 1 1 0 1 H 1 1 1 0 Last change: KU 18 Mar 1999 9:02 pm */ Cube(){ nbedges = 12; volume = 3; edgecolor = "Green"; edgediam = (float)0.04; edges = new Edge[nbedges]; edges[ 0] = new Edge(A,F); edges[ 1] = new Edge(A,G); edges[ 2] = new Edge(A,H); edges[ 3] = new Edge(B,E); edges[ 4] = new Edge(B,G); edges[ 5] = new Edge(B,H); edges[ 6] = new Edge(C,E); edges[ 7] = new Edge(C,F); edges[ 8] = new Edge(C,H); edges[ 9] = new Edge(D,E); edges[10] = new Edge(D,F); edges[11] = new Edge(D,G); } } Indeed, our Polys class pre-defines all the vertices needed by the concentric hierarchy shapes defined in the previous section: tetrahedron, inverted tetrahedron, cube, octahedron, rhombic dodecahedron and cuboctahedron. The constructor method for Polys starts by defining A-D, and then develops the rest using inv and add methods. Apparently, the vertex objects have internal methods for returning the results of these operations. import java.io.*; class Polys { Vertex A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z; Edge[] edges; double volume; int nbedges; String edgecolor; float edgediam; Polys(){ A = new Vertex(new double[]{1,0,0,0}); B = new Vertex(new double[]{0,1,0,0}); C = new Vertex(new double[]{0,0,1,0}); D = new Vertex(new double[]{0,0,0,1}); E = A.inv(); F = B.inv(); G = C.inv(); H = D.inv(); I = A.add(B); J = A.add(C); K = A.add(D); L = B.add(C); M = B.add(D); N = C.add(D); O = I.add(J); P = I.add(K); Q = I.add(L); R = I.add(M); S = N.add(J); T = N.add(K); U = N.add(L); V = N.add(M); W = J.add(L); X = L.add(M); Y = M.add(K); Z = K.add(J); } public void writexyz(){ for (int i=0;inbedges;i++){ edges[i].writeEdge(output,edgecolor,edgediam); } } } Below is our Vertex class. The 4-tuples associated with quadrays get stored in the tuple array (double[]) whereas the corresponding xyz 3-tuple goes in xyz (also double[]). The quad2xyz method performs the conversion. Vertex objects know how to output a String of the form where x,y and z are the xyz coordinates corresponding to the 4-tuple quadray (see the xyzout() method). class Vertex { static final double ROOT2 = Math.sqrt(2); public double[] tuple; public double[] xyz; Vertex(double[] coords){ tuple = new double[4]; for (int i=0;i<4;i++) tuple[i] = coords[i]; } public Vertex inv(){ return simplify(new Vertex(new double[] {-tuple[0], -tuple[1], -tuple[2], -tuple[3]} ) ); } public Vertex add(Vertex v){ return simplify(new Vertex(new double[] {tuple[0]+v.tuple[0], tuple[1]+v.tuple[1], tuple[2]+v.tuple[2], tuple[3]+v.tuple[3]} ) ); } private Vertex simplify(Vertex v){ double minval = v.tuple[0]; for (int i=1;i<4;i++) minval = minval4;i++) v.tuple[i] -= minval; return v; } private void quad2xyz(){ xyz = new double[3]; xyz[0] = 1/ROOT2* (tuple[0] - tuple[1] - tuple[2] + tuple[3]); xyz[1] = 1/ROOT2* (tuple[0] - tuple[1] + tuple[2] - tuple[3]); xyz[2] = 1/ROOT2* (tuple[0] + tuple[1] - tuple[2] - tuple[3]); } public String output(){ return "<"+tuple[0]+", " +tuple[1]+", " +tuple[2]+", " +tuple[3]+">"; } public String xyzout(){ quad2xyz(); return "<"+xyz[0]+", " +xyz[1]+", " +xyz[2]+">"; } } Finally, recall that our Polys class consists of vertices A-Z, plus some number of Edge objects, stored in Edge[] edges. The Edge object consists of a pair of vertices, plus contains a method for writing itself to an output file in the form of a Povray cylinder. This will allow the subclasses of Polys (e.g. Cube) to write themselves in Povray format, by invoking the Polys writepovray method. import java.io.*; class Edge { Vertex[] pair; Edge(Vertex v1, Vertex v2){ pair = new Vertex[]{v1,v2}; } public void xyzout(){ System.out.println("From: "+ pair[0].xyzout()+" to "+ pair[1].xyzout()); } public void writeEdge(PrintWriter output, String edgecolor, float edgediam){ output.println( "cylinder{"+ pair[0].xyzout() + "," + pair[1].xyzout() + "," + edgediam + " pigment {color " + edgecolor + "} no_shadow}"); } } Putting this all together, a Main class, designed for runtime execution, writes polyhedra to a povray file, which file is opened, initialized, and closed in the Main class itself. import java.io.*; public class Main { private static PrintWriter filehandle; public static void main(String[] args){ Tetra oTet = new Tetra(); InvTetra oTet2 = new InvTetra(); Cube oCube = new Cube(); Octahedron oOcta = new Octahedron(); Rhdodecahedron oDodeca = new Rhdodecahedron(); Cuboctahedron oCubocta = new Cuboctahedron(); filehandle = openfile("script.pov"); writeHeader(filehandle); oTet.writepovray(filehandle); oTet2.writepovray(filehandle); oCube.writepovray(filehandle); oOcta.writepovray(filehandle); oDodeca.writepovray(filehandle); oCubocta.writepovray(filehandle); filehandle.close(); } static private PrintWriter openfile(String filename){ try{ filehandle = new PrintWriter( new BufferedWriter( new FileWriter(filename))); } catch(Exception e) {System.out.println("Couldn't create file!");} return filehandle; } private static float camfactor = 8; protected static void writeHeader(PrintWriter output){ // source omitted (see below for download instructions) } } The results of Main are displayed at: http://www.inetarena.com/~pdx4d/ocn/java/polymath/script.gif (21K) Here's a key to what you'll see: Poly Color Volume =========================== Tetra Orange 1 InvTetra Black 1 Cube Green 3 Octa Red 4 RhDodeca Blue 6 Cubocta Yellow 20 This is a rendering obtained by feeding script.pov (the text file output of the above Java program) to Povray, a freeware ray tracing program available for multiple platforms via http://www.povray.org/. Povray saves its result as a BMP (Windows version), which graphic was converted to a GIF for web display. If you would like to download the Java source code for all of the above mentioned polys, plus the classes defined above, point your browser to: http://www.inetarena.com/~pdx4d/ocn/java/polymath/source.zip (6K) ```