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

                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

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

       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;

         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++){


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[]

   public Vertex add(Vertex v){
      return simplify(new Vertex(new double[]

   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]+", "

   public String xyzout(){
        return "<"+xyz[0]+", "
                  +xyz[1]+", "


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 "+

   public void writeEdge(PrintWriter output, String edgecolor,
                         float edgediam){
            "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");

    static private PrintWriter openfile(String filename){

            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

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)