Sie sind auf Seite 1von 171

Calculating the Chord Lengths of an n-frequency

Icosahedral Geodesic Dome


David Anderson
January 1998

After getting a copy of BuckyWorks for Christmas, I decided to build a Icosahedral Geodesic Dome with
the kids in the basement. A 1-frequency icosahedral dome would be simple, but not very much fun; I
wanted more of a construction challenge. A 2- or 3-frequency icosahedral dome would be cool; fun to
build and potentially elaborate. So off to the web I went...

After looking around for some information for a while, I couldn't find any staightforward analysis of the
icosahedron. Lots of pictures and drawings, but nothing on chord lengths and connectors so I'd know what
I'd have make. Damn. So I got out my paper, pencil and calculator.

An icosahedron has 12 vertices, 20 faces, and 30 edges: the most elaborate of the five regular
polyhedrons. Basically, a soccer ball is a simple trucated icosahedron. The icosahedron is a good
approximation of a sphere: each vertex lies on the surface of the sphere it circumscribes. As a structure,
the icosahedron is pure simplicity: each face is an equilateral triangle and all of the edges are the same
length. When a higher frequency icosahedral geodesic structure is desired, the structure becomes more
complicated; each icosahedral face is tesselated into n2 subfaces. Although the tesselation of the
icosahedral face is rotationally symmetric (with a period of 2 /3), the sizes of the tesselated subfaces are
not the same; their edges increase in length as the center of the face is approached.

The simplest representation for vertices of the icosahedron (in normal geometric terms) is in polar
coordinates.

polar radius theta phi


coordinates (* edgeLength) (radians) (radians)
top 0.95105 0.0
0.95105 0.0 1.10716
0.95105 0.62830 1.10716
upper
pentagonal 0.95105 1.25661 1.10716
layer
0.95105 1.88492 1.10716
0.95105 2.51322 1.10716
0.95105 0.31415 2.03437
0.95105 0.94245 2.03437
lower
pentagonal 0.95105 1.57076 2.03437
layer
0.95105 2.19907 2.03437
0.95105 2.82737 2.03437
bottom 0.95105 3.14152

Note that the radius is directly proportional to the length of an edge, as carried through in the following
analysis.

The goal of the analysis is to determine the radius, theta, phi for each vertex. Since each vertex is
equidistant from the center of the circumscribed sphere, each will have the same value for its radius. The
vertices of the icosahedron are paired - each is diametrically opposed to its partner. If one pair is set to be
at the icosahedron's "top" and "bottom", then the other vertices are pentagonally arranged in two layers
between them, each out of phase with the other - the theta's simply walk around the top-bottom axis in
fifth-of- steps. The center of the layers lies on the top-bottom axis. The phis of the top and bottom
vertices are 0 and , while the phi of the pentagonal vertices alternate between the same angle above and
below the perpendicular bisecting plane of the top-bottom axis.

The two unknowns of the icosahedron are therefore the radius of the circumscribed sphere, and the angle
phi which a vertex in a pentagonal layer makes the top-bottom axis. Fortunately, these unknowns can be
found analytically. The plan is to find the radius d as the distance from the center of the icosahedron to a
vertex on a pentagonal layer. Then, by knowing the upper pentagonal layer altitude and the perpendicular
distance of a vertex in the upper pentagonal layer from the top-bottom axis, phi may be found for a
pentagonal layer vertex. All of the needed computations may be done via simple trigonometry and
analytic geometry.

First we start with the upper penagonal layer with side s.


The distance from the center of the pentagon to a vertex is r and is computed using the law of sines and
by knowing that the internal angle must be a fifth of 2 , the other angles are the same, and the sum of the
angles must equal .

Next the perpendicular distance p from the pentagon's center to an edge in the lower pentagonal layer is
found via the Pythagorean Theorem.

Next, the distance t from a vertex in the upper pentagonal layer to the edge bisector directly "below" in
the lower pentagonal layer must be found. This is simply the length of the bisector of one of the
icosahedron's faces since it is what lies between the vertex and bisector and is found using the
Pythagorean Theorem.

Now the perpendicular distance is found by "straightening up" t. The altitude u of the upper pentagonal
layer and the lower pentagonal layer is found, again, using the Pythagorean Theorem. (Note that u is
equal to r - hmmm)
Thus, the distance d and angle phi may be found by the Pythagorean theorem and the law of sines.

The frequency of the polyhedron indicates the number of subdivisions:

02 = 0 subfaces
0-frequency 0 segments per edge
(degeneracy: a mathematical point)

12 = 1 subfaces
1-frequency 1 segment per edge
(identity: the face itself)

2-frequency 2 segments per edge 22 = 4 subfaces

3-frequency 3 segments per edge 32 = 9 subfaces

4-frequency 4 segments per edge 42 = 16 subfaces

...

n-frequency n segments per edge n2 subfaces


Once of the important properties of the icosahedron is the regularity of the dimensions of its edges and
faces; this is thrown off when the tesselated icosahedron's vertices are projected onto the circumscribed
sphere. Consider the 4-frequency face; in the following diagram color is used to indicate chords of the
same length:

In order of increasing length, the number of components of each size are 6 red, 6 darkgreen, 3 purple, 6
orange, 6 blue, and 3 green. Out of the 30 segments, it is clear there is significant symmetry, but just as
clear is that the total saving in manufactiuring has been reduced - and will get worse as the frequency
increases. In addition, the subfaces now have edges of different length. In the 4-frequency face, there are
five distinct shapes which can be denoted by their edges: 3 red-red-purple, 6 orange-blue-darkgreen, 3
darkgreen-darkgreen-purple, 3 blue-blue-green, and 1 green-green-green. Thankfully many of the
subfaces are bilaterally symmetric, and the rest may be flipped over if the inner and outer surfaces are the
same, but it is certainly more complex than the single lengths and sizes found in the icosahedron. There is
some economy of scale which has been preserved, however. Since each face is replicated 20 times on the
icosahedron, each number of specialized materials can be multiplied by 20. If a dome is desired, then the
multiple is lower - but still offers some economy.

Given these preliminaries, an icosahedral geodesic patch may be created by forming a two-dimensional
equilateral mesh and projecting its vertices onto the circumscribed sphere. The icoshedron is "part" of its
circumscribed sphere: each vertex lies on its surface. As the geodesic frequency increases, more and more
vertices touch the sphere and it more closely approximates the mathematical ideal. However, each edge
between two vertices is a straight line and each surface between three edges is a planar surface. In the
limit, as n increase to infinity, the surface is the sphere - but such a limit is, of course, purely
mathematical.

The remaining problem is to calculate the lengths of the chords of the icosahedral geodesic patch. Only
one patch needs to be calculated; it is symmetrically repeated to populate the icosahedral geodesic
surface; this means we'll be duplicating the edges of the icosahedron when we duplicate the tesselated
surfaces, but that's just a bother, not a problem.

To calculate the chord lengths, the mesh of vertices must be found. We label each vertex to facilitate their
subsequent use in chord determination.
By judiciously orienting the icosahedron in Cartesian space, only minimal calculation is needed to
compute the mesh.

x y z
Vertex
(* edgeLength) (* edgeLength) (* edgeLength)
(0,0) 0.0 0.0 0.95105
(0,1) 0.17204 -0.125 0.81962
(1,0) 0.17204 0.125 0.81962
(0,2) 0.34409 -0.25 0.68819
(1,1) 0.34409 0.0 0.68819
(2,0) 0.34409 0.25 0.68819
(0,3) 0.51614 -0.375 0.55675
(1,2) 0.51614 -0.125 0.55675
(2,1) 0.51614 0.125 0.55675
(3,0) 0.51614 0.375 0.55675
(0,4) 0.68819 -0.5 0.42532
(1,3) 0.68819 -0.25 0.42532
(2,2) 0.68819 0.0 0.42532
(3,1) 0.68819 0.25 0.42532
(4,0) 0.68819 0.5 0.42532

Next, the vertices in the mesh must be projected from the flat equilateral triangular face of the
icosahedron onto the curved surface of the circuscribed sphere. This is done by converting the mesh point
to spherical coordinates, extending the radius, and converting back to Cartesian coordinates.
x y z
Vertex
(* edgeLength) (* edgeLength) (* edgeLength)
(0,0) 0.0 0.0 0.95105
(0,1) 0.19323 -0.14039 0.92057
(1,0) 0.19323 0.14039 0.92057
(0,2) 0.40450 -0.29389 0.80901
(1,1) 0.42532 0.0 0.85065
(2,0) 0.40450 0.29389 0.80901
(0,3) 0.57971 -0.42118 0.62533
(1,2) 0.63798 -0.15450 0.68819
(2,1) 0.63798 0.15450 0.68819
(3,0) 0.57971 0.42118 0.62533
(0,4) 0.68819 -0.50000 0.42532
(1,3) 0.77295 -0.28079 0.47771
(2,2) 0.80901 0.0 0.49999
(3,1) 0.77295 0.28079 0.47771
(4,0) 0.68819 0.50000 0.42532

To find the chord lengths, the distance between adjoining pairs of vertices must be found. Distance is
easily calculated by the distance formula; a simple walk through the projected mesh looking below-left,
below-right, and right will pick off all of the chords.

chord
Vertex Vertex
(* edgeLength)
(0,0) (0,1) 0.24079
(0,0) (1,0) 0.24079
(0,1) (0,2) 0.28397
(0,1) (1,1) 0.28011
(0,1) (1,0) 0.28079
(1,0) (1,1) 0.28011
(1,0) (2,0) 0.28397
(0,2) (0,3) 0.28397
(0,2) (1,2) 0.29755
(0,2) (1,1) 0.29755
(1,1) (1,2) 0.30901
(1,1) (2,1) 0.30901
(1,1) (2,0) 0.29755
(2,0) (2,1) 0.29755
(2,0) (3,0) 0.28397
(0,3) (0,4) 0.24079
(0,3) (1,3) 0.28079
(0,3) (1,2) 0.28011
(1,2) (1,3) 0.28011
(1,2) (2,2) 0.29755
(1,2) (2,1) 0.30901
(2,1) (2,2) 0.29755
(2,1) (3,1) 0.28011
(2,1) (3,0) 0.28011
(3,0) (3,1) 0.28079
(3,0) (4,0) 0.24079
(0,4) (1,3) 0.24079
(1,3) (2,2) 0.28397
(2,2) (3,1) 0.28397
(3,1) (4,0) 0.24079

Or, the chords may be collected in a bill of materials.

chord
Chords count
(* edgeLength)
(0,0)-(0,1) (0,0)-(1,0) (0,3)-(0,4) (3,0)-(4,0) (0,4)-(1,3) (3,1)-(4,0) 6 0.24079
(0,1)-(1,1) (1,0)-(1,1) (0,3)-(1,2) (1,2)-(1,3) (2,1)-(3,1) (2,1)-(3,0) 6 0.28011
(0,1)-(1,0) (0,3)-(1,3) (3,0)-(3,1) 3 0.28079
(0,1)-(0,2) (1,0)-(2,0) (0,2)-(0,3) (2,0)-(3,0) (1,3)-(2,2) (2,2)-(3,1) 6 0.28397
(0,2)-(1,2) (0,2)-(1,1) (1,1)-(2,0) (2,0)-(2,1) (1,2)-(2,2) (2,1)-(2,2) 6 0.29755
(1,1)-(1,2) (1,1)-(2,1) (1,2)-(2,1) 3 0.30901
Here are the first five tesselations for an icosahedral patch:

1-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.68819 -0.50000 0.42533
(1,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 1.00000
(0,0) (1,0) 1.00000
(0,1) (1,0) 1.00000

2-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.40451 -0.29389 0.80902
(1,0) 0.40451 0.29389 0.80902
(0,2) 0.68819 -0.50000 0.42533
(1,1) 0.80902 0.00000 0.50000
(2,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.51978
(0,0) (1,0) 0.51978
(0,1) (0,2) 0.51978
(0,1) (1,1) 0.58779
(0,1) (1,0) 0.58779
(1,0) (1,1) 0.58779
(1,0) (2,0) 0.51978
(0,2) (1,1) 0.51978
(1,1) (2,0) 0.51978

3-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.26413 -0.19190 0.89326
(1,0) 0.26413 0.19190 0.89326
(0,2) 0.52825 -0.38380 0.69149
(1,1) 0.57735 0.00000 0.75576
(2,0) 0.52825 0.38380 0.69149
(0,3) 0.68819 -0.50000 0.42533
(1,2) 0.79238 -0.19190 0.48972
(2,1) 0.79238 0.19190 0.48972
(3,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.33155
(0,0) (1,0) 0.33155
(0,1) (0,2) 0.38380
(0,1) (1,1) 0.39223
(0,1) (1,0) 0.38380
(1,0) (1,1) 0.39223
(1,0) (2,0) 0.38380
(0,2) (0,3) 0.33155
(0,2) (1,2) 0.38380
(0,2) (1,1) 0.39223
(1,1) (1,2) 0.39223
(1,1) (2,1) 0.39223
(1,1) (2,0) 0.39223
(2,0) (2,1) 0.38380
(2,0) (3,0) 0.33155
(0,3) (1,2) 0.33155
(1,2) (2,1) 0.38380
(2,1) (3,0) 0.33155

4-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.19324 -0.14040 0.92057
(1,0) 0.19324 0.14040 0.92057
(0,2) 0.40451 -0.29389 0.80902
(1,1) 0.42533 0.00000 0.85065
(2,0) 0.40451 0.29389 0.80902
(0,3) 0.57971 -0.42119 0.62533
(1,2) 0.63799 -0.15451 0.68819
(2,1) 0.63799 0.15451 0.68819
(3,0) 0.57971 0.42119 0.62533
(0,4) 0.68819 -0.50000 0.42533
(1,3) 0.77295 -0.28079 0.47771
(2,2) 0.80902 0.00000 0.50000
(3,1) 0.77295 0.28079 0.47771
(4,0) 0.68819 0.50000 0.42533
Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.24079
(0,0) (1,0) 0.24079
(0,1) (0,2) 0.28397
(0,1) (1,1) 0.28012
(0,1) (1,0) 0.28079
(1,0) (1,1) 0.28012
(1,0) (2,0) 0.28397
(0,2) (0,3) 0.28397
(0,2) (1,2) 0.29756
(0,2) (1,1) 0.29756
(1,1) (1,2) 0.30902
(1,1) (2,1) 0.30902
(1,1) (2,0) 0.29756
(2,0) (2,1) 0.29756
(2,0) (3,0) 0.28397
(0,3) (0,4) 0.24079
(0,3) (1,3) 0.28079
(0,3) (1,2) 0.28012
(1,2) (1,3) 0.28012
(1,2) (2,2) 0.29756
(1,2) (2,1) 0.30902
(2,1) (2,2) 0.29756
(2,1) (3,1) 0.28012
(2,1) (3,0) 0.28012
(3,0) (3,1) 0.28079
(3,0) (4,0) 0.24079
(0,4) (1,3) 0.24079
(1,3) (2,2) 0.28397
(2,2) (3,1) 0.28397
(3,1) (4,0) 0.24079

5-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.15171 -0.11022 0.93239
(1,0) 0.15171 0.11022 0.93239
(0,2) 0.32116 -0.23334 0.86424
(1,1) 0.33129 0.00000 0.89149
(2,0) 0.32116 0.23334 0.86424
(0,3) 0.48174 -0.35001 0.74157
(1,2) 0.51365 -0.12440 0.79069
(2,1) 0.51365 0.12440 0.79069
(3,0) 0.48174 0.35001 0.74157
(0,4) 0.60683 -0.44089 0.58470
(1,3) 0.66258 -0.24070 0.63841
(2,2) 0.68487 0.00000 0.65989
(3,1) 0.66258 0.24070 0.63841
(4,0) 0.60683 0.44089 0.58470
(0,5) 0.68819 -0.50000 0.42533
(1,4) 0.75854 -0.33067 0.46881
(2,3) 0.80291 -0.11667 0.49622
(3,2) 0.80291 0.11667 0.49622
(4,1) 0.75854 0.33067 0.46881
(5,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.18845
(0,0) (1,0) 0.18845
(0,1) (0,2) 0.22026
(0,1) (1,1) 0.21464
(0,1) (1,0) 0.22045
(1,0) (1,1) 0.21464
(1,0) (2,0) 0.22026
(0,2) (0,3) 0.23334
(0,2) (1,2) 0.23309
(0,2) (1,1) 0.23514
(1,1) (1,2) 0.24268
(1,1) (2,1) 0.24268
(1,1) (2,0) 0.23514
(2,0) (2,1) 0.23309
(2,0) (3,0) 0.23334
(0,3) (0,4) 0.22026
(0,3) (1,3) 0.23514
(0,3) (1,2) 0.23309
(1,2) (1,3) 0.24268
(1,2) (2,2) 0.24879
(1,2) (2,1) 0.24879
(2,1) (2,2) 0.24879
(2,1) (3,1) 0.24268
(2,1) (3,0) 0.23309
(3,0) (3,1) 0.23514
(3,0) (4,0) 0.22026
(0,4) (0,5) 0.18845
(0,4) (1,4) 0.22045
(0,4) (1,3) 0.21464
(1,3) (1,4) 0.21464
(1,3) (2,3) 0.23514
(1,3) (2,2) 0.24268
(2,2) (2,3) 0.23309
(2,2) (3,2) 0.23309
(2,2) (3,1) 0.24268
(3,1) (3,2) 0.23514
(3,1) (4,1) 0.21464
(3,1) (4,0) 0.21464
(4,0) (4,1) 0.22045
(4,0) (5,0) 0.18845
(0,5) (1,4) 0.18845
(1,4) (2,3) 0.22026
(2,3) (3,2) 0.23334
(3,2) (4,1) 0.22026
(4,1) (5,0) 0.18845

and here's a quick and dirty java app to generate the chords for an arbitrary frequency.

Icos.java

// Icos.java Copyright 1998 David J. Anderson

// computes the chord lengths for an n-frequency icosahedral geodesic patch

// to compile: javac Icos.java

// to execute: java Icos n s


// where n is the frequency and s is the length of a side of the icosahedron
// outputs an html document containing the vertex and chord information

import java.lang.Math;
import java.util.Hashtable;

class Rounding
{
public static String toString (double d, int place)
{
if (place <= 0)
return ""+(int)d;
String s = "";
if (d < 0)
{
s += "-";
d = -d;
}
d += 0.5*Math.pow(10,-place);
if (d > 1)
{
int i = (int)d;
s += i;
d -= i;
}
else
s += "0";
if (d > 0)
{
d += 1.0;
String f = ""+(int)(d*Math.pow(10,place));
s += "."+f.substring(1);
}
return s;
}
}

class SPoint // Spherical coordinate point


{
public double radius;
public double theta;
public double phi;

public SPoint (double radius, double theta, double phi)


{
this.radius = radius;
this.theta = theta;
this.phi = phi;
}

public CPoint cPoint ()


{
double x;
double y;
double z;
x = radius*Math.cos(theta)*Math.sin(phi);
y = radius*Math.sin(theta)*Math.sin(phi);
z = radius*Math.cos(phi);
return new CPoint(x,y,z);
}
}

class CPoint // Cartesian coordinate point


{
public double x;
public double y;
public double z;

public CPoint (double x, double y, double z)


{
this.x = x;
this.y = y;
this.z = z;
}

public double distanceTo (CPoint cPoint)


{
double xdiff = cPoint.x-x;
double ydiff = cPoint.y-y;
double zdiff = cPoint.z-z;
return Math.sqrt((xdiff*xdiff)+(ydiff*ydiff)+(zdiff*zdiff));
}

public SPoint sPoint ()


{
double radius;
double theta;
double phi;
radius = distanceTo(Icos.origin);
theta = (x == 0.0)? 0.0 : Math.atan2(y,x);
phi = Math.acos(z/radius);
return new SPoint(radius,theta,phi);
}
}

public class Icos // the icosahedron chord determiner


{
private int n;
private double s;
private double d;
private Hashtable cPoints = new Hashtable();

public static final CPoint origin = new CPoint(0.0,0.0,0.0);

public Icos (int n, double s)


{
this.n = n;
this.s = s;
d = s*0.9510565162951534;
}

public String getLabel (int row, int column)


{
return "("+row+","+column+")";
}

public void mesh ()


{
CPoint topCorner = (new SPoint(d,0.0,0.0)).cPoint();
CPoint leftCorner =
(new SPoint(d,-Math.PI/5.0,1.107148717940909)).cPoint();
CPoint rightCorner =
(new SPoint(d,Math.PI/5.0,1.107148717940909)).cPoint();
double incX = (leftCorner.x-topCorner.x)/n;
double incY = (rightCorner.y-leftCorner.y)/n;
double incZ = (leftCorner.z-topCorner.z)/n;
double x;
double y;
double z;
String label;
for (int i = 0; i <= n; i++)
{
z = topCorner.z+(incZ*i);
x = topCorner.x+(incX*i);
for (int j = 0; j <= i; j++)
{
y = -((incY*i)/2.0)+(incY*j);
label = getLabel(j,i-j);
cPoints.put(label,new CPoint(x,y,z));
}
}
}

public void project ()


{
String label;
SPoint sPoint;
CPoint cPoint;

System.out.println();
System.out.println("<H2>Circumscribed Spherical Projection</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println("<TR><TD><B>Vertex<TD><B>x<TD><B>y<TD><B>z");

for (int i = 0; i <= n; i++)


for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
sPoint = ((CPoint)cPoints.get(label)).sPoint();
sPoint.radius = d;
cPoint = sPoint.cPoint();
cPoints.put(label,cPoint);

System.out.println
("<TR><TD>"+label+"<TD>"+Rounding.toString(cPoint.x,5)+"<TD>"+
Rounding.toString(cPoint.y,5)+"<TD>"+Rounding.toString(cPoint.z,5));
}

System.out.println("</TABLE></CENTER>");
}

public String getBelowLeftLabel (int row, int column)


{
int destinationColumn = column+1;
if (row+destinationColumn > n)
return null;
return getLabel(row,destinationColumn);
}

public String getBelowRightLabel (int row, int column)


{
int destinationRow = row+1;
if (destinationRow+column > n)
return null;
return getLabel(destinationRow,column);
}

public String getRightLabel (int row, int column)


{
int destinationRow = row+1;
int destinationColumn = column-1;
if ((destinationRow > n)||(destinationColumn < 0))
return null;
return getLabel(destinationRow,destinationColumn);
}

public void chords ()


{
String label;
String belowLeftLabel;
String belowRightLabel;
String rightLabel;
CPoint cPoint;

System.out.println();
System.out.println("<H2>Chord Lengths</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println("<TR><TD><B>Vertex<TD><B>Vertex<TD><B>chord");

for (int i = 0; i <= n; i++)


for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(j,i-j);

if (belowLeftLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowLeftLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowLeftLabel)),5));

belowRightLabel = getBelowRightLabel(j,i-j);

if (belowRightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowRightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowRightLabel)),5));

rightLabel = getRightLabel(j,i-j);

if (rightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+rightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(rightLabel)),5));
}

System.out.println("</TABLE></CENTER>");
}

public static void main (String[] arguments)


{
int n = Integer.valueOf(arguments[0]).intValue();
double s = Double.valueOf(arguments[1]).doubleValue();
System.out.println
("<TITLE>Calculations for a "+n+"-frequency Icosahedral Geodesic
Patch</TITLE>");
Icos icos = new Icos(n,s);
icos.mesh();
icos.project();
icos.chords();
}
}
Calculating the Fastening Angles between
Subfaces of an n-frequency Icosahedral Geodesic
Dome
David Anderson
January 1998

When building a geodesic structure there are a many ways to go. If the intention is to
do something human-scaled, it all boils down whether you want to go with traditional
or non-traditional materials. For instance, how do you fasten struts together in a 5-
frequency geodesic without a special hub? A set of pre-manufactured aluminum joints
is wonderful - but where do you get them? Although these kinds of special parts have
their advantages, for me, being able to just go down to the local hardware store or
lumber yard is a bigger win. I don't want to have to worry about ordering special parts
for something I'm building when I could take a short drive instead. I don't know, I'm
just funny that way.

Assuming a human-scaled structure, the icosahedral geodesic can be framed by


joining prefabricated triangular subfaces made of standard materials whose edges are extended and angled
in such a way that they lie flat against each other and can be fastened together. I call these edge angles
fastening angles; they vary according to the position of the subface on the geodesic patch.

With the determination of chord lengths completed, I proceeded onward to figure out the geometry of the
subfaces making up a geodesic.

Using the reference vertex layout for a geodesic patch (in this case, 4-frequency)
The various subfaces of the patch may be found by walking the mesh. The first three coefficients for the
equation of the plane (Ax+By+Cz-D=0) the subface lies in are also calculated (which are the
unnormalized direction cosines of the normal to the plane.)

Chords Direction Coefficients


Vertices
(* edgeLength) ABC
(0,0) (0,1) (1,0) 0.24079 0.28079 0.24079 0.00855 0.0 0.05425
(0,1) (0,2) (1,1) 0.28397 0.29755 0.28011 0.02639 -0.01111 0.06528
(0,1) (1,1) (1,0) 0.28011 0.28011 0.28079 0.01963 0.0 0.06516
(1,0) (1,1) (2,0) 0.28011 0.29755 0.28397 0.02639 0.01111 0.06528
(0,2) (0,3) (1,2) 0.28397 0.28011 0.29755 0.04098 -0.02171 0.05414
(0,2) (1,2) (1,1) 0.29755 0.30901 0.29755 0.04131 -0.01223 0.06571
(1,1) (1,2) (2,1) 0.30901 0.30901 0.30901 0.05020 0.0 0.06571
(1,1) (2,1) (2,0) 0.30901 0.29755 0.29755 0.04131 0.01223 0.06571
(2,0) (2,1) (3,0) 0.29755 0.28011 0.28397 0.04098 0.02171 0.05414
(0,3) (0,4) (1,3) 0.24079 0.24079 0.28079 0.03971 -0.02263 0.03045
(0,3) (1,3) (1,2) 0.28079 0.28011 0.28011 0.04819 -0.02074 0.04335
(1,2) (1,3) (2,2) 0.28011 0.28397 0.29755 0.05628 -0.01059 0.04245
(1,2) (2,2) (2,1) 0.29755 0.29755 0.30901 0.05815 0.0 0.05285
(2,1) (2,2) (3,1) 0.29755 0.28397 0.28011 0.05628 0.01059 0.04245
(2,1) (3,1) (3,0) 0.28011 0.28079 0.28011 0.04819 0.02074 0.04335
(3,0) (3,1) (4,0) 0.28079 0.24079 0.24079 0.03971 0.02263 0.03045

Here the vertices (and chord lengths) of the subface are calculated in a counter-clockwise direction. By
inspection it can be seen that rotational symmetry is evident with respect to the placement of a subface in
the mesh. However, moving from the center of the mesh outwards, some subfaces are mirror images of
others. If a patch is being constructed with different inside and outside materials, the handedness of the
subface matters. In the case of edge extensions for fastening, the handedness must be observed.

Rather than calculate the dihedral angle along and edge between subfaces, the dihedral angle between the
subface and the plane including the edge and the icosahedral center (an edge plane) is calculated (the
fastening angle.) Two subfaces which share a common edge are fastened together along their edge plane
when each is angled by its fastening angle.

The fastening angle is calculated by computing the direction coefficients of the edge plane and then
determining the dihedral angle between them.
Fastening Angle
Vertices Edge
radians (degrees)
(0,0) (0,1) 1.47908 (84.74502)
(0,0) (0,1) (1,0) (0,1) (1,0) 1.52035 (87.10942)
(1,0) (0,0) 1.47908 (84.74502)
(0,1) (0,2) 1.47922 (84.75287)
(0,1) (0,2) (1,1) (0,2) (1,1) 1.49233 (85.50421)
(1,1) (0,1) 1.47593 (84.56438)
(0,1) (1,1) 1.48445 (85.05278)
(0,1) (1,1) (1,0) (1,1) (1,0) 1.48445 (85.05278)
(1,0) (0,1) 1.48507 (85.08838)
(1,0) (1,1) 1.47593 (84.56438)
(1,0) (1,1) (2,0) (1,1) (2,0) 1.49233 (85.50421)
(2,0) (1,0) 1.47922 (84.75287)
(0,2) (0,3) 1.47922 (84.75287)
(0,2) (0,3) (1,2) (0,3) (1,2) 1.47593 (84.56438)
(1,2) (0,2) 1.49233 (85.50421)
(0,2) (1,2) 1.47441 (84.47770)
(0,2) (1,2) (1,1) (1,2) (1,1) 1.48522 (85.09681)
(1,1) (0,2) 1.47441 (84.47770)
(1,1) (1,2) 1.47559 (84.54528)
(1,1) (1,2) (2,1) (1,2) (2,1) 1.47559 (84.54528)
(2,1) (1,1) 1.47559 (84.54528)
(1,1) (2,1) 1.48522 (85.09681)
(1,1) (2,1) (2,0) (2,1) (2,0) 1.47441 (84.47770)
(2,0) (1,1) 1.47441 (84.47770)
(2,0) (2,1) 1.49233 (85.50421)
(2,0) (2,1) (3,0) (2,1) (3,0) 1.47593 (84.56438)
(3,0) (2,0) 1.47922 (84.75287)
(0,3) (0,4) 1.47908 (84.74502)
(0,3) (0,4) (1,3)
(0,4) (1,3) 1.47908 (84.74502)
(1,3) (0,3) 1.52035 (87.10942)
(0,3) (1,3) 1.48507 (85.08838)
(0,3) (1,3) (1,2) (1,3) (1,2) 1.48445 (85.05278)
(1,2) (0,3) 1.48445 (85.05278)
(1,2) (1,3) 1.47593 (84.56438)
(1,2) (1,3) (2,2) (1,3) (2,2) 1.47922 (84.75287)
(2,2) (1,2) 1.49233 (85.50421)
(1,2) (2,2) 1.47441 (84.47770)
(1,2) (2,2) (2,1) (2,2) (2,1) 1.47441 (84.47770)
(2,1) (1,2) 1.48522 (85.09681)
(2,1) (2,2) 1.49233 (85.50421)
(2,1) (2,2) (3,1) (2,2) (3,1) 1.47922 (84.75287)
(3,1) (2,1) 1.47593 (84.56438)
(2,1) (3,1) 1.48445 (85.05278)
(2,1) (3,1) (3,0) (3,1) (3,0) 1.48507 (85.08838)
(3,0) (2,1) 1.48445 (85.05278)
(3,0) (3,1) 1.52035 (87.10942)
(3,0) (3,1) (4,0) (3,1) (4,0) 1.47908 (84.74502)
(4,0) (3,0) 1.47908 (84.74502)

Note that the dihedral angle between the two subfaces is the sum of their common edge's two fastening
angles.

Here are the fastening angle calculations for the first five tesselations for an icosahedral patch:

1-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.68819 -0.50000 0.42533
(1,0) 0.68819 0.50000 0.42533
Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 1.00000
(0,0) (1,0) 1.00000
(0,1) (1,0) 1.00000

Subface Definition
Chords
Vertices Planar Coefficients
(* edgeLength)
(0,0) (0,1) (1,0) 1.00000 1.00000 1.00000 0.52573 0.00000 0.68819

Fastening Angle Determination


Fastening Angle
Vertices Edge
radians (degrees)
(0,0) (0,1) 1.20593 (69.09484)
(0,0) (0,1) (1,0) (0,1) (1,0) 1.20593 (69.09484)
(1,0) (0,0) 1.20593 (69.09484)

2-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.40451 -0.29389 0.80902
(1,0) 0.40451 0.29389 0.80902
(0,2) 0.68819 -0.50000 0.42533
(1,1) 0.80902 0.00000 0.50000
(2,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.51978
(0,0) (1,0) 0.51978
(0,1) (0,2) 0.51978
(0,1) (1,1) 0.58779
(0,1) (1,0) 0.58779
(1,0) (1,1) 0.58779
(1,0) (2,0) 0.51978
(0,2) (1,1) 0.51978
(1,1) (2,0) 0.51978

Subface Definition
Chords
Vertices Planar Coefficients
(* edgeLength)
(0,0) (0,1) (1,0) 0.51978 0.58779 0.51978 0.08349 0.00000 0.23776
(0,1) (0,2) (1,1) 0.51978 0.51978 0.58779 0.17645 -0.06754 0.16674
(0,1) (1,1) (1,0) 0.58779 0.58779 0.58779 0.18164 0.00000 0.23776
(1,0) (1,1) (2,0) 0.58779 0.51978 0.51978 0.17645 0.06754 0.16674

Fastening Angle Determination


Fastening Angle
Vertices Edge
radians (degrees)
(0,0) (0,1) 1.37481 (78.77054)
(0,0) (0,1) (1,0) (0,1) (1,0) 1.44484 (82.78321)
(1,0) (0,0) 1.37481 (78.77054)
(0,1) (0,2) 1.37481 (78.77054)
(0,1) (0,2) (1,1) (0,2) (1,1) 1.37481 (78.77054)
(1,1) (0,1) 1.44484 (82.78321)
(0,1) (1,1) 1.38209 (79.18768)
(0,1) (1,1) (1,0) (1,1) (1,0) 1.38209 (79.18768)
(1,0) (0,1) 1.38209 (79.18768)
(1,0) (1,1) 1.44484 (82.78321)
(1,0) (1,1) (2,0) (1,1) (2,0) 1.37481 (78.77054)
(2,0) (1,0) 1.37481 (78.77054)
3-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.26413 -0.19190 0.89326
(1,0) 0.26413 0.19190 0.89326
(0,2) 0.52825 -0.38380 0.69149
(1,1) 0.57735 0.00000 0.75576
(2,0) 0.52825 0.38380 0.69149
(0,3) 0.68819 -0.50000 0.42533
(1,2) 0.79238 -0.19190 0.48972
(2,1) 0.79238 0.19190 0.48972
(3,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.33155
(0,0) (1,0) 0.33155
(0,1) (0,2) 0.38380
(0,1) (1,1) 0.39223
(0,1) (1,0) 0.38380
(1,0) (1,1) 0.39223
(1,0) (2,0) 0.38380
(0,2) (0,3) 0.33155
(0,2) (1,2) 0.38380
(0,2) (1,1) 0.39223
(1,1) (1,2) 0.39223
(1,1) (2,1) 0.39223
(1,1) (2,0) 0.39223
(2,0) (2,1) 0.38380
(2,0) (3,0) 0.33155
(0,3) (1,2) 0.33155
(1,2) (2,1) 0.38380
(2,1) (3,0) 0.33155

Subface Definition
Chords
Vertices Planar Coefficients
(* edgeLength)
(0,0) (0,1) (1,0) 0.33155 0.38380 0.33155 0.02218 0.00000 0.10137
(0,1) (0,2) (1,1) 0.38380 0.39223 0.39223 0.06511 -0.02688 0.11079
(0,1) (1,1) (1,0) 0.39223 0.39223 0.38380 0.05277 0.00000 0.12021
(1,0) (1,1) (2,0) 0.39223 0.39223 0.38380 0.06511 0.02688 0.11079
(0,2) (0,3) (1,2) 0.33155 0.33155 0.38380 0.07452 -0.03803 0.06138
(0,2) (1,2) (1,1) 0.38380 0.39223 0.39223 0.08977 -0.02688 0.09195
(1,1) (1,2) (2,1) 0.39223 0.38380 0.39223 0.10211 0.00000 0.08253
(1,1) (2,1) (2,0) 0.39223 0.38380 0.39223 0.08977 0.02688 0.09195
(2,0) (2,1) (3,0) 0.38380 0.33155 0.33155 0.07452 0.03803 0.06138

Fastening Angle Determination


Fastening Angle
Vertices Edge
radians (degrees)
(0,0) (0,1) 1.44482 (82.78237)
(0,0) (0,1) (1,0) (0,1) (1,0) 1.49871 (85.86993)
(1,0) (0,0) 1.44482 (82.78237)
(0,1) (0,2) 1.44463 (82.77114)
(0,1) (0,2) (1,1) (0,2) (1,1) 1.45230 (83.21072)
(1,1) (0,1) 1.45230 (83.21072)
(0,1) (1,1) 1.45230 (83.21072)
(0,1) (1,1) (1,0) (1,1) (1,0) 1.45230 (83.21072)
(1,0) (0,1) 1.44463 (82.77114)
(1,0) (1,1) 1.45230 (83.21072)
(1,0) (1,1) (2,0) (1,1) (2,0) 1.45230 (83.21072)
(2,0) (1,0) 1.44463 (82.77114)
(0,2) (0,3) 1.44482 (82.78237)
(0,2) (0,3) (1,2) (0,3) (1,2) 1.44482 (82.78237)
(1,2) (0,2) 1.49871 (85.86993)
(0,2) (1,2) 1.44463 (82.77114)
(0,2) (1,2) (1,1) (1,2) (1,1) 1.45230 (83.21072)
(1,1) (0,2) 1.45230 (83.21072)
(1,1) (1,2) 1.45230 (83.21072)
(1,1) (1,2) (2,1) (1,2) (2,1) 1.44463 (82.77114)
(2,1) (1,1) 1.45230 (83.21072)
(1,1) (2,1) 1.45230 (83.21072)
(1,1) (2,1) (2,0) (2,1) (2,0) 1.44463 (82.77114)
(2,0) (1,1) 1.45230 (83.21072)
(2,0) (2,1) 1.49871 (85.86993)
(2,0) (2,1) (3,0) (2,1) (3,0) 1.44482 (82.78237)
(3,0) (2,0) 1.44482 (82.78237)

4-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.19324 -0.14040 0.92057
(1,0) 0.19324 0.14040 0.92057
(0,2) 0.40451 -0.29389 0.80902
(1,1) 0.42533 0.00000 0.85065
(2,0) 0.40451 0.29389 0.80902
(0,3) 0.57971 -0.42119 0.62533
(1,2) 0.63799 -0.15451 0.68819
(2,1) 0.63799 0.15451 0.68819
(3,0) 0.57971 0.42119 0.62533
(0,4) 0.68819 -0.50000 0.42533
(1,3) 0.77295 -0.28079 0.47771
(2,2) 0.80902 0.00000 0.50000
(3,1) 0.77295 0.28079 0.47771
(4,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.24079
(0,0) (1,0) 0.24079
(0,1) (0,2) 0.28397
(0,1) (1,1) 0.28012
(0,1) (1,0) 0.28079
(1,0) (1,1) 0.28012
(1,0) (2,0) 0.28397
(0,2) (0,3) 0.28397
(0,2) (1,2) 0.29756
(0,2) (1,1) 0.29756
(1,1) (1,2) 0.30902
(1,1) (2,1) 0.30902
(1,1) (2,0) 0.29756
(2,0) (2,1) 0.29756
(2,0) (3,0) 0.28397
(0,3) (0,4) 0.24079
(0,3) (1,3) 0.28079
(0,3) (1,2) 0.28012
(1,2) (1,3) 0.28012
(1,2) (2,2) 0.29756
(1,2) (2,1) 0.30902
(2,1) (2,2) 0.29756
(2,1) (3,1) 0.28012
(2,1) (3,0) 0.28012
(3,0) (3,1) 0.28079
(3,0) (4,0) 0.24079
(0,4) (1,3) 0.24079
(1,3) (2,2) 0.28397
(2,2) (3,1) 0.28397
(3,1) (4,0) 0.24079

Subface Definition
Chords
Vertices Planar Coefficients
(* edgeLength)
(0,0) (0,1) (1,0) 0.24079 0.28079 0.24079 0.00856 0.00000 0.05426
(0,1) (0,2) (1,1) 0.28397 0.29756 0.28012 0.02640 -0.01112 0.06529
(0,1) (1,1) (1,0) 0.28012 0.28012 0.28079 0.01963 0.00000 0.06517
(1,0) (1,1) (2,0) 0.28012 0.29756 0.28397 0.02640 0.01112 0.06529
(0,2) (0,3) (1,2) 0.28397 0.28012 0.29756 0.04098 -0.02172 0.05414
(0,2) (1,2) (1,1) 0.29756 0.30902 0.29756 0.04131 -0.01224 0.06572
(1,1) (1,2) (2,1) 0.30902 0.30902 0.30902 0.05020 0.00000 0.06572
(1,1) (2,1) (2,0) 0.30902 0.29756 0.29756 0.04131 0.01224 0.06572
(2,0) (2,1) (3,0) 0.29756 0.28012 0.28397 0.04098 0.02172 0.05414
(0,3) (0,4) (1,3) 0.24079 0.24079 0.28079 0.03971 -0.02264 0.03046
(0,3) (1,3) (1,2) 0.28079 0.28012 0.28012 0.04819 -0.02075 0.04335
(1,2) (1,3) (2,2) 0.28012 0.28397 0.29756 0.05629 -0.01060 0.04245
(1,2) (2,2) (2,1) 0.29756 0.29756 0.30902 0.05815 0.00000 0.05285
(2,1) (2,2) (3,1) 0.29756 0.28397 0.28012 0.05629 0.01060 0.04245
(2,1) (3,1) (3,0) 0.28012 0.28079 0.28012 0.04819 0.02075 0.04335
(3,0) (3,1) (4,0) 0.28079 0.24079 0.24079 0.03971 0.02264 0.03046

Fastening Angle Determination


Fastening Angle
Vertices Edge
radians (degrees)
(0,0) (0,1) 1.47908 (84.74502)
(0,0) (0,1) (1,0)
(0,1) (1,0) 1.52035 (87.10942)
(1,0) (0,0) 1.47908 (84.74502)
(0,1) (0,2) 1.47922 (84.75287)
(0,1) (0,2) (1,1) (0,2) (1,1) 1.49233 (85.50421)
(1,1) (0,1) 1.47593 (84.56438)
(0,1) (1,1) 1.48445 (85.05278)
(0,1) (1,1) (1,0) (1,1) (1,0) 1.48445 (85.05278)
(1,0) (0,1) 1.48507 (85.08838)
(1,0) (1,1) 1.47593 (84.56438)
(1,0) (1,1) (2,0) (1,1) (2,0) 1.49233 (85.50421)
(2,0) (1,0) 1.47922 (84.75287)
(0,2) (0,3) 1.47922 (84.75287)
(0,2) (0,3) (1,2) (0,3) (1,2) 1.47593 (84.56438)
(1,2) (0,2) 1.49233 (85.50421)
(0,2) (1,2) 1.47441 (84.47770)
(0,2) (1,2) (1,1) (1,2) (1,1) 1.48522 (85.09681)
(1,1) (0,2) 1.47441 (84.47770)
(1,1) (1,2) 1.47559 (84.54528)
(1,1) (1,2) (2,1) (1,2) (2,1) 1.47559 (84.54528)
(2,1) (1,1) 1.47559 (84.54528)
(1,1) (2,1) 1.48522 (85.09681)
(1,1) (2,1) (2,0) (2,1) (2,0) 1.47441 (84.47770)
(2,0) (1,1) 1.47441 (84.47770)
(2,0) (2,1) 1.49233 (85.50421)
(2,0) (2,1) (3,0) (2,1) (3,0) 1.47593 (84.56438)
(3,0) (2,0) 1.47922 (84.75287)
(0,3) (0,4) 1.47908 (84.74502)
(0,3) (0,4) (1,3) (0,4) (1,3) 1.47908 (84.74502)
(1,3) (0,3) 1.52035 (87.10942)
(0,3) (1,3) 1.48507 (85.08838)
(0,3) (1,3) (1,2) (1,3) (1,2) 1.48445 (85.05278)
(1,2) (0,3) 1.48445 (85.05278)
(1,2) (1,3) 1.47593 (84.56438)
(1,2) (1,3) (2,2) (1,3) (2,2) 1.47922 (84.75287)
(2,2) (1,2) 1.49233 (85.50421)
(1,2) (2,2) 1.47441 (84.47770)
(1,2) (2,2) (2,1) (2,2) (2,1) 1.47441 (84.47770)
(2,1) (1,2) 1.48522 (85.09681)
(2,1) (2,2) 1.49233 (85.50421)
(2,1) (2,2) (3,1) (2,2) (3,1) 1.47922 (84.75287)
(3,1) (2,1) 1.47593 (84.56438)
(2,1) (3,1) 1.48445 (85.05278)
(2,1) (3,1) (3,0) (3,1) (3,0) 1.48507 (85.08838)
(3,0) (2,1) 1.48445 (85.05278)
(3,0) (3,1) 1.52035 (87.10942)
(3,0) (3,1) (4,0) (3,1) (4,0) 1.47908 (84.74502)
(4,0) (3,0) 1.47908 (84.74502)

5-frequency

Circumscribed Spherical Projection


Vertex x y z
(0,0) 0.00000 0.00000 0.95106
(0,1) 0.15171 -0.11022 0.93239
(1,0) 0.15171 0.11022 0.93239
(0,2) 0.32116 -0.23334 0.86424
(1,1) 0.33129 0.00000 0.89149
(2,0) 0.32116 0.23334 0.86424
(0,3) 0.48174 -0.35001 0.74157
(1,2) 0.51365 -0.12440 0.79069
(2,1) 0.51365 0.12440 0.79069
(3,0) 0.48174 0.35001 0.74157
(0,4) 0.60683 -0.44089 0.58470
(1,3) 0.66258 -0.24070 0.63841
(2,2) 0.68487 0.00000 0.65989
(3,1) 0.66258 0.24070 0.63841
(4,0) 0.60683 0.44089 0.58470
(0,5) 0.68819 -0.50000 0.42533
(1,4) 0.75854 -0.33067 0.46881
(2,3) 0.80291 -0.11667 0.49622
(3,2) 0.80291 0.11667 0.49622
(4,1) 0.75854 0.33067 0.46881
(5,0) 0.68819 0.50000 0.42533

Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.18845
(0,0) (1,0) 0.18845
(0,1) (0,2) 0.22026
(0,1) (1,1) 0.21464
(0,1) (1,0) 0.22045
(1,0) (1,1) 0.21464
(1,0) (2,0) 0.22026
(0,2) (0,3) 0.23334
(0,2) (1,2) 0.23309
(0,2) (1,1) 0.23514
(1,1) (1,2) 0.24268
(1,1) (2,1) 0.24268
(1,1) (2,0) 0.23514
(2,0) (2,1) 0.23309
(2,0) (3,0) 0.23334
(0,3) (0,4) 0.22026
(0,3) (1,3) 0.23514
(0,3) (1,2) 0.23309
(1,2) (1,3) 0.24268
(1,2) (2,2) 0.24879
(1,2) (2,1) 0.24879
(2,1) (2,2) 0.24879
(2,1) (3,1) 0.24268
(2,1) (3,0) 0.23309
(3,0) (3,1) 0.23514
(3,0) (4,0) 0.22026
(0,4) (0,5) 0.18845
(0,4) (1,4) 0.22045
(0,4) (1,3) 0.21464
(1,3) (1,4) 0.21464
(1,3) (2,3) 0.23514
(1,3) (2,2) 0.24268
(2,2) (2,3) 0.23309
(2,2) (3,2) 0.23309
(2,2) (3,1) 0.24268
(3,1) (3,2) 0.23514
(3,1) (4,1) 0.21464
(3,1) (4,0) 0.21464
(4,0) (4,1) 0.22045
(4,0) (5,0) 0.18845
(0,5) (1,4) 0.18845
(1,4) (2,3) 0.22026
(2,3) (3,2) 0.23334
(3,2) (4,1) 0.22026
(4,1) (5,0) 0.18845

Subface Definition
Chords
Vertices Planar Coefficients
(* edgeLength)
(0,0) (0,1) (1,0) 0.18845 0.22045 0.18845 0.00412 0.00000 0.03344
(0,1) (0,2) (1,1) 0.22026 0.23514 0.21464 0.01255 -0.00531 0.04079
(0,1) (1,1) (1,0) 0.21464 0.21464 0.22045 0.00902 0.00000 0.03959
(1,0) (1,1) (2,0) 0.21464 0.23514 0.22026 0.01255 0.00531 0.04079
(0,2) (0,3) (1,2) 0.23334 0.23309 0.23309 0.02195 -0.01180 0.03995
(0,2) (1,2) (1,1) 0.23309 0.24268 0.23514 0.02013 -0.00599 0.04381
(1,1) (1,2) (2,1) 0.24268 0.24879 0.24268 0.02508 0.00000 0.04537
(1,1) (2,1) (2,0) 0.24268 0.23309 0.23514 0.02013 0.00599 0.04381
(2,0) (2,1) (3,0) 0.23309 0.23309 0.23334 0.02195 0.01180 0.03995
(0,3) (0,4) (1,3) 0.22026 0.21464 0.23514 0.02652 -0.01546 0.03011
(0,3) (1,3) (1,2) 0.23514 0.24268 0.23309 0.02864 -0.01217 0.03731
(1,2) (1,3) (2,2) 0.24268 0.24268 0.24879 0.03416 -0.00659 0.03844
(1,2) (2,2) (2,1) 0.24879 0.24879 0.24879 0.03254 0.00000 0.04260
(2,1) (2,2) (3,1) 0.24879 0.24268 0.24268 0.03416 0.00659 0.03844
(2,1) (3,1) (3,0) 0.24268 0.23514 0.23309 0.02864 0.01217 0.03731
(3,0) (3,1) (4,0) 0.23514 0.21464 0.22026 0.02652 0.01546 0.03011
(0,4) (0,5) (1,4) 0.18845 0.18845 0.22045 0.02442 -0.01475 0.01793
(0,4) (1,4) (1,3) 0.22045 0.21464 0.21464 0.02912 -0.01461 0.02423
(1,3) (1,4) (2,3) 0.21464 0.22026 0.23514 0.03383 -0.01016 0.02453
(1,3) (2,3) (2,2) 0.23514 0.23309 0.24268 0.03689 -0.00618 0.03101
(2,2) (2,3) (3,2) 0.23309 0.23334 0.23309 0.03819 0.00000 0.02754
(2,2) (3,2) (3,1) 0.23309 0.23514 0.24268 0.03689 0.00618 0.03101
(3,1) (3,2) (4,1) 0.23514 0.22026 0.21464 0.03383 0.01016 0.02453
(3,1) (4,1) (4,0) 0.21464 0.22045 0.21464 0.02912 0.01461 0.02423
(4,0) (4,1) (5,0) 0.22045 0.18845 0.18845 0.02442 0.01475 0.01793

Fastening Angle Determination


Fastening Angle
Vertices Edge
radians (degrees)
(0,0) (0,1) 1.49894 (85.88288)
(0,0) (0,1) (1,0) (0,1) (1,0) 1.53195 (87.77434)
(1,0) (0,0) 1.49894 (85.88288)
(0,1) (0,2) (1,1) (0,1) (0,2) 1.49910 (85.89196)
(0,2) (1,1) 1.51385 (86.73705)
(1,1) (0,1) 1.49448 (85.62737)
(0,1) (1,1) 1.50278 (86.10282)
(0,1) (1,1) (1,0) (1,1) (1,0) 1.50278 (86.10282)
(1,0) (0,1) 1.50819 (86.41266)
(1,0) (1,1) 1.49448 (85.62737)
(1,0) (1,1) (2,0) (1,1) (2,0) 1.51385 (86.73705)
(2,0) (1,0) 1.49910 (85.89196)
(0,2) (0,3) 1.49957 (85.91926)
(0,2) (0,3) (1,2) (0,3) (1,2) 1.49935 (85.90625)
(1,2) (0,2) 1.49935 (85.90625)
(0,2) (1,2) 1.49467 (85.63830)
(0,2) (1,2) (1,1) (1,2) (1,1) 1.50359 (86.14942)
(1,1) (0,2) 1.49646 (85.74076)
(1,1) (1,2) 1.49393 (85.59562)
(1,1) (1,2) (2,1) (1,2) (2,1) 1.49962 (85.92203)
(2,1) (1,1) 1.49393 (85.59562)
(1,1) (2,1) 1.50359 (86.14942)
(1,1) (2,1) (2,0) (2,1) (2,0) 1.49467 (85.63830)
(2,0) (1,1) 1.49646 (85.74076)
(2,0) (2,1) 1.49935 (85.90625)
(2,0) (2,1) (3,0) (2,1) (3,0) 1.49935 (85.90625)
(3,0) (2,0) 1.49957 (85.91926)
(0,3) (0,4) 1.49910 (85.89196)
(0,3) (0,4) (1,3) (0,4) (1,3) 1.49448 (85.62737)
(1,3) (0,3) 1.51385 (86.73705)
(0,3) (1,3) 1.49646 (85.74076)
(0,3) (1,3) (1,2) (1,3) (1,2) 1.50359 (86.14942)
(1,2) (0,3) 1.49467 (85.63830)
(1,2) (1,3) 1.49393 (85.59562)
(1,2) (1,3) (2,2)
(1,3) (2,2) 1.49393 (85.59562)
(2,2) (1,2) 1.49962 (85.92203)
(1,2) (2,2) 1.49455 (85.63148)
(1,2) (2,2) (2,1) (2,2) (2,1) 1.49455 (85.63148)
(2,1) (1,2) 1.49455 (85.63148)
(2,1) (2,2) 1.49962 (85.92203)
(2,1) (2,2) (3,1) (2,2) (3,1) 1.49393 (85.59562)
(3,1) (2,1) 1.49393 (85.59562)
(2,1) (3,1) 1.50359 (86.14942)
(2,1) (3,1) (3,0) (3,1) (3,0) 1.49646 (85.74076)
(3,0) (2,1) 1.49467 (85.63830)
(3,0) (3,1) 1.51385 (86.73705)
(3,0) (3,1) (4,0) (3,1) (4,0) 1.49448 (85.62737)
(4,0) (3,0) 1.49910 (85.89196)
(0,4) (0,5) 1.49894 (85.88288)
(0,4) (0,5) (1,4) (0,5) (1,4) 1.49894 (85.88288)
(1,4) (0,4) 1.53195 (87.77434)
(0,4) (1,4) 1.50819 (86.41266)
(0,4) (1,4) (1,3) (1,4) (1,3) 1.50278 (86.10282)
(1,3) (0,4) 1.50278 (86.10282)
(1,3) (1,4) 1.49448 (85.62737)
(1,3) (1,4) (2,3) (1,4) (2,3) 1.49910 (85.89196)
(2,3) (1,3) 1.51385 (86.73705)
(1,3) (2,3) 1.49646 (85.74076)
(1,3) (2,3) (2,2) (2,3) (2,2) 1.49467 (85.63830)
(2,2) (1,3) 1.50359 (86.14942)
(2,2) (2,3) 1.49935 (85.90625)
(2,2) (2,3) (3,2) (2,3) (3,2) 1.49957 (85.91926)
(3,2) (2,2) 1.49935 (85.90625)
(2,2) (3,2) 1.49467 (85.63830)
(2,2) (3,2) (3,1) (3,2) (3,1) 1.49646 (85.74076)
(3,1) (2,2) 1.50359 (86.14942)
(3,1) (3,2) 1.51385 (86.73705)
(3,1) (3,2) (4,1) (3,2) (4,1) 1.49910 (85.89196)
(4,1) (3,1) 1.49448 (85.62737)
(3,1) (4,1) 1.50278 (86.10282)
(3,1) (4,1) (4,0) (4,1) (4,0) 1.50819 (86.41266)
(4,0) (3,1) 1.50278 (86.10282)
(4,0) (4,1) 1.53195 (87.77434)
(4,0) (4,1) (5,0) (4,1) (5,0) 1.49894 (85.88288)
(5,0) (4,0) 1.49894 (85.88288)

and here's a quick and dirty java app to generate the fastening angles for an arbitrary frequency.

Icos.java

// Icos.java Copyright 1998 David J. Anderson

// computes the chord lengths for an n-frequency icosahedral geodesic patch

// to compile: javac Icos.java

// to execute: java Icos n s


// where n is the frequency and s is the length of a side of the icosahedron
// outputs an html document containing the vertex and chord information

import java.lang.Math;
import java.util.Hashtable;

class Rounding
{
public static String toString (double d, int place)
{
if (place <= 0)
return ""+(int)d;
String s = "";
if (d < 0)
{
s += "-";
d = -d;
}
d += 0.5*Math.pow(10,-place);
if (d > 1)
{
int i = (int)d;
s += i;
d -= i;
}
else
s += "0";
if (d > 0)
{
d += 1.0;
String f = ""+(int)(d*Math.pow(10,place));
s += "."+f.substring(1);
}
return s;
}
}

class SPoint // Spherical coordinate point


{
public double radius;
public double theta;
public double phi;

public SPoint (double radius, double theta, double phi)


{
this.radius = radius;
this.theta = theta;
this.phi = phi;
}

public CPoint cPoint ()


{
double x;
double y;
double z;
x = radius*Math.cos(theta)*Math.sin(phi);
y = radius*Math.sin(theta)*Math.sin(phi);
z = radius*Math.cos(phi);
return new CPoint(x,y,z);
}
}

class CPoint // Cartesian coordinate point


{
public double x;
public double y;
public double z;

public CPoint (double x, double y, double z)


{
this.x = x;
this.y = y;
this.z = z;
}

public double distanceTo (CPoint cPoint)


{
double xdiff = cPoint.x-x;
double ydiff = cPoint.y-y;
double zdiff = cPoint.z-z;
return Math.sqrt((xdiff*xdiff)+(ydiff*ydiff)+(zdiff*zdiff));
}

public SPoint sPoint ()


{
double radius;
double theta;
double phi;
radius = distanceTo(Icos.origin);
theta = (x == 0.0)? 0.0 : Math.atan2(y,x);
phi = Math.acos(z/radius);
return new SPoint(radius,theta,phi);
}

public void translate (double dx, double dy, double dz)


{
x += dx;
y += dy;
z += dz;
}
}

class Plane // a geometric plane


{
public double a;
public double b;
public double c;
public double d;

public Plane (CPoint A, CPoint B, CPoint C)


{
a = (((A.y*B.z)+(A.z*C.y)+(B.y*C.z))-((A.y*C.z)+(A.z*B.y)+(B.z*C.y)));
b = (((A.z*B.x)+(A.x*C.z)+(B.z*C.x))-((A.z*C.x)+(A.x*B.z)+(B.x*C.z)));
c = (((A.x*B.y)+(A.y*C.x)+(B.x*C.y))-((A.x*C.y)+(A.y*B.x)+(B.y*C.x)));
d = Math.sqrt((a*a)+(b*b)+(c*c));
}

public double dihedralAngleBetween (Plane plane)


{
return Math.acos(Math.abs(((a*plane.a)+(b*plane.b)+(c*plane.c))/(d*plane.d)));
}
}

public class Icos // the icosahedron chord determiner


{
private int n;
private double s;
private double d;
private Hashtable cPoints = new Hashtable();

public static final CPoint origin = new CPoint(0.0,0.0,0.0);

public Icos (int n, double s)


{
this.n = n;
this.s = s;
d = s*0.9510565162951534;
}

public String getLabel (int row, int column)


{
return "("+row+","+column+")";
}

public void mesh ()


{
CPoint topCorner = (new SPoint(d,0.0,0.0)).cPoint();
CPoint leftCorner =
(new SPoint(d,-Math.PI/5.0,1.107148717940909)).cPoint();
CPoint rightCorner =
(new SPoint(d,Math.PI/5.0,1.107148717940909)).cPoint();
double incX = (leftCorner.x-topCorner.x)/n;
double incY = (rightCorner.y-leftCorner.y)/n;
double incZ = (leftCorner.z-topCorner.z)/n;
double x;
double y;
double z;
String label;
for (int i = 0; i <= n; i++)
{
z = topCorner.z+(incZ*i);
x = topCorner.x+(incX*i);
for (int j = 0; j <= i; j++)
{
y = -((incY*i)/2.0)+(incY*j);
label = getLabel(j,i-j);
cPoints.put(label,new CPoint(x,y,z));
}
}
}

public void project ()


{
String label;
SPoint sPoint;
CPoint cPoint;

System.out.println();
System.out.println("<H2>Circumscribed Spherical Projection</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println("<TR><TD><B>Vertex<TD><B>x<TD><B>y<TD><B>z");

for (int i = 0; i <= n; i++)


for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
sPoint = ((CPoint)cPoints.get(label)).sPoint();
sPoint.radius = d;
cPoint = sPoint.cPoint();
cPoints.put(label,cPoint);

System.out.println
("<TR><TD>"+label+"<TD>"+Rounding.toString(cPoint.x,5)+"<TD>"+
Rounding.toString(cPoint.y,5)+"<TD>"+Rounding.toString(cPoint.z,5));
}

System.out.println("</TABLE></CENTER>");
}

public String getBelowLeftLabel (int row, int column)


{
int destinationColumn = column+1;
if (row+destinationColumn > n)
return null;
return getLabel(row,destinationColumn);
}

public String getBelowRightLabel (int row, int column)


{
int destinationRow = row+1;
if (destinationRow+column > n)
return null;
return getLabel(destinationRow,column);
}

public String getRightLabel (int row, int column)


{
int destinationRow = row+1;
int destinationColumn = column-1;
if ((destinationRow > n)||(destinationColumn < 0))
return null;
return getLabel(destinationRow,destinationColumn);
}

public void chords ()


{
String label;
String belowLeftLabel;
String belowRightLabel;
String rightLabel;
CPoint cPoint;

System.out.println();
System.out.println("<H2>Chord Lengths</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println("<TR><TD><B>Vertex<TD><B>Vertex<TD><B>chord");

for (int i = 0; i <= n; i++)


for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(j,i-j);

if (belowLeftLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowLeftLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowLeftLabel)),5));

belowRightLabel = getBelowRightLabel(j,i-j);

if (belowRightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowRightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowRightLabel)),5));

rightLabel = getRightLabel(j,i-j);

if (rightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+rightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(rightLabel)),5));
}

System.out.println("</TABLE></CENTER>");
}
public void surfaces ()
{
String label;
String belowLeftLabel;
String belowRightLabel;
String rightLabel;
CPoint cPoint;
CPoint belowLeftCPoint;
CPoint belowRightCPoint;
CPoint rightCPoint;
Plane plane;

System.out.println();
System.out.println("<H2>Subface Definition</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println
("<TR><TD><B>Vertices<TD><B>Chords</B><BR>(* edgeLength)"+
"<TD><B>Planar Coefficients");

for (int i = 0; i <= n; i++)


for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(j,i-j);
belowRightLabel = getBelowRightLabel(j,i-j);
rightLabel = getRightLabel(j,i-j);

if ((belowLeftLabel != null) && (belowRightLabel != null))


{
belowLeftCPoint = (CPoint)cPoints.get(belowLeftLabel);
belowRightCPoint = (CPoint)cPoints.get(belowRightLabel);
plane = new Plane(cPoint,belowLeftCPoint,belowRightCPoint);
System.out.println
("<TR><TD>"+label+" "+belowLeftLabel+" "+belowRightLabel+
"<TD>"+Rounding.toString(cPoint.distanceTo(belowLeftCPoint),5)+
" "+Rounding.toString
(belowLeftCPoint.distanceTo(belowRightCPoint),5)+" "+
Rounding.toString(belowRightCPoint.distanceTo(cPoint),5)+
"<TD>"+Rounding.toString(plane.a,5)+" "+
Rounding.toString(plane.b,5)+" "+Rounding.toString(plane.c,5));
}

if ((belowRightLabel != null) && (rightLabel != null))


{
belowRightCPoint = (CPoint)cPoints.get(belowRightLabel);
rightCPoint = (CPoint)cPoints.get(rightLabel);
plane = new Plane(cPoint,belowRightCPoint,rightCPoint);
System.out.println
("<TR><TD>"+label+" "+belowRightLabel+" "+rightLabel+
"<TD>"+Rounding.toString(cPoint.distanceTo(belowRightCPoint),5)+
" "+Rounding.toString
(belowRightCPoint.distanceTo(rightCPoint),5)+" "+
Rounding.toString(rightCPoint.distanceTo(cPoint),5)+
"<TD>"+Rounding.toString(plane.a,5)+" "+
Rounding.toString(plane.b,5)+" "+Rounding.toString(plane.c,5));
}
}
System.out.println("</TABLE></CENTER>");
}

public void fasteners ()


{
String label;
String belowLeftLabel;
String belowRightLabel;
String rightLabel;
CPoint cPoint;
CPoint belowLeftCPoint;
CPoint belowRightCPoint;
CPoint rightCPoint;
Plane plane;
Plane belowLeftPlane;
Plane belowPlane;
Plane belowRightPlane;
Plane rightPlane;
double belowLeftAngle;
double belowAngle;
double belowRightAngle;
double rightAngle;

System.out.println();
System.out.println("<H2>Fastening Angle Determination</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println
("<TR><TD><B>Vertices<TD><B>Edge<TD><B>Fastening Angle</B><BR>radians
(degrees)");

for (int i = 0; i <= n; i++)


for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(j,i-j);
belowRightLabel = getBelowRightLabel(j,i-j);
rightLabel = getRightLabel(j,i-j);

if ((belowLeftLabel != null) && (belowRightLabel != null))


{
belowLeftCPoint = (CPoint)cPoints.get(belowLeftLabel);
belowRightCPoint = (CPoint)cPoints.get(belowRightLabel);
plane = new Plane(cPoint,belowLeftCPoint,belowRightCPoint);
belowLeftPlane = new Plane(cPoint,belowLeftCPoint,origin);
belowPlane = new Plane(belowLeftCPoint,belowRightCPoint,origin);
belowRightPlane = new Plane(cPoint,belowRightCPoint,origin);
belowLeftAngle = plane.dihedralAngleBetween(belowLeftPlane);
belowAngle = plane.dihedralAngleBetween(belowPlane);
belowRightAngle = plane.dihedralAngleBetween(belowRightPlane);

System.out.println
("<TR><TD ROWSPAN=3>"+label+" "+belowLeftLabel+" "+belowRightLabel+
"<TD>"+label+" "+belowRightLabel+"<TD>"+
Rounding.toString(belowLeftAngle,5)+" ("+
Rounding.toString(180.0*belowLeftAngle/Math.PI,5)+")"+
"<TR><TD>"+belowLeftLabel+" "+belowRightLabel+"<TD>"+
Rounding.toString(belowAngle,5)+" ("+
Rounding.toString(180.0*belowAngle/Math.PI,5)+")"+
"<TR><TD>"+belowRightLabel+" "+label+"<TD>"+
Rounding.toString(belowRightAngle,5)+" ("+
Rounding.toString(180.0*belowRightAngle/Math.PI,5)+")");
}

if ((belowRightLabel != null) && (rightLabel != null))


{
belowRightCPoint = (CPoint)cPoints.get(belowRightLabel);
rightCPoint = (CPoint)cPoints.get(rightLabel);
plane = new Plane(cPoint,belowRightCPoint,rightCPoint);
belowRightPlane = new Plane(cPoint,belowRightCPoint,origin);
belowPlane = new Plane(belowRightCPoint,rightCPoint,origin);
rightPlane = new Plane(cPoint,rightCPoint,origin);
belowRightAngle = plane.dihedralAngleBetween(belowRightPlane);
belowAngle = plane.dihedralAngleBetween(belowPlane);
rightAngle = plane.dihedralAngleBetween(rightPlane);

System.out.println
("<TR><TD ROWSPAN=3>"+label+" "+belowRightLabel+" "+rightLabel+
"<TD>"+label+" "+belowRightLabel+"<TD>"+
Rounding.toString(belowRightAngle,5)+" ("+
Rounding.toString(180.0*belowRightAngle/Math.PI,5)+")"+
"<TR><TD>"+belowRightLabel+" "+rightLabel+"<TD>"+
Rounding.toString(belowAngle,5)+" ("+
Rounding.toString(180.0*belowAngle/Math.PI,5)+")"+
"<TR><TD>"+rightLabel+" "+label+"<TD>"+
Rounding.toString(rightAngle,5)+" ("+
Rounding.toString(180.0*rightAngle/Math.PI,5)+")");
}
}

System.out.println("</TABLE></CENTER>");
}

public static void main (String[] arguments)


{
int n = Integer.valueOf(arguments[0]).intValue();
double s = Double.valueOf(arguments[1]).doubleValue();
System.out.println
("<TITLE>Calculations for a "+n+"-frequency Icosahedral Geodesic
Patch</TITLE>");
Icos icos = new Icos(n,s);
icos.mesh();
icos.project();
icos.chords();
icos.surfaces();
icos.fasteners();
}
}
An Inexpensive Technique for Building Models of
Geodesic Domes
A Prototyping Saga

David Anderson
February 1998

After writing some simple code to generate geodesic angles and lengths (follow links from here), the time
had come to temper the calculations with a little reality. It was time to build prototypical models.

Easy to say, especially with all the math done, but what do you use as materials? You need struts and
hubs. In a large world, struts should be rigid and hubs have to be strong and shear-resistant; everything is
measured and cut precisely as time has been taken to make sure the cost of materials isn't wasted. In my
small, modeling world, struts should still be rigid, but hubs need to be flexible and forgiving since the
precision is not as imperitive as simply being able to try new ideas quickly.

After some cursory searching on the web, I found that I'd need to be creative and figure out a technique
that would work for me, since I couldn't find anybody who really talks about the specifics of building
geodesic models out there...

Wood and Wire

Everybody is entitled to at least one false start.

A trip to the local craft store netted me a thousand popsicle sticks, a


spool of 20 guage wire, and a spool of 30 guage wire. Calculating a
two frequency icosahedral geodesic dome for a maximum subface
edge length of 4.1 inches (the useable length of the ubiquitous
popsicle stick) I got out a drill and saw and made lots of the two
sizes of struts I'd need. I drilled a hole at each end of the stick
making sure the distance between the holes matched the calculated chord length of the strut.

The wire was used to tie together five or six sticks at a vertex. I decided to stack the sticks at a vertex
since this seemed easy to do, and the wires could be tightened if the structure seemed "flimsy". Several
sticks would be brought together, their holes aligned, and a wire looped around and through a couple
times. The ends of the wire would be twisted together; more tension on the twist would serve to tighten up
the stack and make the geodesic more rigid locally.

I made more than I needed since I figured the quality of the wood wasn't great and I'd be wiring the struts
together. Under tension, The wire could cut through the cheap wood. If that happened, I'd not only have to
rewire the vertex with the damaged strut, but also the adjoining vertex connected by the damaged strut;
but I figured I'd only have to do that a few times since the wood wasn't that cheap. But I was wrong.

The different height of sticks at a vertex caused some serious problems. There was as much as a half inch
effective difference in actual versus intended chord length at some vertices. In a larger structure, this
would be a problem, but not a big one since the as the strut lengthens the relative error decreases. But half
an inch of error doesn't diminish very much on a four inch strut; the dome was distorted and as it grew, so
did the tension on individual vertices which translated to twisting and bending of the popsicle sticks. Each
additional vertex caused a bit more distortion and sticks started to be cut by wires. At about a 40% of a
sphere, I decided it was only going to get worse. My first attempt is now hanging on a wall in the
basement with several struts just about at their limit.

Wood and String

Of course, since I had so many popsicle sticks I figured, what the heck, I'd try again. Tight vertices
seemed like the problem: I decided to loosen them up a little. Instead of using wire, I'd try something with
a little more give. So, I went out and bought some string.

Now, the nice thing about wire is that you can push it through a hole. Wire stays rigid; generally an
intentional effort is required to bend a piece of wire. String doesn't act so nicely. No matter how hard you
try, you can't push a string through a small hole - it must be dragged. I got a big needle, threaded it with
the string, and started dragging.

After about twenty minutes I had three sticks strung together. At this rate it'd take weeks to build the
model. Seeing as I didn't want to spend weeks on just the first of many models, I decided a new way must
be found. The remainder of the sticks became kindling.

I sent out a quick note requesting a scalable design for hubs from the folks on the geodesic mailing list. I
got a couple of responses (and I thank all who replied!) but nothing seemed like it was what I was looking
for; they all took to much effort. I needed something quick-and-dirty. Fortunately I had included access to
my other geodesic papers in my mail message.

John Dunaj, another geodesic modeler, took a look at the calculation papers and wrote back, saying the
chord length tables had helped his planning; he was using plastic soda straws and small nuts and bolts.
Plastic straws! That was the answer for the strut - rigid enough, easy to cut to length, and cheap. But using
screws for hubs was too high-maintenance and expensive for me. I wanted to be able to build a model,
strip down a section, and replace it with framing for windows or doors - or whatever. I needed hubs that
would facilitate attaching together hollow cylinders of varying length. Then the answer for quick, low
cost hubs hit me...

Plastic Straws and Pipe Cleaners

Pipe cleaners make the perfect hub! You can twist a few pipe cleaners together to form a five-spoked or
six-spoked star, fold the ends over a few times so they'll plug in the straws, cut the straws to the right
length (taking away a tenth of an inch or so for the pipe cleaner fuzz factor), and you're set!
By making the pipe cleaners stick down the straws a good fraction of their length, a dome model
predicated on this technique stands up very well for design purposes. A section of the dome may
extracted, quickly modified, and replaced - all to give the model a plug-and-play quality that was very
attractive to the quick-and-dirty designer in me.

Of course, other qualities of the geodesic are not realized. Most seriously: a force applied on a strut, once
it becomes great enough to overcome the coefficient of friction between a plastic straw and a pipe cleaner,
causes the struts to slip on the hubs. In a bolted model, this would not happen: the structure would become
stronger (unless the local force-time differential is great enough to break a bolt or strut - all real materials
have their limits.)

However, when I'm considering a model for a structure I intend to build, I'm not looking at proving
physical properties - I'm simply interested that I crunched the numbers correctly and that the results look
good to me. For geodesic domes, I take it for granted that structural engineers know what they're talking
about: geodesic structures are the ephemeral in Fuller's sence of the word: they give the most for the least.
I simply assume if the materials are good and the frequency is hight, the dome will be strong.

Practical Results

I built a 14" diameter icosahedron first, to test different pipe cleaner twisting and folding techniques.
Total time: about an hour.

I built a 19" diameter semi-spherical 2-frequency geodesic dome, cutting the straws and forming the hubs
as I went along. Total time: about an hour and a half.

I built a 36.5" diameter semi-spherical 4-frequency geodesic dome, pre-cutting all the struts and pre-
making all the hubs before I started assembly. Total time: about 4 hours.

And, to give my son something he could think about and play with, I built a tetrahedron. Total time: about
5 minutes.

The 2-frequency dome is destined to become a 15' diameter greenhouse this spring or summer; I'll
probably use bolts and PVC pipe, and cover the thing with plastic, clear on all the sunlit exposures, but
internally reflective on the north side. I'll put a door on the north side and have a couple of quick-change
screen sections so I can use it in summer and winter.
The 4-frequency dome is destined to become a 35' diamter patio enclosure; basically to keep the elements
away from some areas on the patio. This dome may become multi-frequency: some faces may be
tesselated at a higher frequency than others. Some of this will be based on functional need: the patio is
used as a basketball half-court and should keep the ball from rolling escaping down the hill next to the
patio - a tighter tesselation will keep the basketball in. Some of this will be based on design need: the
enclosure will be anchored to the ground around the patio and also to bricks on the house. It is likely to be
hemispherical (or a little more) with a third (or so) of the dome sliced off to accomodate the house, and
some open holes on the sides at strategic places to let people use existing walkways.

By playing with a model based on the quick-and-dirty platic straw and pipe cleaner technique, I should be
able to get things going much more quickly on each project than I would if I had to rely on a purely
mathematical technique. And since I'll be able to play more than calculate, the end results should feel
much more playful than a purely calculated space.
A Simple Bolted PVC Geodesic Strut Design
David Anderson
May 1998

Once the math of the n-frequency geodesic is worked out, building a structure is fairly straightforward;
the question is reduced to construction technique. There are two general directions you can go with a
dome - either building a faced structure or an edged structure. A faced structure centers around the
construction of geodesic faces as the principal component of the structure. The geometry of the faces is
determined as a function of the chord lengths and fastening angles, the faces are constructed individually,
and are integrated into a finished dome. The edged structure amounts to building struts which form the
edges of the geodesic structure as a set of joined chords. The chord lengths for the geodesic are
determined, the struts are fabricated and finally, the structure is constructed by attaching the struts
together at geodesic vertices.

Generally, building a edged structure is easier than the corresponding faced structure. After all, the faced
structure has surfaces which have to be carefully built to fasten to the adjoining surfaces; if the surfaces
are more than simple cardboard triangles connected by duct tape, this construction is not trivial. The
edged structure is just a framework. All one needs to do is cut the struts to the right length, determine a
means for attaching them, and the dome practically builds itself.

I'd been planning a geodesic greenhouse: I'd figured out the math and built some simple models with
straws and pipe cleaners. Now it was time to see if it would work on human scale. I decided on a 2-
frequency half-spherical geodesic because I'd only need struts of two sizes; I wanted something fairly
straightforward to prove everything before I added complexity. The math worked out to 30 short struts
and 35 long ones.

The main considerations for me were materials and technique. I wanted this thing to be cheap since I
didn't want to sink money into false starts - but at the same time I wanted it to be solid enough to hold up
to the elements. I didn't want to toss this out as a prototype unless I'd really screwed up. I chose PVC pipe
because it had
a good track
record: it was
strong, it could
be cut easily,
and it was
remarkably
affordable.

I decided I was
going to try the
flattening technique I had read about in articles on the Internet geodesic mailing list. By putting some
adhesive inside the end of a PVC strut, putting that end in a vice, and screwing it closed for a while,
letting the glue set, a good solid strut could be made. The clamped end would be able to be drilled and
bolted to other struts. To test
things out I put an end of a
PVC pipe I intended on
using into my bench vice
and started turning... Now,
although I may not be the
strongest guy on my street, I'm certainly not the weakest - this
PVC pipe was really hard to crush. I'm sure Fuller would have
something synergetic to say about collapsing a cylinder, but all I
know is that there was no way I wanted to vice-close 130 PVC
pipe ends. This was not a reasonable answer for me.

Since at one time I was a woodworker (mostly making cabinetry) I


have an old bandsaw. After a little thinking, I decided the PVC
would still be strong enough for my purposes if instead of
squeezing the pipe flat, I used the bandsaw to cut it flat. I tried
cutting a few pipes, drilling 1/4" holes 1" from the ends, and
connecting them with a bolt. Voila! The technique worked. In fact,
it worked better than I thought at that moment. Because the PVC had to bend up to 12 degrees on a 2-
frequency dome, cutting the PVC made it bend more easily - without breaking. The bend put less strain
on the smoothly cut strut so the dome was easier to assemble.

The diagram shows the gentle curve of the cut; this is important for two reasons. First, smoothly cut
shapes resist cracking or breaking better than sharp cuts. PVC bends when a smooth force is applied
along a smooth line, but it's still brittle enough to fracture if too much force is quickly applied or a sharp
cut exists in the material. Stress tends to accumulate around sharp cuts. Second, the struts must
accommodate each other in the close quarters around a geodesic vertex. If the curve wasn't relatively long
and smooth, the struts from below would press up against the struts from above where they came together.
Such pressing would locally distort the geodesic near the vertex and increase the stress on the joint. The
smooth shape of the curve lets the struts fit nicely against each other and avoids increasing the joint's
mechanical stress.

The dome I desired was supposed to be about 14' in diameter - but since the PVC pipe came in 10'
lengths, only two struts of a 2-frequency geodesic would be able to be cut per pipe - with a lot of waste. I
spent a little time iterating runs of the Java code I wrote to calculate the chord lengths - remembering to
add 2" per strut (because of I was giving up 1" on each end,) I worked it down to three struts per pipe to
get a slightly smaller 11' diameter dome. Smaller but cheaper, and that was better for me on the first try.

Measuring and cutting the struts (adding an inch onto each end) took a little over an hour - I got faster as I
went along. Drilling a 1/4" hole 1" from each end took another half hour. The struts were ready.

To fasten the struts together I decided to use a 2" long 1/4" bolt and wingnut at each vertex - with two
washers to sandwich the PVC. I chose wingnuts so I could quickly unjoin and rejoin struts - that way I
could make partial geodesic sections and join them together during construction. The wingnuts also meant
I could build the dome quickly by hand and then go tighten things up at the end - very important for the
degree of instant gratification I require.

An important thing to realize is that if you're doing a lot of cuts on the bandsaw, and you're basically
eyeballing the effort, you don't want to go too shallow. I never cut the end completely flat since that
would have given up too much of the pipe's surface. This cut leaves a bit of a tight fit at the bolt, and
you're going to wreck your hands trying to tighten the wingnut against the compression resistance of the
PVC. What's important is to keep the height
of the stacked PVC short enough so you get
good purchase with the wingnut. Unless you
stack the PVC right, it can be a tight fit.

In the case of the 5-way joints this is still


pretty easy; a stack of five struts at a vertex
was still manageable on a 2" bolt. In the
case of the 6-way joint, there's trouble
unless you realize an underlying geodesic
principle: a flattened joint is always
rotationally symmetric. You can get tight
joints if you add the struts to the bolt in a
particular order. For a 5-way joint, add the
struts in every-other order: if you numbered
the struts in clockwise-order, you'd add
struts in the sequence 1, 3, 5, 2, and 4. For a 6-way joint, you make sure opposite pairs of struts are
aligned - this way the grooves of the paired pipes are kept together: if you numbered the struts in
clockwise-order, you'd add struts in the sequence 1, 4, 2, 5, 3, and 6. If you don't keep the pairs together,
you'll tear your hands to pieces trying to push pipes together while you're pushing a bolt through. Trust
me, this is the voice of sore-handed experience.

Connecting the struts into a geodesic can be accomplished in many ways, but my two suggestions for
wingnut-constructed small domes are by-the-partial-face and by-layers-from-the-top-down. The BTPF
method is done by pre-building the partial geodesic faces with the intention of connecting them together
at the construction site. The struts already present in an adjoining face are left out of the one you're
building - to connect them you undo the wingnut on the target joint, add the struts, and reconnect the joint
with wingnut. If the faces aren't too big, this is very easy. The BLFTTD method is also easy, but is
especially nice for not-too-large edged-structure domes. You start with the pentagon at the top of the
dome as the first layer. Then you build lattitudes of the successive layers and, one at a time, add them as
the layer under the previously completed structure above. If you have a reasonable way to hoist the
existing structure up another level each time, everything's simple.

In any case, I was able to put my first dome, 11' in diameter, together myself in about three hours total -
less than 5 hours from uncut raw materials to geodesic structure.

Next I've got to build a greenhouse-functional cover for it.


Planning a Bigger Dome, Part I
David Anderson
May 1998

With the framework of the backyard greenhouse done, my thoughts turned to a bigger domed structure: in
particular, planning a 50' diameter, 10-frequency dome. The struts would be between 2.5' and 3.5' long,
and 1500 of them would be needed for a half spherical structure. It would be as tall as a three story
building, and using the technique previously detailed, once the struts were fabrcated, ought to go up very
quickly with 25 helpers. Using bolts and wingnuts, it could be constructed a layer at a time, with the layer
"rings" being pre-built. Twenty-eight different strut lengths would be required.

After a quick note to the geodesic group announcing my intentions, I got back quite a few supporting
notes - with quite a few novel uses for such a structure. But I also got back some notes which expressed
concern about the tolerances required and instability of larger domes fabricated with something as pliable
as PVC pipe. Sections could "dimple" if measurements were not precise or too much localized pressure
was exerted - the structure might even collapse under its own weight! It's a scary thought - I'd hate to
invest a lot of time and effort into something that could fall down due to poor planning or a wrong choice
of materials.

This lead to the thought of building reinforcement into the structure; it would increase the weight, but also
increase the local structural integrity. After some thought experimentation, I decided a 9-frequency
geodesic patch situated "inside" each 10-frequency patch, connected together by struts, would work well.
I believe that an even-odd offset would be optimal since then not every triangle in the grid would have to
be fully connected: each internal vertex in the outer shell would only have to be connected to nine struts,
while the external vertices would connect to ten struts. The inner shell would similarly have nine-strut
internal vertices, with the external vertices connected to eight on the edges and seven at the "points".

Interestingly enough, the pattern matches the one needed for close-sphere packing - it's the geodesist's
friend, the octet truss, bent to wrap a geodesic sphere.
At this point some
programming is required to calculate the layering of the geodesic patches. Basically, figuring out where
the vertices in the outer and inner shell are - a derivation of the previous Java code, and what the lengths
of the connectors needed between the shells and inner
patches are - new code. That work will be reported in
Part II.
Planning a Bigger Dome, Part II
David Anderson
May 1998

To build a good support structure based on an


octet truss, the notion of separate inner and
outer shells is simply a convenience. In Part I, a
10-frequency outer icosahedral shell was
considered to be supported by a 9-frequency
inner icosahedral shell connected by a system
of struts. These struts connect the shells
together to form a layer of tetrahedrons and
octahedrons.

A section of this layering can be seen in the diagram on the left. Downward pointing tetrahedrons are
blue, while the upward pointing tetrahedrons are red. (Although only one upward pointing tetrahedron is
shown, look closely at the arrangement and extend it outward. You ought to get the idea...) The volumes
between these tetrahedrons are octahedrons. This space-filling arrangement is a section of an octet truss.
When this structure is appropriately extended and its vertices are projected as an icosahedral patch, the
resulting shell reinforces itself radially to resist local deformations.

To calculate the vertices of this puppy for use in a geodesic, you have to find the centers of every other
tesselation on the geodesic patch and project them only to a fraction of the radius of the circumscribed
sphere. This can be computed easily if the tesselation is effectively calculated at three times the frequency
with the extra unused vertices discarded.

Triple the frequency, you ask? Why not


double? Consider: if you double the
frequency, you end up with four triangles -
the new vertices are on the edges, not in the
face. Only if you triple (or tesselate with a
frequency that has a factor of 3 in it) does
the center point get calculated explicitly. (In
the diagram on the right, the red circle
indicates the center of the face.) The nicest
part about all this is that most of the
calculations needed can be made by
adapting the techniques which were
previously determined for calculating chord
lengths for a geodesic patch. The code adjustments are straightforward.

The only tricky part of this is what the fraction of the radius to project the center point should be. And this
turns out to be only a little nasty...
In order to utilize the octet truss in a geodesic patch, it has to be deformed. The tetrahedrons' sides are
stretched - the further their vertices have to be projected from the "truss plane", the greater the stretch. To
preserve the maximum strength of the tetrahedron in the truss, the radial distance of the center vertex must
be multiplied by the relative change of the radial projection to the circumscribed sphere. First we assume
the triangle's center vertex is on the patch so we can generate the relative change: (r+ r)/r. Now we must
consider that on an unprojected side, the center point already lies "below" the face by the altitude of the
tetrahedron - call its radial distance h, equal to the altitude of the tetrahedron. So when we put it together,
the new radial distance for the vertex is then h(r+ r)/r. All that's left is a little math to figure out the
value of r - which we already have by simply converting Cartesian to Spherical coordinates. Generally,
the sides of the tetrahedron will be longer in the center of an icosahedral side, where the projected
distance is greatest.

Of course, we could ditch all this complication and simply subtract a constant amount from each radial
distance for points on the inner shell, and everything would likely work out well enough. But as the
domes get bigger and the structural integrity is brought into question, I'd rather follow the all rules that I
can figure out.

The last thing which has to be done is to connect the inner shells. Since each side-structure of the geodesic
has an underlying shell which is recessed by "half" a subface width, although the sides of the outer shell
meet at geodesic vertices, the sides of the inner shell must be connected artificially. The edge vertices of
the inner shell are connected to their neighbors by a "ladder" of struts.

The Java chordlength application from the earlier paper has now been adapted to generate the inner shell
and extra chords for an arbitrary size and frequency:

Icos.java

// Icos.java Copyright 1998 David J. Anderson

// computes the chord lengths for an n-frequency icosahedral geodesic patch


// with octet strut bracing

// to compile: javac Icos.java

// to execute: java Icos n s


// where n is the frequency and s is the length of a side of the icosahedron
// outputs an html document containing the vertex and chord information

import java.lang.Math;
import java.util.Hashtable;

class Rounding
{
public static String toString (double d, int place)
{
if (place <= 0)
return ""+(int)d;
String s = "";
if (d < 0)
{
s += "-";
d = -d;
}
d += 0.5*Math.pow(10,-place);
if (d > 1)
{
int i = (int)d;
s += i;
d -= i;
}
else
s += "0";
if (d > 0)
{
d += 1.0;
String f = ""+(int)(d*Math.pow(10,place));
s += "."+f.substring(1);
}
return s;
}
}

class SPoint // Spherical coordinate point


{
public double radius, theta, phi;

public SPoint (double radius, double theta, double phi)


{
this.radius = radius;
this.theta = theta;
this.phi = phi;
}

public CPoint cPoint ()


{
double x, y, z;
x = radius*Math.cos(theta)*Math.sin(phi);
y = radius*Math.sin(theta)*Math.sin(phi);
z = radius*Math.cos(phi);
return new CPoint(x,y,z);
}
}

class CPoint // Cartesian coordinate point


{
public double x, y, z;

public CPoint (double x, double y, double z)


{
this.x = x;
this.y = y;
this.z = z;
}

public double distanceTo (CPoint cPoint)


{
double xdiff = cPoint.x-x;
double ydiff = cPoint.y-y;
double zdiff = cPoint.z-z;
return Math.sqrt((xdiff*xdiff)+(ydiff*ydiff)+(zdiff*zdiff));
}

public SPoint sPoint ()


{
double radius, theta, phi;
radius = distanceTo(Icos.origin);
theta = (x == 0.0)? 0.0 : Math.atan2(y,x);
phi = Math.acos(z/radius);
return new SPoint(radius,theta,phi);
}
}

public class Icos // the icosahedron chord determiner


{
private int n;
private double s, d;
private Hashtable cPoints = new Hashtable();
public static final CPoint origin = new CPoint(0.0,0.0,0.0);
private static final String outerShell = "Outer";
private static final String innerShell = "Inner";

public Icos (int n, double s)


{
this.n = n;
this.s = s;
d = s*0.9510565162951534;
}

public String getLabel (String shell, int row, int column)


{
return "("+shell+","+row+","+column+")";
}

public void mesh ()


{
CPoint topCorner = (new SPoint(d,0.0,0.0)).cPoint();
CPoint leftCorner =
(new SPoint(d,-Math.PI/5.0,1.107148717940909)).cPoint();
CPoint rightCorner =
(new SPoint(d,Math.PI/5.0,1.107148717940909)).cPoint();
double incX = (leftCorner.x-topCorner.x)/n;
double incY = (rightCorner.y-leftCorner.y)/n;
double incZ = (leftCorner.z-topCorner.z)/n;
double x, y, z;
int i, I, j, J;
String label;
CPoint cPoint;
for (i = 0; i <= n; i++)
{
z = topCorner.z+(incZ*i);
x = topCorner.x+(incX*i);
for (j = 0; j <= i; j++)
{
y = -((incY*i)/2.0)+(incY*j);
label = getLabel(outerShell,j,i-j);
cPoint = new CPoint(x,y,z);
cPoints.put(label,cPoint);
}
}
incX /= 3.0;
incY /= 3.0;
incZ /= 3.0;
for (i = 0; i < n; i++)
{
I = 3*i;
z = topCorner.z+(incZ*(I+2));
x = topCorner.x+(incX*(I+2));
for (j = 0; j <= i; j++)
{
J = 3*j;
y = -((incY*(I+2))/2.0)+(incY*(J+1));
label = getLabel(innerShell,j,i-j);
cPoint = new CPoint(x,y,z);
cPoints.put(label,cPoint);
}
}
}

public void project ()


{
String label;
SPoint sPoint;
CPoint cPoint;
int i, K, j, J;
double stretchFactor;

System.out.println();
System.out.println("<H2>Circumscribed Spherical Projection</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println("<TR><TD><B>Vertex<TD><B>x<TD><B>y<TD><B>z");

for (i = 0; i <= n; i++)


for (j = 0; j <= i; j++)
{
label = getLabel(outerShell,j,i-j);
sPoint = ((CPoint)cPoints.get(label)).sPoint();
sPoint.radius = d;
cPoint = sPoint.cPoint();
cPoints.put(label,cPoint);

System.out.println
("<TR><TD>"+label+"<TD>"+Rounding.toString(cPoint.x,5)+"<TD>"+
Rounding.toString(cPoint.y,5)+"<TD>"+Rounding.toString(cPoint.z,5));
}
for (i = 0; i < n; i++)
for (j = 0; j <= i; j++)
{
label = getLabel(innerShell,j,i-j);
sPoint = ((CPoint)cPoints.get(label)).sPoint();
stretchFactor = d/sPoint.radius;
sPoint.radius = d-(stretchFactor*((s/n)*0.8164965809));
cPoint = sPoint.cPoint();
cPoints.put(label,cPoint);

System.out.println
("<TR><TD>"+label+"<TD>"+Rounding.toString(cPoint.x,5)+"<TD>"+
Rounding.toString(cPoint.y,5)+"<TD>"+Rounding.toString(cPoint.z,5));
}

System.out.println("</TABLE></CENTER>");
}

public String getBelowLeftLabel (String shell, int row, int column)


{
int N = (shell.equals(outerShell))? n : n-1;
if (row+column+1 > N)
return null;
return getLabel(shell,row,column+1);
}

public String getBelowRightLabel (String shell, int row, int column)


{
int N = (shell.equals(outerShell))? n : n-1;
if (row+column+1 > N)
return null;
return getLabel(shell,row+1,column);
}

public String getRightLabel (String shell, int row, int column)


{
int N = (shell.equals(outerShell))? n : n-1;
if ((row+1 > N)||(column-1 < 0))
return null;
return getLabel(shell,row+1,column-1);
}

public String getInnerBelowLabel (int row, int column)


{
if (row+column > n-1)
return null;
return getLabel(innerShell,row,column);
}

public String getInnerAboveLeftLabel (int row, int column)


{
if (row == 0)
return null;
return getLabel(innerShell,row-1,column);
}

public String getInnerAboveRightLabel (int row, int column)


{
if (column == 0)
return null;
return getLabel(innerShell,row,column-1);
}

public void chords ()


{
String label, belowLeftLabel, belowRightLabel, rightLabel, innerBelowLabel,
innerAboveLeftLabel, innerAboveRightLabel, nextInnerShellLabel;
CPoint cPoint;
SPoint sPoint;
int i, j;
System.out.println();
System.out.println("<H2>Chord Lengths</H2>");
System.out.println
("<P><CENTER><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println("<TR><TD><B>Vertex<TD><B>Vertex<TD><B>chord");
System.out.println("<TR><TR><TD COLSPAN=3>Outer Shell");
for (i = 0; i <= n; i++)
for (j = 0; j <= i; j++)
{
label = getLabel(outerShell,j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(outerShell,j,i-j);
if (belowLeftLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowLeftLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowLeftLabel)),5));
belowRightLabel = getBelowRightLabel(outerShell,j,i-j);
if (belowRightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowRightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowRightLabel)),5));
rightLabel = getRightLabel(outerShell,j,i-j);
if (rightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+rightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(rightLabel)),5));
}
System.out.println("<TR><TR><TD COLSPAN=3>Inner Shell");
for (i = 0; i < n; i++)
for (j = 0; j <= i; j++)
{
label = getLabel("Inner",j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(innerShell,j,i-j);
if (belowLeftLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowLeftLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowLeftLabel)),5));
belowRightLabel = getBelowRightLabel(innerShell,j,i-j);
if (belowRightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+belowRightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowRightLabel)),5));
rightLabel = getRightLabel(innerShell,j,i-j);
if (rightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+rightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(rightLabel)),5));
}
System.out.println("<TR><TR><TD COLSPAN=3>Shell Connectors");
for (i = 0; i <= n; i++)
for (j = 0; j <= i; j++)
{
label = getLabel(outerShell,j,i-j);
cPoint = (CPoint)cPoints.get(label);
innerBelowLabel = getInnerBelowLabel(j,i-j);
if (innerBelowLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+innerBelowLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(innerBelowLabel)),5));
innerAboveLeftLabel = getInnerAboveLeftLabel(j,i-j);
if (innerAboveLeftLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+innerAboveLeftLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo
((CPoint)cPoints.get(innerAboveLeftLabel)),5));
innerAboveRightLabel = getInnerAboveRightLabel(j,i-j);
if (innerAboveRightLabel != null)
System.out.println
("<TR><TD>"+label+"<TD>"+innerAboveRightLabel+"<TD>"+
Rounding.toString
(cPoint.distanceTo
((CPoint)cPoints.get(innerAboveRightLabel)),5));
}
System.out.println("<TR><TR><TD COLSPAN=3>Shell Connectors");
for (i = 0; i < n; i++)
{
label = getLabel(innerShell,i,0);
cPoint = (CPoint)cPoints.get(label);
nextInnerShellLabel = getLabel(innerShell,0,i);
sPoint = ((CPoint)cPoints.get(nextInnerShellLabel)).sPoint();
sPoint.theta += (2.0*Math.PI/5.0);
System.out.println
("<TR><TD>"+label+"<TD>"+nextInnerShellLabel+"<TD>"+
Rounding.toString(cPoint.distanceTo(sPoint.cPoint()),5));
}

System.out.println("</TABLE></CENTER>");
}

public static void main (String[] arguments)


{
int n = Integer.valueOf(arguments[0]).intValue();
double s = Double.valueOf(arguments[1]).doubleValue();
System.out.println
("<TITLE>Calculations for a "+n+"-frequency Icosahedral Geodesic Patch"+
" with Octet Strut Bracing</TITLE>");
Icos icos = new Icos(n,s);
icos.mesh();
icos.project();
icos.chords();
}
}

Finally, here are the chord lengths for a patch of the 50 ft diameter dome. If I can engineer in a few
walkways, find some financing and able bodies, and a suitable place to build it, it'd be a really cool
project...

600-inch 10-frequency
Icosahedral Geodesic Patch
with Octet-Strut Bracing
Circumscribed Spherical Projection
Vertex x y z
(Outer,0,0) 0.00000 0.00000 300.00000
(Outer,0,1) 22.87612 -16.62048 298.66443
(Outer,1,0) 22.87612 16.62048 298.66443
(Outer,0,2) 47.85479 -34.76854 294.11064
(Outer,1,1) 48.17945 0.00000 296.10596
(Outer,2,0) 47.85479 34.76854 294.11064
(Outer,0,3) 74.32120 -53.99751 285.58822
(Outer,1,2) 75.41500 -18.26407 289.79131
(Outer,2,1) 75.41500 18.26407 289.79131
(Outer,3,0) 74.32120 53.99751 285.58822
(Outer,0,4) 101.30711 -73.60393 272.61572
(Outer,1,3) 103.67439 -37.66193 278.98602
(Outer,2,2) 104.50114 0.00000 281.21080
(Outer,3,1) 103.67439 37.66193 278.98602
(Outer,4,0) 101.30711 73.60393 272.61572
(Outer,0,5) 127.59762 -92.70510 255.19524
(Outer,1,4) 131.68499 -57.40485 263.36998
(Outer,2,3) 133.88169 -19.45415 267.76338
(Outer,3,2) 133.88169 19.45415 267.76338
(Outer,4,1) 131.68499 57.40485 263.36998
(Outer,5,0) 127.59762 92.70510 255.19524
(Outer,0,6) 151.96067 -110.40589 233.91985
(Outer,1,5) 158.02199 -76.53980 243.25030
(Outer,2,4) 162.02650 -39.23971 249.41463
(Outer,3,3) 163.43055 0.00000 251.57594
(Outer,4,2) 162.02650 39.23971 249.41463
(Outer,5,1) 158.02199 76.53980 243.25030
(Outer,6,0) 151.96067 110.40589 233.91985
(Outer,0,7) 173.41612 -125.99419 209.88643
(Outer,1,6) 181.43018 -94.15482 219.58588
(Outer,2,5) 187.43437 -58.36245 226.85278
(Outer,3,4) 190.66897 -19.78987 230.76764
(Outer,4,3) 190.66897 19.78987 230.76764
(Outer,5,2) 187.43437 58.36245 226.85278
(Outer,6,1) 181.43018 94.15482 219.58588
(Outer,7,0) 173.41612 125.99419 209.88643
(Outer,0,8) 191.41915 -139.07415 184.43723
(Outer,1,7) 201.10668 -109.58442 193.77141
(Outer,2,6) 209.00228 -75.92452 201.37903
(Outer,3,5) 214.21071 -38.90830 206.39748
(Outer,4,4) 216.03534 0.00000 208.15555
(Outer,5,3) 214.21071 38.90830 206.39748
(Outer,6,2) 209.00228 75.92452 201.37903
(Outer,7,1) 201.10668 109.58442 193.77141
(Outer,8,0) 191.41915 139.07415 184.43723
(Outer,0,9) 205.88510 -149.58428 158.85801
(Outer,1,8) 216.80751 -122.51546 167.28559
(Outer,2,7) 226.24501 -91.32035 174.56743
(Outer,3,6) 233.26738 -56.49289 179.98579
(Outer,4,5) 237.03298 -19.13495 182.89128
(Outer,5,4) 237.03298 19.13495 182.89128
(Outer,6,3) 233.26738 56.49289 179.98579
(Outer,7,2) 226.24501 91.32035 174.56743
(Outer,8,1) 216.80751 122.51546 167.28559
(Outer,9,0) 205.88510 149.58428 158.85801
(Outer,0,10) 217.08204 -157.71933 134.16408
(Outer,1,9) 228.76122 -132.96381 141.38221
(Outer,2,8) 239.27393 -104.30561 147.87942
(Outer,3,7) 247.73732 -71.99668 153.11008
(Outer,4,6) 253.26778 -36.80196 156.52810
(Outer,5,5) 255.19524 0.00000 157.71933
(Outer,6,4) 253.26778 36.80196 156.52810
(Outer,7,3) 247.73732 71.99668 153.11008
(Outer,8,2) 239.27393 104.30561 147.87942
(Outer,9,1) 228.76122 132.96381 141.38221
(Outer,10,0) 217.08204 157.71933 134.16408
(Inner,0,0) 13.67106 0.00000 272.95040
(Inner,0,1) 35.74894 -15.58387 269.11315
(Inner,1,0) 35.74894 15.58387 269.11315
(Inner,0,2) 59.33746 -32.33339 262.17904
(Inner,1,1) 59.71863 0.00000 263.86319
(Inner,2,0) 59.33746 32.33339 262.17904
(Inner,0,3) 83.75020 -49.78480 251.67490
(Inner,1,2) 84.89945 -16.82265 255.12847
(Inner,2,1) 84.89945 16.82265 255.12847
(Inner,3,0) 83.75020 49.78480 251.67490
(Inner,0,4) 108.05384 -67.29061 237.44008
(Inner,1,3) 110.36930 -34.36628 242.52812
(Inner,2,2) 111.17597 0.00000 244.30071
(Inner,3,1) 110.36930 34.36628 242.52812
(Inner,4,0) 108.05384 67.29061 237.44008
(Inner,0,5) 131.20824 -84.11326 219.75170
(Inner,1,4) 134.99939 -51.92619 226.10124
(Inner,2,3) 137.02690 -17.56868 229.49697
(Inner,3,2) 137.02690 17.56868 229.49697
(Inner,4,1) 134.99939 51.92619 226.10124
(Inner,5,0) 131.20824 84.11326 219.75170
(Inner,0,6) 152.27310 -99.56959 199.32807
(Inner,1,5) 157.67043 -68.73256 206.39327
(Inner,2,4) 161.20811 -35.13736 211.02416
(Inner,3,3) 162.44318 0.00000 212.64088
(Inner,4,2) 161.20811 35.13736 211.02416
(Inner,5,1) 157.67043 68.73256 206.39327
(Inner,6,0) 152.27310 99.56959 199.32807
(Inner,0,7) 170.59520 -113.16687 177.18569
(Inner,1,6) 177.51703 -84.11326 184.37493
(Inner,2,5) 182.64623 -51.92619 189.70229
(Inner,3,4) 185.38933 -17.56868 192.55135
(Inner,4,3) 185.38933 17.56868 192.55135
(Inner,5,2) 182.64623 51.92619 189.70229
(Inner,6,1) 177.51703 84.11326 184.37493
(Inner,7,0) 170.59520 113.16687 177.18569
(Inner,0,8) 185.89448 -124.67099 154.41216
(Inner,1,7) 194.08553 -97.62327 161.21601
(Inner,2,6) 200.67143 -67.29061 166.68655
(Inner,3,5) 204.97156 -34.36628 170.25843
(Inner,4,4) 206.46966 0.00000 171.50281
(Inner,5,3) 204.97156 34.36628 170.25843
(Inner,6,2) 200.67143 67.29061 166.68655
(Inner,7,1) 194.08553 97.62327 161.21601
(Inner,8,0) 185.89448 124.67099 154.41216
(Inner,0,9) 198.23041 -134.09022 131.95960
(Inner,1,8) 207.34384 -109.08712 138.02630
(Inner,2,7) 215.09829 -80.83348 143.18835
(Inner,3,6) 220.79599 -49.78480 146.98124
(Inner,4,5) 223.82582 -16.82265 148.99816
(Inner,5,4) 223.82582 16.82265 148.99816
(Inner,6,3) 220.79599 49.78480 146.98124
(Inner,7,2) 215.09829 80.83348 143.18835
(Inner,8,1) 207.34384 109.08712 138.02630
(Inner,9,0) 198.23041 134.09022 131.95960

Chord Lengths
Vertex Vertex chord

Outer Shell
(Outer,0,0) (Outer,0,1) 28.30797
(Outer,0,0) (Outer,1,0) 28.30797
(Outer,0,1) (Outer,0,2) 31.20934
(Outer,0,1) (Outer,1,1) 30.38164
(Outer,0,1) (Outer,1,0) 33.24095
(Outer,1,0) (Outer,1,1) 30.38164
(Outer,1,0) (Outer,2,0) 31.20934
(Outer,0,2) (Outer,0,3) 33.80615
(Outer,0,2) (Outer,1,2) 32.41326
(Outer,0,2) (Outer,1,1) 34.82726
(Outer,1,1) (Outer,1,2) 33.39501
(Outer,1,1) (Outer,2,1) 33.39501
(Outer,1,1) (Outer,2,0) 34.82726
(Outer,2,0) (Outer,2,1) 32.41326
(Outer,2,0) (Outer,3,0) 33.80615
(Outer,0,3) (Outer,0,4) 35.79018
(Outer,0,3) (Outer,1,3) 34.23522
(Outer,0,3) (Outer,1,2) 35.99640
(Outer,1,2) (Outer,1,3) 35.93917
(Outer,1,2) (Outer,2,2) 35.40063
(Outer,1,2) (Outer,2,1) 36.52814
(Outer,2,1) (Outer,2,2) 35.40063
(Outer,2,1) (Outer,3,1) 35.93917
(Outer,2,1) (Outer,3,0) 35.99640
(Outer,3,0) (Outer,3,1) 34.23522
(Outer,3,0) (Outer,4,0) 35.79018
(Outer,0,4) (Outer,0,5) 36.87165
(Outer,0,4) (Outer,1,4) 35.64701
(Outer,0,4) (Outer,1,3) 36.57885
(Outer,1,3) (Outer,1,4) 37.65949
(Outer,1,3) (Outer,2,3) 37.01286
(Outer,1,3) (Outer,2,2) 37.73664
(Outer,2,2) (Outer,2,3) 37.71622
(Outer,2,2) (Outer,3,2) 37.71622
(Outer,2,2) (Outer,3,1) 37.73664
(Outer,3,1) (Outer,3,2) 37.01286
(Outer,3,1) (Outer,4,1) 37.65949
(Outer,3,1) (Outer,4,0) 36.57885
(Outer,4,0) (Outer,4,1) 35.64701
(Outer,4,0) (Outer,5,0) 36.87165
(Outer,0,5) (Outer,0,6) 36.87165
(Outer,0,5) (Outer,1,5) 36.46424
(Outer,0,5) (Outer,1,4) 36.46424
(Outer,1,4) (Outer,1,5) 38.26990
(Outer,1,4) (Outer,2,4) 38.01751
(Outer,1,4) (Outer,2,3) 38.26726
(Outer,2,3) (Outer,2,4) 38.99071
(Outer,2,3) (Outer,3,3) 38.90542
(Outer,2,3) (Outer,3,2) 38.90830
(Outer,3,2) (Outer,3,3) 38.90542
(Outer,3,2) (Outer,4,2) 38.99071
(Outer,3,2) (Outer,4,1) 38.26726
(Outer,4,1) (Outer,4,2) 38.01751
(Outer,4,1) (Outer,5,1) 38.26990
(Outer,4,1) (Outer,5,0) 36.46424
(Outer,5,0) (Outer,5,1) 36.46424
(Outer,5,0) (Outer,6,0) 36.87165
(Outer,0,6) (Outer,0,7) 35.79018
(Outer,0,6) (Outer,1,6) 36.57885
(Outer,0,6) (Outer,1,5) 35.64701
(Outer,1,5) (Outer,1,6) 37.65949
(Outer,1,5) (Outer,2,5) 38.26726
(Outer,1,5) (Outer,2,4) 38.01751
(Outer,2,4) (Outer,2,5) 38.99071
(Outer,2,4) (Outer,3,4) 39.32427
(Outer,2,4) (Outer,3,3) 39.32427
(Outer,3,3) (Outer,3,4) 39.57975
(Outer,3,3) (Outer,4,3) 39.57975
(Outer,3,3) (Outer,4,2) 39.32427
(Outer,4,2) (Outer,4,3) 39.32427
(Outer,4,2) (Outer,5,2) 38.99071
(Outer,4,2) (Outer,5,1) 38.01751
(Outer,5,1) (Outer,5,2) 38.26726
(Outer,5,1) (Outer,6,1) 37.65949
(Outer,5,1) (Outer,6,0) 35.64701
(Outer,6,0) (Outer,6,1) 36.57885
(Outer,6,0) (Outer,7,0) 35.79018
(Outer,0,7) (Outer,0,8) 33.80615
(Outer,0,7) (Outer,1,7) 35.99640
(Outer,0,7) (Outer,1,6) 34.23522
(Outer,1,6) (Outer,1,7) 35.93917
(Outer,1,6) (Outer,2,6) 37.73664
(Outer,1,6) (Outer,2,5) 37.01286
(Outer,2,5) (Outer,2,6) 37.71622
(Outer,2,5) (Outer,3,5) 38.90830
(Outer,2,5) (Outer,3,4) 38.90542
(Outer,3,4) (Outer,3,5) 38.90542
(Outer,3,4) (Outer,4,4) 39.32427
(Outer,3,4) (Outer,4,3) 39.57975
(Outer,4,3) (Outer,4,4) 39.32427
(Outer,4,3) (Outer,5,3) 38.90542
(Outer,4,3) (Outer,5,2) 38.90542
(Outer,5,2) (Outer,5,3) 38.90830
(Outer,5,2) (Outer,6,2) 37.71622
(Outer,5,2) (Outer,6,1) 37.01286
(Outer,6,1) (Outer,6,2) 37.73664
(Outer,6,1) (Outer,7,1) 35.93917
(Outer,6,1) (Outer,7,0) 34.23522
(Outer,7,0) (Outer,7,1) 35.99640
(Outer,7,0) (Outer,8,0) 33.80615
(Outer,0,8) (Outer,0,9) 31.20934
(Outer,0,8) (Outer,1,8) 34.82726
(Outer,0,8) (Outer,1,7) 32.41326
(Outer,1,7) (Outer,1,8) 33.39501
(Outer,1,7) (Outer,2,7) 36.52814
(Outer,1,7) (Outer,2,6) 35.40063
(Outer,2,6) (Outer,2,7) 35.40063
(Outer,2,6) (Outer,3,6) 37.73664
(Outer,2,6) (Outer,3,5) 37.71622
(Outer,3,5) (Outer,3,6) 37.01286
(Outer,3,5) (Outer,4,5) 38.26726
(Outer,3,5) (Outer,4,4) 38.99071
(Outer,4,4) (Outer,4,5) 38.01751
(Outer,4,4) (Outer,5,4) 38.01751
(Outer,4,4) (Outer,5,3) 38.99071
(Outer,5,3) (Outer,5,4) 38.26726
(Outer,5,3) (Outer,6,3) 37.01286
(Outer,5,3) (Outer,6,2) 37.71622
(Outer,6,2) (Outer,6,3) 37.73664
(Outer,6,2) (Outer,7,2) 35.40063
(Outer,6,2) (Outer,7,1) 35.40063
(Outer,7,1) (Outer,7,2) 36.52814
(Outer,7,1) (Outer,8,1) 33.39501
(Outer,7,1) (Outer,8,0) 32.41326
(Outer,8,0) (Outer,8,1) 34.82726
(Outer,8,0) (Outer,9,0) 31.20934
(Outer,0,9) (Outer,0,10) 28.30797
(Outer,0,9) (Outer,1,9) 33.24095
(Outer,0,9) (Outer,1,8) 30.38164
(Outer,1,8) (Outer,1,9) 30.38164
(Outer,1,8) (Outer,2,8) 34.82726
(Outer,1,8) (Outer,2,7) 33.39501
(Outer,2,7) (Outer,2,8) 32.41326
(Outer,2,7) (Outer,3,7) 35.99640
(Outer,2,7) (Outer,3,6) 35.93917
(Outer,3,6) (Outer,3,7) 34.23522
(Outer,3,6) (Outer,4,6) 36.57885
(Outer,3,6) (Outer,4,5) 37.65949
(Outer,4,5) (Outer,4,6) 35.64701
(Outer,4,5) (Outer,5,5) 36.46424
(Outer,4,5) (Outer,5,4) 38.26990
(Outer,5,4) (Outer,5,5) 36.46424
(Outer,5,4) (Outer,6,4) 35.64701
(Outer,5,4) (Outer,6,3) 37.65949
(Outer,6,3) (Outer,6,4) 36.57885
(Outer,6,3) (Outer,7,3) 34.23522
(Outer,6,3) (Outer,7,2) 35.93917
(Outer,7,2) (Outer,7,3) 35.99640
(Outer,7,2) (Outer,8,2) 32.41326
(Outer,7,2) (Outer,8,1) 33.39501
(Outer,8,1) (Outer,8,2) 34.82726
(Outer,8,1) (Outer,9,1) 30.38164
(Outer,8,1) (Outer,9,0) 30.38164
(Outer,9,0) (Outer,9,1) 33.24095
(Outer,9,0) (Outer,10,0) 28.30797
(Outer,0,10) (Outer,1,9) 28.30797
(Outer,1,9) (Outer,2,8) 31.20934
(Outer,2,8) (Outer,3,7) 33.80615
(Outer,3,7) (Outer,4,6) 35.79018
(Outer,4,6) (Outer,5,5) 36.87165
(Outer,5,5) (Outer,6,4) 36.87165
(Outer,6,4) (Outer,7,3) 35.79018
(Outer,7,3) (Outer,8,2) 33.80615
(Outer,8,2) (Outer,9,1) 31.20934
(Outer,9,1) (Outer,10,0) 28.30797

Inner Shell
(Inner,0,0) (Inner,0,1) 27.29495
(Inner,0,0) (Inner,1,0) 27.29495
(Inner,0,1) (Inner,0,2) 29.74973
(Inner,0,1) (Inner,1,1) 29.06828
(Inner,0,1) (Inner,1,0) 31.16775
(Inner,1,0) (Inner,1,1) 29.06828
(Inner,1,0) (Inner,2,0) 29.74973
(Inner,0,2) (Inner,0,3) 31.79419
(Inner,0,2) (Inner,1,2) 30.71985
(Inner,0,2) (Inner,1,1) 32.37947
(Inner,1,1) (Inner,1,2) 31.51779
(Inner,1,1) (Inner,2,1) 31.51779
(Inner,1,1) (Inner,2,0) 32.37947
(Inner,2,0) (Inner,2,1) 30.71985
(Inner,2,0) (Inner,3,0) 31.79419
(Inner,0,3) (Inner,0,4) 33.16249
(Inner,0,3) (Inner,1,3) 32.09316
(Inner,0,3) (Inner,1,2) 33.16249
(Inner,1,2) (Inner,1,3) 33.39552
(Inner,1,2) (Inner,2,2) 33.02571
(Inner,1,2) (Inner,2,1) 33.64531
(Inner,2,1) (Inner,2,2) 33.02571
(Inner,2,1) (Inner,3,1) 33.39552
(Inner,2,1) (Inner,3,0) 33.16249
(Inner,3,0) (Inner,3,1) 32.09316
(Inner,3,0) (Inner,4,0) 33.16249
(Inner,0,4) (Inner,0,5) 33.64531
(Inner,0,4) (Inner,1,4) 33.02571
(Inner,0,4) (Inner,1,3) 33.39552
(Inner,1,3) (Inner,1,4) 34.42142
(Inner,1,3) (Inner,2,3) 34.09689
(Inner,1,3) (Inner,2,2) 34.42142
(Inner,2,2) (Inner,2,3) 34.58439
(Inner,2,2) (Inner,3,2) 34.58439
(Inner,2,2) (Inner,3,1) 34.42142
(Inner,3,1) (Inner,3,2) 34.09689
(Inner,3,1) (Inner,4,1) 34.42142
(Inner,3,1) (Inner,4,0) 33.39552
(Inner,4,0) (Inner,4,1) 33.02571
(Inner,4,0) (Inner,5,0) 33.64531
(Inner,0,5) (Inner,0,6) 33.16249
(Inner,0,5) (Inner,1,5) 33.39552
(Inner,0,5) (Inner,1,4) 33.02571
(Inner,1,4) (Inner,1,5) 34.42142
(Inner,1,4) (Inner,2,4) 34.58439
(Inner,1,4) (Inner,2,3) 34.58439
(Inner,2,3) (Inner,2,4) 35.13736
(Inner,2,3) (Inner,3,3) 35.19622
(Inner,2,3) (Inner,3,2) 35.13736
(Inner,3,2) (Inner,3,3) 35.19622
(Inner,3,2) (Inner,4,2) 35.13736
(Inner,3,2) (Inner,4,1) 34.58439
(Inner,4,1) (Inner,4,2) 34.58439
(Inner,4,1) (Inner,5,1) 34.42142
(Inner,4,1) (Inner,5,0) 33.02571
(Inner,5,0) (Inner,5,1) 33.39552
(Inner,5,0) (Inner,6,0) 33.16249
(Inner,0,6) (Inner,0,7) 31.79419
(Inner,0,6) (Inner,1,6) 33.16249
(Inner,0,6) (Inner,1,5) 32.09316
(Inner,1,5) (Inner,1,6) 33.39552
(Inner,1,5) (Inner,2,5) 34.42142
(Inner,1,5) (Inner,2,4) 34.09689
(Inner,2,4) (Inner,2,5) 34.58439
(Inner,2,4) (Inner,3,4) 35.13736
(Inner,2,4) (Inner,3,3) 35.19622
(Inner,3,3) (Inner,3,4) 35.19622
(Inner,3,3) (Inner,4,3) 35.19622
(Inner,3,3) (Inner,4,2) 35.19622
(Inner,4,2) (Inner,4,3) 35.13736
(Inner,4,2) (Inner,5,2) 34.58439
(Inner,4,2) (Inner,5,1) 34.09689
(Inner,5,1) (Inner,5,2) 34.42142
(Inner,5,1) (Inner,6,1) 33.39552
(Inner,5,1) (Inner,6,0) 32.09316
(Inner,6,0) (Inner,6,1) 33.16249
(Inner,6,0) (Inner,7,0) 31.79419
(Inner,0,7) (Inner,0,8) 29.74973
(Inner,0,7) (Inner,1,7) 32.37947
(Inner,0,7) (Inner,1,6) 30.71985
(Inner,1,6) (Inner,1,7) 31.51779
(Inner,1,6) (Inner,2,6) 33.64531
(Inner,1,6) (Inner,2,5) 33.02571
(Inner,2,5) (Inner,2,6) 33.02571
(Inner,2,5) (Inner,3,5) 34.42142
(Inner,2,5) (Inner,3,4) 34.58439
(Inner,3,4) (Inner,3,5) 34.09689
(Inner,3,4) (Inner,4,4) 34.58439
(Inner,3,4) (Inner,4,3) 35.13736
(Inner,4,3) (Inner,4,4) 34.58439
(Inner,4,3) (Inner,5,3) 34.09689
(Inner,4,3) (Inner,5,2) 34.58439
(Inner,5,2) (Inner,5,3) 34.42142
(Inner,5,2) (Inner,6,2) 33.02571
(Inner,5,2) (Inner,6,1) 33.02571
(Inner,6,1) (Inner,6,2) 33.64531
(Inner,6,1) (Inner,7,1) 31.51779
(Inner,6,1) (Inner,7,0) 30.71985
(Inner,7,0) (Inner,7,1) 32.37947
(Inner,7,0) (Inner,8,0) 29.74973
(Inner,0,8) (Inner,0,9) 27.29495
(Inner,0,8) (Inner,1,8) 31.16775
(Inner,0,8) (Inner,1,7) 29.06828
(Inner,1,7) (Inner,1,8) 29.06828
(Inner,1,7) (Inner,2,7) 32.37947
(Inner,1,7) (Inner,2,6) 31.51779
(Inner,2,6) (Inner,2,7) 30.71985
(Inner,2,6) (Inner,3,6) 33.16249
(Inner,2,6) (Inner,3,5) 33.39552
(Inner,3,5) (Inner,3,6) 32.09316
(Inner,3,5) (Inner,4,5) 33.39552
(Inner,3,5) (Inner,4,4) 34.42142
(Inner,4,4) (Inner,4,5) 33.02571
(Inner,4,4) (Inner,5,4) 33.02571
(Inner,4,4) (Inner,5,3) 34.42142
(Inner,5,3) (Inner,5,4) 33.39552
(Inner,5,3) (Inner,6,3) 32.09316
(Inner,5,3) (Inner,6,2) 33.39552
(Inner,6,2) (Inner,6,3) 33.16249
(Inner,6,2) (Inner,7,2) 30.71985
(Inner,6,2) (Inner,7,1) 31.51779
(Inner,7,1) (Inner,7,2) 32.37947
(Inner,7,1) (Inner,8,1) 29.06828
(Inner,7,1) (Inner,8,0) 29.06828
(Inner,8,0) (Inner,8,1) 31.16775
(Inner,8,0) (Inner,9,0) 27.29495
(Inner,0,9) (Inner,1,8) 27.29495
(Inner,1,8) (Inner,2,7) 29.74973
(Inner,2,7) (Inner,3,6) 31.79419
(Inner,3,6) (Inner,4,5) 33.16249
(Inner,4,5) (Inner,5,4) 33.64531
(Inner,5,4) (Inner,6,3) 33.16249
(Inner,6,3) (Inner,7,2) 31.79419
(Inner,7,2) (Inner,8,1) 29.74973
(Inner,8,1) (Inner,9,0) 27.29495

Shell Connectors
(Outer,0,0) (Inner,0,0) 30.30807
(Outer,0,1) (Inner,0,1) 32.25000
(Outer,0,1) (Inner,0,0) 31.97162
(Outer,1,0) (Inner,1,0) 32.25000
(Outer,1,0) (Inner,0,0) 31.97162
(Outer,0,2) (Inner,0,2) 34.02071
(Outer,0,2) (Inner,0,1) 33.75615
(Outer,1,1) (Inner,1,1) 34.24542
(Outer,1,1) (Inner,0,1) 33.55573
(Outer,1,1) (Inner,1,0) 33.55573
(Outer,2,0) (Inner,2,0) 34.02071
(Outer,2,0) (Inner,1,0) 33.75615
(Outer,0,3) (Inner,0,3) 35.45089
(Outer,0,3) (Inner,0,2) 35.23969
(Outer,1,2) (Inner,1,2) 35.96589
(Outer,1,2) (Inner,0,2) 34.91233
(Outer,1,2) (Inner,1,1) 35.38671
(Outer,2,1) (Inner,2,1) 35.96589
(Outer,2,1) (Inner,1,1) 35.38671
(Outer,2,1) (Inner,2,0) 34.91233
(Outer,3,0) (Inner,3,0) 35.45089
(Outer,3,0) (Inner,2,0) 35.23969
(Outer,0,4) (Inner,0,4) 36.36897
(Outer,0,4) (Inner,0,3) 36.25071
(Outer,1,3) (Inner,1,3) 37.21373
(Outer,1,3) (Inner,0,3) 35.91427
(Outer,1,3) (Inner,1,2) 36.82332
(Outer,2,2) (Inner,2,2) 37.50877
(Outer,2,2) (Inner,1,2) 36.70853
(Outer,2,2) (Inner,2,1) 36.70853
(Outer,3,1) (Inner,3,1) 37.21373
(Outer,3,1) (Inner,2,1) 36.82332
(Outer,3,1) (Inner,3,0) 35.91427
(Outer,4,0) (Inner,4,0) 36.36897
(Outer,4,0) (Inner,3,0) 36.25071
(Outer,0,5) (Inner,0,5) 36.64834
(Outer,0,5) (Inner,0,4) 36.64834
(Outer,1,4) (Inner,1,4) 37.81482
(Outer,1,4) (Inner,0,4) 36.44886
(Outer,1,4) (Inner,1,3) 37.67648
(Outer,2,3) (Inner,2,3) 38.44172
(Outer,2,3) (Inner,1,3) 37.57689
(Outer,2,3) (Inner,2,2) 38.00672
(Outer,3,2) (Inner,3,2) 38.44172
(Outer,3,2) (Inner,2,2) 38.00672
(Outer,3,2) (Inner,3,1) 37.57689
(Outer,4,1) (Inner,4,1) 37.81482
(Outer,4,1) (Inner,3,1) 37.67648
(Outer,4,1) (Inner,4,0) 36.44886
(Outer,5,0) (Inner,5,0) 36.64834
(Outer,5,0) (Inner,4,0) 36.64834
(Outer,0,6) (Inner,0,6) 36.25071
(Outer,0,6) (Inner,0,5) 36.36897
(Outer,1,5) (Inner,1,5) 37.67648
(Outer,1,5) (Inner,0,5) 36.44886
(Outer,1,5) (Inner,1,4) 37.81482
(Outer,2,4) (Inner,2,4) 38.61771
(Outer,2,4) (Inner,1,4) 37.88041
(Outer,2,4) (Inner,2,3) 38.61771
(Outer,3,3) (Inner,3,3) 38.94758
(Outer,3,3) (Inner,2,3) 38.64315
(Outer,3,3) (Inner,3,2) 38.64315
(Outer,4,2) (Inner,4,2) 38.61771
(Outer,4,2) (Inner,3,2) 38.61771
(Outer,4,2) (Inner,4,1) 37.88041
(Outer,5,1) (Inner,5,1) 37.67648
(Outer,5,1) (Inner,4,1) 37.81482
(Outer,5,1) (Inner,5,0) 36.44886
(Outer,6,0) (Inner,6,0) 36.25071
(Outer,6,0) (Inner,5,0) 36.36897
(Outer,0,7) (Inner,0,7) 35.23969
(Outer,0,7) (Inner,0,6) 35.45089
(Outer,1,6) (Inner,1,6) 36.82332
(Outer,1,6) (Inner,0,6) 35.91427
(Outer,1,6) (Inner,1,5) 37.21373
(Outer,2,5) (Inner,2,5) 38.00672
(Outer,2,5) (Inner,1,5) 37.57689
(Outer,2,5) (Inner,2,4) 38.44172
(Outer,3,4) (Inner,3,4) 38.64315
(Outer,3,4) (Inner,2,4) 38.64315
(Outer,3,4) (Inner,3,3) 38.94758
(Outer,4,3) (Inner,4,3) 38.64315
(Outer,4,3) (Inner,3,3) 38.94758
(Outer,4,3) (Inner,4,2) 38.64315
(Outer,5,2) (Inner,5,2) 38.00672
(Outer,5,2) (Inner,4,2) 38.44172
(Outer,5,2) (Inner,5,1) 37.57689
(Outer,6,1) (Inner,6,1) 36.82332
(Outer,6,1) (Inner,5,1) 37.21373
(Outer,6,1) (Inner,6,0) 35.91427
(Outer,7,0) (Inner,7,0) 35.23969
(Outer,7,0) (Inner,6,0) 35.45089
(Outer,0,8) (Inner,0,8) 33.75615
(Outer,0,8) (Inner,0,7) 34.02071
(Outer,1,7) (Inner,1,7) 35.38671
(Outer,1,7) (Inner,0,7) 34.91233
(Outer,1,7) (Inner,1,6) 35.96589
(Outer,2,6) (Inner,2,6) 36.70853
(Outer,2,6) (Inner,1,6) 36.70853
(Outer,2,6) (Inner,2,5) 37.50877
(Outer,3,5) (Inner,3,5) 37.57689
(Outer,3,5) (Inner,2,5) 38.00672
(Outer,3,5) (Inner,3,4) 38.44172
(Outer,4,4) (Inner,4,4) 37.88041
(Outer,4,4) (Inner,3,4) 38.61771
(Outer,4,4) (Inner,4,3) 38.61771
(Outer,5,3) (Inner,5,3) 37.57689
(Outer,5,3) (Inner,4,3) 38.44172
(Outer,5,3) (Inner,5,2) 38.00672
(Outer,6,2) (Inner,6,2) 36.70853
(Outer,6,2) (Inner,5,2) 37.50877
(Outer,6,2) (Inner,6,1) 36.70853
(Outer,7,1) (Inner,7,1) 35.38671
(Outer,7,1) (Inner,6,1) 35.96589
(Outer,7,1) (Inner,7,0) 34.91233
(Outer,8,0) (Inner,8,0) 33.75615
(Outer,8,0) (Inner,7,0) 34.02071
(Outer,0,9) (Inner,0,9) 31.97162
(Outer,0,9) (Inner,0,8) 32.25000
(Outer,1,8) (Inner,1,8) 33.55573
(Outer,1,8) (Inner,0,8) 33.55573
(Outer,1,8) (Inner,1,7) 34.24542
(Outer,2,7) (Inner,2,7) 34.91233
(Outer,2,7) (Inner,1,7) 35.38671
(Outer,2,7) (Inner,2,6) 35.96589
(Outer,3,6) (Inner,3,6) 35.91427
(Outer,3,6) (Inner,2,6) 36.82332
(Outer,3,6) (Inner,3,5) 37.21373
(Outer,4,5) (Inner,4,5) 36.44886
(Outer,4,5) (Inner,3,5) 37.67648
(Outer,4,5) (Inner,4,4) 37.81482
(Outer,5,4) (Inner,5,4) 36.44886
(Outer,5,4) (Inner,4,4) 37.81482
(Outer,5,4) (Inner,5,3) 37.67648
(Outer,6,3) (Inner,6,3) 35.91427
(Outer,6,3) (Inner,5,3) 37.21373
(Outer,6,3) (Inner,6,2) 36.82332
(Outer,7,2) (Inner,7,2) 34.91233
(Outer,7,2) (Inner,6,2) 35.96589
(Outer,7,2) (Inner,7,1) 35.38671
(Outer,8,1) (Inner,8,1) 33.55573
(Outer,8,1) (Inner,7,1) 34.24542
(Outer,8,1) (Inner,8,0) 33.55573
(Outer,9,0) (Inner,9,0) 31.97162
(Outer,9,0) (Inner,8,0) 32.25000
(Outer,0,10) (Inner,0,9) 30.30807
(Outer,1,9) (Inner,0,9) 31.97162
(Outer,1,9) (Inner,1,8) 32.25000
(Outer,2,8) (Inner,1,8) 33.75615
(Outer,2,8) (Inner,2,7) 34.02071
(Outer,3,7) (Inner,2,7) 35.23969
(Outer,3,7) (Inner,3,6) 35.45089
(Outer,4,6) (Inner,3,6) 36.25071
(Outer,4,6) (Inner,4,5) 36.36897
(Outer,5,5) (Inner,4,5) 36.64834
(Outer,5,5) (Inner,5,4) 36.64834
(Outer,6,4) (Inner,5,4) 36.36897
(Outer,6,4) (Inner,6,3) 36.25071
(Outer,7,3) (Inner,6,3) 35.45089
(Outer,7,3) (Inner,7,2) 35.23969
(Outer,8,2) (Inner,7,2) 34.02071
(Outer,8,2) (Inner,8,1) 33.75615
(Outer,9,1) (Inner,8,1) 32.25000
(Outer,9,1) (Inner,9,0) 31.97162
(Outer,10,0) (Inner,9,0) 30.30807

Shell Connectors
(Inner,0,0) (Inner,0,0) 16.07130
(Inner,1,0) (Inner,0,1) 16.81016
(Inner,2,0) (Inner,0,2) 17.43884
(Inner,3,0) (Inner,0,3) 17.90078
(Inner,4,0) (Inner,0,4) 18.14642
(Inner,5,0) (Inner,0,5) 18.14642
(Inner,6,0) (Inner,0,6) 17.90078
(Inner,7,0) (Inner,0,7) 17.43884
(Inner,8,0) (Inner,0,8) 16.81016
(Inner,9,0) (Inner,0,9) 16.07130
Planning a Bigger Dome, Part III
David Anderson
June 1998

Okay. The logic of the dome was described in Part I, and the mathematics of the dome was described in
Part II. A lot of words, pictures, and tables - but what does it look like? Here's a snapshot of a patch...

The current web-ready visualization technology is VRML (Virtual Reality Markup Language.) If you
don't know about it (but you want to) check out the VRML consortium's pages for more information, or
just go to your local bookstore and browse the shelves. VRML is principally a representation format, not a
programming language, so it's missing some stuff that would make it more internally functional,
especially computational facilities like those in PostScript. Such is life.

I'm also building a coffee-stirrer and pipe cleaner model (along the lines of the cheap modeling technique
described previously) but realizing the structure in VRML is a lot quicker. So far the model is great - it's
rigid enough to wave around and bounce off things without deforming. Something that you just can't do
with a single geodesic shell patch.
In any case, the Java code to generate octet-struted icosahedral geodesic patches has been modified to
produce a VRML world instead of a tabular html page.

Icos.java

// Icos.java Copyright 1998 David J. Anderson

// computes the chord lengths for an n-frequency icosahedral geodesic patch


// with octet strut bracing, rendering them as a vrml world

// to compile: javac Icos.java

// to execute: java Icos n s


// where n is the frequency and s is the length of a side of the icosahedron
// outputs an html document containing the vertex and chord information

import java.lang.Math;
import java.util.Hashtable;

class Rounding
{
public static String toString (double d, int place)
{
if (place <= 0)
return ""+(int)d;
String s = "";
if (d < 0)
{
s += "-";
d = -d;
}
d += 0.5*Math.pow(10,-place);
if (d > 1)
{
int i = (int)d;
s += i;
d -= i;
}
else
s += "0";
if (d > 0)
{
d += 1.0;
String f = ""+(int)(d*Math.pow(10,place));
s += "."+f.substring(1);
}
return s;
}
}

class SPoint // Spherical coordinate point


{
public double radius, theta, phi;

public SPoint (double radius, double theta, double phi)


{
this.radius = radius;
this.theta = theta;
this.phi = phi;
}

public CPoint cPoint ()


{
double x, y, z;
x = radius*Math.cos(theta)*Math.sin(phi);
y = radius*Math.sin(theta)*Math.sin(phi);
z = radius*Math.cos(phi);
return new CPoint(x,y,z);
}
}

class CPoint // Cartesian coordinate point


{
public double x, y, z;

public CPoint (double x, double y, double z)


{
this.x = x;
this.y = y;
this.z = z;
}

public double distanceTo (CPoint cPoint)


{
double xdiff = cPoint.x-x;
double ydiff = cPoint.y-y;
double zdiff = cPoint.z-z;
return Math.sqrt((xdiff*xdiff)+(ydiff*ydiff)+(zdiff*zdiff));
}

public SPoint sPoint ()


{
double radius, theta, phi;
radius = distanceTo(Icos.origin);
theta = (x == 0.0)? Math.PI/2.0 : Math.atan2(y,x);
phi = Math.acos(z/radius);
return new SPoint(radius,theta,phi);
}
}

public class Icos // the icosahedron chord determiner


{
private int n;
private double s, d;
private Hashtable cPoints = new Hashtable();
public static final CPoint origin = new CPoint(0.0,0.0,0.0);
private static final String outerShell = "Outer";
private static final String innerShell = "Inner";

public Icos (int n, double s)


{
this.n = n;
this.s = s;
d = s*0.9510565162951534;
}

public String getLabel (String shell, int row, int column)


{
return "("+shell+","+row+","+column+")";
}
public void mesh ()
{
CPoint topCorner = (new SPoint(d,0.0,0.0)).cPoint();
CPoint leftCorner =
(new SPoint(d,-Math.PI/5.0,1.107148717940909)).cPoint();
CPoint rightCorner =
(new SPoint(d,Math.PI/5.0,1.107148717940909)).cPoint();
double incX = (leftCorner.x-topCorner.x)/n;
double incY = (rightCorner.y-leftCorner.y)/n;
double incZ = (leftCorner.z-topCorner.z)/n;
double x, y, z;
int i, I, j, J;
String label;
CPoint cPoint;
for (i = 0; i <= n; i++)
{
z = topCorner.z+(incZ*i);
x = topCorner.x+(incX*i);
for (j = 0; j <= i; j++)
{
y = -((incY*i)/2.0)+(incY*j);
label = getLabel(outerShell,j,i-j);
cPoint = new CPoint(x,y,z);
cPoints.put(label,cPoint);
}
}
incX /= 3.0;
incY /= 3.0;
incZ /= 3.0;
for (i = 0; i < n; i++)
{
I = 3*i;
z = topCorner.z+(incZ*(I+2));
x = topCorner.x+(incX*(I+2));
for (j = 0; j <= i; j++)
{
J = 3*j;
y = -((incY*(I+2))/2.0)+(incY*(J+1));
label = getLabel(innerShell,j,i-j);
cPoint = new CPoint(x,y,z);
cPoints.put(label,cPoint);
}
}
}

public void project ()


{
String label;
SPoint sPoint;
CPoint cPoint;
int i, K, j, J;
double stretchFactor;

for (i = 0; i <= n; i++)


{
for (j = 0; j <= i; j++)
{
label = getLabel(outerShell,j,i-j);
sPoint = ((CPoint)cPoints.get(label)).sPoint();
sPoint.radius = d;
cPoint = sPoint.cPoint();
cPoints.put(label,cPoint);
System.out.println("Knob { point "+roundCPoint(cPoint)+" }");
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j <= i; j++)
{
label = getLabel(innerShell,j,i-j);
sPoint = ((CPoint)cPoints.get(label)).sPoint();
stretchFactor = d/sPoint.radius;
sPoint.radius = d-(stretchFactor*((s/n)*0.8164965809));
cPoint = sPoint.cPoint();
cPoints.put(label,cPoint);
}
}
}

public String getBelowLeftLabel (String shell, int row, int column)


{
int N = (shell.equals(outerShell))? n : n-1;
if (row+column+1 > N)
return null;
return getLabel(shell,row,column+1);
}

public String getBelowRightLabel (String shell, int row, int column)


{
int N = (shell.equals(outerShell))? n : n-1;
if (row+column+1 > N)
return null;
return getLabel(shell,row+1,column);
}

public String getRightLabel (String shell, int row, int column)


{
int N = (shell.equals(outerShell))? n : n-1;
if ((row+1 > N)||(column-1 < 0))
return null;
return getLabel(shell,row+1,column-1);
}

public String getInnerBelowLabel (int row, int column)


{
if (row+column > n-1)
return null;
return getLabel(innerShell,row,column);
}

public String getInnerAboveLeftLabel (int row, int column)


{
if (row == 0)
return null;
return getLabel(innerShell,row-1,column);
}

public String getInnerAboveRightLabel (int row, int column)


{
if (column == 0)
return null;
return getLabel(innerShell,row,column-1);
}

public void chords ()


{
String label, belowLeftLabel, belowRightLabel, rightLabel,
innerBelowLabel, innerAboveLeftLabel, innerAboveRightLabel,
nextInnerShellLabel;
String outerColor = "color 1 1 1";
String innerColor = "color .8 .3 .1";
String connectorColor = "color .9 .65 .55";
CPoint cPoint;
SPoint sPoint;
int i, j;
for (i = 0; i <= n; i++)
{
for (j = 0; j <= i; j++)
{
label = getLabel(outerShell,j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(outerShell,j,i-j);
if (belowLeftLabel != null)
printStrut(cPoint,belowLeftLabel,outerColor);
belowRightLabel = getBelowRightLabel(outerShell,j,i-j);
if (belowRightLabel != null)
printStrut(cPoint,belowRightLabel,outerColor);
rightLabel = getRightLabel(outerShell,j,i-j);
if (rightLabel != null)
printStrut(cPoint,rightLabel,outerColor);
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j <= i; j++)
{
label = getLabel("Inner",j,i-j);
cPoint = (CPoint)cPoints.get(label);
belowLeftLabel = getBelowLeftLabel(innerShell,j,i-j);
if (belowLeftLabel != null)
printStrut(cPoint,belowLeftLabel,innerColor);
belowRightLabel = getBelowRightLabel(innerShell,j,i-j);
if (belowRightLabel != null)
printStrut(cPoint,belowRightLabel,innerColor);
rightLabel = getRightLabel(innerShell,j,i-j);
if (rightLabel != null)
printStrut(cPoint,rightLabel,innerColor);
}
}
for (i = 0; i <= n; i++)
{
for (j = 0; j <= i; j++)
{
label = getLabel(outerShell,j,i-j);
cPoint = (CPoint)cPoints.get(label);
innerBelowLabel = getInnerBelowLabel(j,i-j);
if (innerBelowLabel != null)
printStrut(cPoint,innerBelowLabel,connectorColor);
innerAboveLeftLabel = getInnerAboveLeftLabel(j,i-j);
if (innerAboveLeftLabel != null)
printStrut(cPoint,innerAboveLeftLabel,connectorColor);
innerAboveRightLabel = getInnerAboveRightLabel(j,i-j);
if (innerAboveRightLabel != null)
printStrut(cPoint,innerAboveRightLabel,connectorColor);
}
}
for (i = 0; i < n; i++)
{
label = getLabel(innerShell,i,0);
cPoint = (CPoint)cPoints.get(label);
nextInnerShellLabel = getLabel(innerShell,0,i);
sPoint = ((CPoint)cPoints.get(nextInnerShellLabel)).sPoint();
sPoint.theta += (2.0*Math.PI/5.0);
}
}

String roundCPoint (CPoint cPoint)


{
return Rounding.toString(cPoint.x,5)+" "+Rounding.toString(cPoint.y,5)+" "+
Rounding.toString(cPoint.z,5);
}

String roundSPoint (SPoint sPoint)


{
return Rounding.toString(sPoint.radius,5)+" "+
Rounding.toString(sPoint.theta,5)+" "+Rounding.toString(sPoint.phi,5);
}

void printStrut (CPoint startCPoint, String label, String color)


{
System.out.println("# start "+roundCPoint(startCPoint));
CPoint endPoint = (CPoint)cPoints.get(label);
CPoint endCPoint = new CPoint(endPoint.x,endPoint.y,endPoint.z);
System.out.println("# end "+roundCPoint(endCPoint));
endCPoint.x -= startCPoint.x;
endCPoint.y -= startCPoint.y;
endCPoint.z -= startCPoint.z;
System.out.println("# diff "+roundCPoint(endCPoint));
SPoint endSPoint = endCPoint.sPoint();
System.out.println("# sphere "+roundSPoint(endSPoint));
System.out.println
("Strut { start "+roundCPoint(startCPoint)+" "+
"radius 1 1 "+Rounding.toString(endSPoint.radius,5)+" "+
"theta 0 0 1 "+Rounding.toString(endSPoint.theta,5)+" "+
"phi 0 1 0 "+Rounding.toString(endSPoint.phi,5)+" "+
color+" }");
}

void printHeader ()
{
System.out.print
("#VRML V2.0 utf8\n\n"+
"PROTO Strut [field SFVec3f start 0 0 0\n"+
" field SFVec3f radius 1 1 1\n"+
" field SFRotation theta 1 0 0 0\n"+
" field SFRotation phi 0 0 1 0\n"+
" field SFColor color .9 .5 .2]\n"+
" { Transform { translation IS start rotation IS theta\n"+
" children Transform { rotation IS phi\n"+
" children Transform { scale IS radius\n"+
" children Transform { translation 0 0 .5 scale 0.02 0.02 0.5\n"+
" children Transform { rotation 1 0 0 1.5708\n"+
" children Shape {\n"+
" geometry Cylinder { }\n"+
" appearance Appearance {\n"+
" material Material { diffuseColor IS color }\n"+
" }}}}}}}}\n\n"+
"PROTO Knob [field SFVec3f point 0 0 0\n"+
" field SFColor color .9 .8 0]\n"+
" { Transform {translation IS point scale 0.05 0.05 0.05\n"+
" children Shape {\n"+
" geometry Sphere { }\n"+
" appearance Appearance {\n"+
" material Material { diffuseColor IS color }\n"+
" }}}}\n\n"+
// "Strut { start 1 1 0 radius 50 50 .0001 color .3 .3 .3 }\n"+
"Strut { start 0 0 0 radius 1 1 2 phi 0 1 0 1.5708 color .5 0 0 }\n"+
"Strut { start 0 0 0 radius 1 1 2 phi 0 1 0 1.5708 theta 0 0 1 1.5708 color
0 .5 0 }\n"+
"Strut { start 0 0 0 radius 1 1 2 color 0 0 .5 }\n\n");
}

public static void main (String[] arguments)


{
int n = Integer.valueOf(arguments[0]).intValue();
double s = Double.valueOf(arguments[1]).doubleValue();
Icos icos = new Icos(n,s);
icos.printHeader();
icos.mesh();
icos.project();
icos.chords();
}
}

A 10-frequency patch may be viewed here if your browser has a VRML plug-in loaded. The white struts
are the outer shell, the orange-red is the inner, and the connecting struts are the not-so-white-not-so-
orange-red color in between. A small Red X Green Y Blue Z axis floats at the center of the world - zoom
out if that's all you can see. If you don't have a suitable plug-in, surf to where you got your browser and
download one. At this time, plug-in viewers are available for both Microsoft's Internet Explorer and
Netscape's Navigator. And beware - the model is not small... it'll takes some patience to see it when you
load at the world at 28.8.

One of the interesting parts of all this was writing the code to draw a strut in VRML.

VRML is pretty cool, but you have to know how to do some 3D to do more than play. The
language comes with some basic shapes like spheres, cylinders, boxes, and cones, and a full
set of rectilinear transformation mechanisms. You effectively build a "graph" of the scene you
wish to represent and let the user explore. VRML is also capable of doing animation,
triggering scene-modifying code, and hyperlinking to html pages (or other VRML worlds.) If I
could count on everybody having viewers and the scenes took less time to download, you'd be
reading this in an immersive environment right now.

Anyway, to draw a mathematical scene you really need to figure out all the geometric
transforms yourself and know how to write the VRML. To define the strut, I start with a
cylinder. Since "up" for me is always along the Z axis instead of VRML's Y axis, I transform
the strut-space into my more-familiar setting. This isn't strictly necessary of course, but it did
make it easier for me to debug the code... Change the machine, not the person.

Next I slide the unit cyliner up to be sitting on the XY plane and scale it to be tall and thin, 1
unit tall. To orient the strut in 3D, I need to do some spherical coordinate conversions.
Fortunately, these are already embodied as methods of the CPoint and SPoint Java objects in
Icos.java. Since I know the start point of the strut-cylinder is currently at (0,0,0), to get the
right orientation all I have to do is scale the strut to the right length and rotate it into position
by spinning it first around the X or Y axis and then the Z axis. Now the strut simply needs to
be translated to the real start point and voila, I have a correcly sized, oriented, and positioned
cylinder. Sweet.

I've happily tucked it away and won't have to think about it any more. Thank you Mr. Reuse.
Tetrahedral Geodesics
David Anderson
June 1998

Since an icosahedron approximates a sphere closely at the onset, most people associate geodesics with
icosahedral structure. But geodesic properties are not limited to the tesselated icosaheron. From my
perspective, any de-projection of a sphere onto a closed solid can be
consided geodesic; any form will do.
I decided to explore the ins and outs of tetrahedral geodesic structure.
Although globally, the tetrahedron is less complex than the icosahedron,
the projective mathematics of the transformation is identical.
And the form of the resulting geodesic looks quite bizarre.

To make a tetrahedral geodesic patch, the first goal is understanding a tetrahedron analytically. A
tetrahedron is the simplest of the platonic solids. Four equilateral triangles are edge-connected to form a
pyramid with a triangular base. The center of the solid lies equidistant from each vertex; the solid is
rotationally symmetic around any center-vertex and center-face axis with a period of 2 /3, and
rotationally symmetric around any center-edge axis with a period of .

The neatest trick (and the easiest way) I've seen to construct at tetrahedron is with a cube. By connecting
the opposite corners of opposite faces, a perfect tetrahedron is formed. How can you tell? Because the
length of all the edges is the same ( in a unit cube,) and the distance from any vertex to the center is the
same ( /2 in a unit cube.) This makes the center of the cube the center of the tetrahedron. Now, if we
choose to deal with the unit tetrahedron we need to scale everything by 1/ ; the edges become one unit
long, then the distance from the center to a vertex becomes / .

To make a tetrahedral geodesic patch along the lines of what we've done before for the icosahedron, we
need to situate a triangular mesh of points in 3-space, with the top vertex on the z-axis and the bottom two
vertices symmetric, the same distance from but on opposite sides of the x axis. Therefore, although we
know the top vertex is (0,0, / ), but the bottom vertices, (x1,y1,z1) and (x2,y2,z2), are unknown.

We can make three mathematical statements about the vertices of our mesh:

1. From symmetry, x1 = x2, y1 = -y2, and z1 = z2

2. The distance between any two vertices is the length of an edge, ((xa - xb)2 + (ya - yb)2 + (za -
zb)2)1/2 = 1

3. The distance from the tetrahedron's center (0,0,0) to any vertex is known, (xa2 + ya2 + za2)1/2 =
/
This turns out to be enough information enough to find the unknown vertices. Substituting 1 into 2, we
have:

((2y1)2)1/2 = 1

which fixes y1 at 1/2 and y2 at -1/2. Knowing this makes equation 3 for the first unknown point become:

(x12 + 1/4 + z12)1/2 = /

By using this information with the distance from the first unknown vertex to the top vertex we have:

(x12 + 1/4 + (z1 - / )2)1/2 = 1

These two equations can now be solved simultaneously to find that x1 = 1/ and z1 = -1/ .

Our mesh vertices are (0,0, / ), (1/ ,1/2,-1/ ) and (1/ ,-1/2,-1/ ).

Now that the mesh can be constructed, a simple change to the previous Icos.java program (which
generated a vrml icosahedral geodesic patch world) and merger with the other previous Icos.java program
(which generated an html icosahedral geodesic patch table of vertices and chord lengths) yields
Tetra.java. This quick-and-dirty code will generate a tetrahedral patch rendered as html tables as well as a
vrml world. And, since it was already there, the octet truss bracing is also included. The color coding of
the struts in vrml matches the coding described in the previous paper.

For example, the outer shell of a 5-frequency tetrahedral geodesic patch with a side length of 1 unit is
rendered as:

Circumscribed Spherical Projection

Vertex x y z
(0,0) 0.00000 0.00000 0.61237
(0,1) 0.07625 -0.13207 0.59308
(1,0) 0.07625 0.13207 0.59308
(0,2) 0.19245 -0.33333 0.47629
(1,1) 0.22942 0.00000 0.56777
(2,0) 0.19245 0.33333 0.47629
(0,3) 0.28868 -0.50000 0.20412
(1,2) 0.45227 -0.26112 0.31980
(2,1) 0.45227 0.26112 0.31980
(3,0) 0.28868 0.50000 0.20412
(0,4) 0.30500 -0.52827 -0.05392
(1,3) 0.45883 -0.39736 -0.08111
(2,2) 0.60302 0.00000 -0.10660
(3,1) 0.45883 0.39736 -0.08111
(4,0) 0.30500 0.52827 -0.05392
(0,5) 0.28868 -0.50000 -0.20412
(1,4) 0.38125 -0.39620 -0.26958
(2,3) 0.48113 -0.16667 -0.34021
(3,2) 0.48113 0.16667 -0.34021
(4,1) 0.38125 0.39620 -0.26958
(5,0) 0.28868 0.50000 -0.20412

Chord Lengths

Vertex Vertex chord


(0,0) (0,1) 0.15371
(0,0) (1,0) 0.15371
(0,1) (0,2) 0.26010
(0,1) (1,1) 0.20382
(0,1) (1,0) 0.26414
(1,0) (1,1) 0.20382
(1,0) (2,0) 0.26010
(0,2) (0,3) 0.33333
(0,2) (1,2) 0.31178
(0,2) (1,1) 0.34763
(1,1) (1,2) 0.42348
(1,1) (2,1) 0.42348
(1,1) (2,0) 0.34763
(2,0) (2,1) 0.31178
(2,0) (3,0) 0.33333
(0,3) (0,4) 0.26010
(0,3) (1,3) 0.34763
(0,3) (1,2) 0.31178
(1,2) (1,3) 0.42348
(1,2) (2,2) 0.52223
(1,2) (2,1) 0.52223
(2,1) (2,2) 0.52223
(2,1) (3,1) 0.42348
(2,1) (3,0) 0.31178
(3,0) (3,1) 0.34763
(3,0) (4,0) 0.26010
(0,4) (0,5) 0.15371
(0,4) (1,4) 0.26414
(0,4) (1,3) 0.20382
(1,3) (1,4) 0.20382
(1,3) (2,3) 0.34763
(1,3) (2,2) 0.42348
(2,2) (2,3) 0.31178
(2,2) (3,2) 0.31178
(2,2) (3,1) 0.42348
(3,1) (3,2) 0.34763
(3,1) (4,1) 0.20382
(3,1) (4,0) 0.20382
(4,0) (4,1) 0.26414
(4,0) (5,0) 0.15371
(0,5) (1,4) 0.15371
(1,4) (2,3) 0.26010
(2,3) (3,2) 0.33333
(3,2) (4,1) 0.26010
(4,1) (5,0) 0.15371

The vrml world for this example displays a patch which looks like this:
At this point I'm constructing a small 6-frequency geodesic out of pipe cleaners and coffee stirrers to hang
on the wall.

The interesting thing to note about the tetrahedral geodesic is the seeming unevenness of the projection.
Since the unprojected points in the mesh near center of a face are so much closer to the center of the solid,
they must be projected farther to lie on the circumscribed sphere. Since these points end up farther apart
the farther they're projected, the tesselations of the side are smaller near edges and larger near the center
of a face. The geodesic grid looks distorted - like it's bulging too far outward. Of course, bulging is
present in all tesselations of a flat surface onto a sphere; but since a quarter of the sphere's surface area is
covered by each patch, the bulge is much more pronounced - the projected tetrahedral side's bulging is
five times more pronounced than the projected side of an icosahedron.

What this pronounced bulging implies for building domes is a much larger varience of struts sizes in the
tetrahedral geodesic than the icosahedral geodesic. With icosahedral geodesics, since the bulge in a
projected side is less pronounced, has chord lengths which have less variance and tesselations are closer
in size. However, in tetrahedral geodesics, the tesselations are relatively small near the vertics and grow
larger as the center of the side is approaced. The short struts are the edges of the smaller tesselations; the
longer struts are edges of the larger tesselations.

We can take advantage of this bulging. A small tetrahedral geodesic could be used as a simple temporary
shelter. If three odd-frequency patches were used, a tetrahedral geodesic dome cold be constructed with
entry through the largest triangle in one of the patch tesselations, and large transparent windows in the
others. These shelters would still approximate a spherical shape, with all the economies that come with it,
but for significantly fewer parts than a full scale icosahedral geodesic. In addition, since there is be more
variance between the parts, there'd be less chance of mis-construction. Larger tetrahedral geodesics would
also offer some economy, and could be linked to icosahedral geodesics to offer some variation. (To say
nothing of the middel ground of octahedral geodesics.)

However, as in all geodesics, as the frequency increases, the local variance of the parts decreases. And
because of the eveness of the projection, a icosahedral geodesic will always more closely approximate a
sphere than a tetrahedral geodesic for a given frequency. If a more-perfect, more-uniformally-tesselated
sphere is what's desired, the tetrahedron loses. But in a world which is always seeking novelty, the
tetrahedral geodesic structure is certainly different, and certainly fun to play with.
Octahedral Geodesics
David Anderson
June 1998

To round out the tessellation of platonic solids made up of equilateral triangles, attention is briefly turned
to the octahedron. The tessellation of an octahedron is done in the same way as the icosahedron and the
tetrahedron and has similar properties. But it also has some different properties - ones that make it
considerably more attractive as a bridge between traditional, right-angle construction and the more
resource-efficient geodesics.

To make a octahedral geodesic patch, the octahedron must be analytically understood. The octahedron is a
middle ground between the tetrahedron and the icosahedron. In a tetrahedron, three equilateral triangles
come together at a vertex; in an icosahedron, five. The octahedron has four equilaterals coming together at
each vertex.

To tessellate an octahedral side, the vertices of the side must be found. This is quite easy; for a unit
icosahedron with a center at (0,0,0), the six vertices lie on the 3D axis at (v,0,0), (-v,0,0), (0,v,0), (0,-v,0),
(0,0,v), and (0,0,-v). to find v, all is needed is that the distance between two adjacent vertices must equal
one:

(v2 + v2)1/2 = 1

which fixes v at 1/ . All done.

Changing the tetrahedral geodesic code, Tetra.java, to handle the octahedral mesh gives us Octa.java. This
generates an octahedral patch rendered as html tables and a vrml world (with an obligatory octet truss.)
Again, the color coding of the struts in vrml matches the coding described in the previous paper.

For example, the outer shell of a 10-frequency octahedral geodesic patch with a side length of 3 unit is
rendered as (octet truss removed for brevity):

Circumscribed Spherical Projection

Vertex x y z
(0,0) 0.00000 0.00000 2.12132
(0,1) 0.16565 -0.16565 2.10835
(1,0) 0.16565 0.16565 2.10835
(0,2) 0.36380 -0.36380 2.05798
(1,1) 0.36927 0.00000 2.08893
(2,0) 0.36380 0.36380 2.05798
(0,3) 0.59088 -0.59088 1.94980
(1,2) 0.61237 -0.20412 2.02073
(2,1) 0.61237 0.20412 2.02073
(3,0) 0.59088 0.59088 1.94980
(0,4) 0.83205 -0.83205 1.76505
(1,3) 0.88465 -0.44233 1.87663
(2,2) 0.90453 0.00000 1.91881
(3,1) 0.88465 0.44233 1.87663
(4,0) 0.83205 0.83205 1.76505
(0,5) 1.06066 -1.06066 1.50000
(1,4) 1.15728 -0.69437 1.63663
(2,3) 1.21666 -0.24333 1.72062
(3,2) 1.21666 0.24333 1.72062
(4,1) 1.15728 0.69437 1.63663
(5,0) 1.06066 1.06066 1.50000
(0,6) 1.24808 -1.24808 1.17670
(1,5) 1.38873 -0.92582 1.30931
(2,4) 1.50000 -0.50000 1.41421
(3,3) 1.54349 0.00000 1.45521
(4,2) 1.50000 0.50000 1.41421
(5,1) 1.38873 0.92582 1.30931
(6,0) 1.24808 1.24808 1.17670
(0,7) 1.37872 -1.37872 0.83563
(1,6) 1.54814 -1.10581 0.93831
(2,5) 1.70332 -0.73000 1.03237
(3,4) 1.80074 -0.25725 1.09141
(4,3) 1.80074 0.25725 1.09141
(5,2) 1.70332 0.73000 1.03237
(6,1) 1.54814 1.10581 0.93831
(7,0) 1.37872 1.37872 0.83563
(0,8) 1.45521 -1.45521 0.51450
(1,7) 1.63299 -1.22474 0.57735
(2,6) 1.80907 -0.90453 0.63960
(3,5) 1.94666 -0.48666 0.68825
(4,4) 2.00000 0.00000 0.70711
(5,3) 1.94666 0.48666 0.68825
(6,2) 1.80907 0.90453 0.63960
(7,1) 1.63299 1.22474 0.57735
(8,0) 1.45521 1.45521 0.51450
(0,9) 1.49083 -1.49083 0.23426
(1,8) 1.66174 -1.29246 0.26112
(2,7) 1.83712 -1.02062 0.28868
(3,6) 1.99047 -0.66349 0.31277
(4,5) 2.08310 -0.23146 0.32733
(5,4) 2.08310 0.23146 0.32733
(6,3) 1.99047 0.66349 0.31277
(7,2) 1.83712 1.02062 0.28868
(8,1) 1.66174 1.29246 0.26112
(9,0) 1.49083 1.49083 0.23426
(0,10) 1.50000 -1.50000 0.00000
(1,9) 1.65647 -1.32518 0.00000
(2,8) 1.81902 -1.09141 0.00000
(3,7) 1.96960 -0.78784 0.00000
(4,6) 2.08013 -0.41603 0.00000
(5,5) 2.12132 0.00000 0.00000
(6,4) 2.08013 0.41603 0.00000
(7,3) 1.96960 0.78784 0.00000
(8,2) 1.81902 1.09141 0.00000
(9,1) 1.65647 1.32518 0.00000
(10,0) 1.50000 1.50000 0.00000
Chord Lengths
Vertex Vertex chord
(0,0) (0,1) 0.23462
(0,0) (1,0) 0.23462
(0,1) (0,2) 0.28472
(0,1) (1,1) 0.26321
(0,1) (1,0) 0.33129
(1,0) (1,1) 0.26321
(1,0) (2,0) 0.28472
(0,2) (0,3) 0.33887
(0,2) (1,2) 0.29778
(0,2) (1,1) 0.36516
(1,1) (1,2) 0.32468
(1,1) (2,1) 0.32468
(1,1) (2,0) 0.36516
(2,0) (2,1) 0.29778
(2,0) (3,0) 0.33887
(0,3) (0,4) 0.38789
(0,3) (1,3) 0.33723
(0,3) (1,2) 0.39379
(1,2) (1,3) 0.38941
(1,2) (2,2) 0.37069
(1,2) (2,1) 0.40825
(2,1) (2,2) 0.37069
(2,1) (3,1) 0.38941
(2,1) (3,0) 0.39379
(3,0) (3,1) 0.33723
(3,0) (4,0) 0.38789
(0,4) (0,5) 0.41806
(0,4) (1,4) 0.37579
(0,4) (1,3) 0.40878
(1,3) (1,4) 0.44209
(1,3) (2,3) 0.41733
(1,3) (2,2) 0.44478
(2,2) (2,3) 0.44262
(2,2) (3,2) 0.44262
(2,2) (3,1) 0.44478
(3,1) (3,2) 0.41733
(3,1) (4,1) 0.44209
(3,1) (4,0) 0.40878
(4,0) (4,1) 0.37579
(4,0) (5,0) 0.41806
(0,5) (0,6) 0.41806
(0,5) (1,5) 0.40271
(0,5) (1,4) 0.40271
(1,4) (1,5) 0.46291
(1,4) (2,4) 0.45245
(1,4) (2,3) 0.46261
(2,3) (2,4) 0.48994
(2,3) (3,3) 0.48628
(2,3) (3,2) 0.48666
(3,2) (3,3) 0.48628
(3,2) (4,2) 0.48994
(3,2) (4,1) 0.46261
(4,1) (4,2) 0.45245
(4,1) (5,1) 0.46291
(4,1) (5,0) 0.40271
(5,0) (5,1) 0.40271
(5,0) (6,0) 0.41806
(0,6) (0,7) 0.38789
(0,6) (1,6) 0.40878
(0,6) (1,5) 0.37579
(1,5) (1,6) 0.44209
(1,5) (2,5) 0.46261
(1,5) (2,4) 0.45245
(2,4) (2,5) 0.48994
(2,4) (3,4) 0.50356
(2,4) (3,3) 0.50356
(3,3) (3,4) 0.51450
(3,3) (4,3) 0.51450
(3,3) (4,2) 0.50356
(4,2) (4,3) 0.50356
(4,2) (5,2) 0.48994
(4,2) (5,1) 0.45245
(5,1) (5,2) 0.46261
(5,1) (6,1) 0.44209
(5,1) (6,0) 0.37579
(6,0) (6,1) 0.40878
(6,0) (7,0) 0.38789
(0,7) (0,8) 0.33887
(0,7) (1,7) 0.39379
(0,7) (1,6) 0.33723
(1,6) (1,7) 0.38941
(1,6) (2,6) 0.44478
(1,6) (2,5) 0.41733
(2,5) (2,6) 0.44262
(2,5) (3,5) 0.48666
(2,5) (3,4) 0.48628
(3,4) (3,5) 0.48628
(3,4) (4,4) 0.50356
(3,4) (4,3) 0.51450
(4,3) (4,4) 0.50356
(4,3) (5,3) 0.48628
(4,3) (5,2) 0.48628
(5,2) (5,3) 0.48666
(5,2) (6,2) 0.44262
(5,2) (6,1) 0.41733
(6,1) (6,2) 0.44478
(6,1) (7,1) 0.38941
(6,1) (7,0) 0.33723
(7,0) (7,1) 0.39379
(7,0) (8,0) 0.33887
(0,8) (0,9) 0.28472
(0,8) (1,8) 0.36516
(0,8) (1,7) 0.29778
(1,7) (1,8) 0.32468
(1,7) (2,7) 0.40825
(1,7) (2,6) 0.37069
(2,6) (2,7) 0.37069
(2,6) (3,6) 0.44478
(2,6) (3,5) 0.44262
(3,5) (3,6) 0.41733
(3,5) (4,5) 0.46261
(3,5) (4,4) 0.48994
(4,4) (4,5) 0.45245
(4,4) (5,4) 0.45245
(4,4) (5,3) 0.48994
(5,3) (5,4) 0.46261
(5,3) (6,3) 0.41733
(5,3) (6,2) 0.44262
(6,2) (6,3) 0.44478
(6,2) (7,2) 0.37069
(6,2) (7,1) 0.37069
(7,1) (7,2) 0.40825
(7,1) (8,1) 0.32468
(7,1) (8,0) 0.29778
(8,0) (8,1) 0.36516
(8,0) (9,0) 0.28472
(0,9) (0,10) 0.23462
(0,9) (1,9) 0.33129
(0,9) (1,8) 0.26321
(1,8) (1,9) 0.26321
(1,8) (2,8) 0.36516
(1,8) (2,7) 0.32468
(2,7) (2,8) 0.29778
(2,7) (3,7) 0.39379
(2,7) (3,6) 0.38941
(3,6) (3,7) 0.33723
(3,6) (4,6) 0.40878
(3,6) (4,5) 0.44209
(4,5) (4,6) 0.37579
(4,5) (5,5) 0.40271
(4,5) (5,4) 0.46291
(5,4) (5,5) 0.40271
(5,4) (6,4) 0.37579
(5,4) (6,3) 0.44209
(6,3) (6,4) 0.40878
(6,3) (7,3) 0.33723
(6,3) (7,2) 0.38941
(7,2) (7,3) 0.39379
(7,2) (8,2) 0.29778
(7,2) (8,1) 0.32468
(8,1) (8,2) 0.36516
(8,1) (9,1) 0.26321
(8,1) (9,0) 0.26321
(9,0) (9,1) 0.33129
(9,0) (10,0) 0.23462
(0,10) (1,9) 0.23462
(1,9) (2,8) 0.28472
(2,8) (3,7) 0.33887
(3,7) (4,6) 0.38789
(4,6) (5,5) 0.41806
(5,5) (6,4) 0.41806
(6,4) (7,3) 0.38789
(7,3) (8,2) 0.33887
(8,2) (9,1) 0.28472
(9,1) (10,0) 0.23462

The vrml world for this example displays a patch which looks like this:

The octahedron has the qualities of a geodesic: its equilateral triangular basis makes it strong, it uses
materials more efficiently that traditional architectures, and as the tessellation frequency increases it more
and more closely approaches its limiting circumscribed sphere. Its projected patches bulge more than the
icosahedral geodesic, but less than the tetrahedral geodesic. This is expected since each patch covers an
eighth of a sphere to the tetrhedral's fourth and the icosahedral's twentieth.
However, the truly important quality of the octahedral geodesic is that it aligns with the traditional
architectural forms. Although an octahedral geodesic dome can certainly stand alone, it can also be joined
directly as geodesic living space to an existing
rectangular box structure. Consider a residence, as
pictured on the left; sections of an octahedral, half-
spherical geodesic may be attached to the structure
simply and directly since it can be fabricated in 90o
sections. In A, 3/4 of the dome is attached to extend a
corner. In B, 1/2 of the dome is attached to join to a
side. In C, 1/4 of the dome is attached as a fill-in
between two sides at a corner. These extensions could
be connected to an existing structure relatively easily,
bringing homes built in the past forward into the
geodesic age.

There are many places where rectangular box


construction could be augmented by the spherical dome, as anyone interested in geodesics knows.
However, few can afford the luxury of leveling their house or place of business to construct the more
efficient geodesic structure - and few builders are up to the task of pure geodesic construction. If
prefabricated octahedral geodesic sections could be shipped to a site, assembled into a right-angle-fitting
unit, and attached directly onto the structure, the benefits of geodesic living could be mainstreamed
perhaps a little more quickly.
Externally Octet-Trussed Geodesic Patches
David Anderson
July 1998

One of the reasons I like geodesic structures is the way they look. To me, they're just cool. Take a locally
simple structure and extend it outward, scaling the edges slightly according to some theoretically
staightforward rules, and you have a tesselated surface that curves back on itself - that you can build.
Mathematical elegance in action.

One of the reasons I wrote the software to bend the octet truss for use in geodesic patches (see Planning a
Bigger Dome, Part II) was to support a large geodesic, keeping it from dimpling when radial pressure was
applied. I placed the truss inside the dome, since it made sense that supporting structures should be
underneath the thing they support, and aesthetically, I wanted to preserve the geodesic look on the
outside. Looking back, however, I realize this aesthetic choice might not be pleasing in some cases, and
that the supporting structure does not really support the geodesic by itself - the inner and outer shells are
mutually supportive. The bracing can be moved from the inside to the outside the dome.

If you spend most of your time inside a dome, you want it to look geodesic inside. After all, if you went to
all that time and trouble to put up a geodesic dome instead of a nice rectilinear box, it stands to reason that
you don't want a lot of internal bracing getting in your way, and you don't want to see the patch
connectors on the inside walls. And, there's usually lots of room outside. When the internal space is at a
premium, if you put the struts outside you get more room inside.

To think about this easily, we start by looking at the old internally-trussed world differently. We change
the meaning of the shells we previously designated as inner and outer:

The outer shell which we considered to be the n-frequency geodesic patch becomes the geodesic
shell.

The inner shell which was formed by connecting the top vertices of the inward pointing
tetrahedrons becomes the truss shell.

With this change in logical orientation, it's easy to move the truss to the outside by making the
tetrahedrons point outward instead of inward. In the code, this simply amounts to changing a sign from
minus to plus. Instead of subtracting the stretched height of the tetrahedron from the truss point's radius, it
is added. The geodesic shell becomes the inner shell, while the truss shell becomes the outer.

Keeping with the coloring used in earlier paper (geodesic shell is white, truss shell is red, and shell
connectors are pink) links to the vrml views and html tables for geodesic examples, are given below. The
vrml and html are given for 5-frequency geodesics with a untesselated side length of 3 units. In addition, a
set of twenty-four viewpoints is provided to enhance your vrml experience.
Vrml World Html Tables

tetra-5-3.wrl tetra-5-3.html
octa-5-3.wrl octa-5-3.html
icosa-5-3.wrl icosa-5-3.html

I can imagine space where the inner surface of the geodesic surrounds premium space, while the external
structure can be used as scaffolding: to attach rigging and support facilities. Simple living spaces have
these needs, but space or underwater vehicles come to mind as well. If both the shells were covered, and
appropriately pressurized, the space in between could be used for many purposes, to hold storage closets,
vessels, or even machinery. It could be a space for ductwork, or material or electrical transport - out of
site to observers on the inside or the outside, but necessary to the smooth operation of any house or
vehicle. And since the trussed geodesic patches could be prefabricated (each patch could be built whole,
or as sections of tesselations) they could be shipped to a remote site and then assembled into possibly very
large structures.

In the end, mathematically, it doesn't really matter if the bracing is on the inside or the outside of the
geodesic. What matters is the purpose to which the structure will be put.

Circumscribed Spherical Projection


Vertex x y z
(Geodesic,0,0) 0.00000 0.00000 1.83712
(Geodesic,0,1) 0.22875 -0.39620 1.77924
(Geodesic,1,0) 0.22875 0.39620 1.77924
(Geodesic,0,2) Spherical
Circumscribed 0.57735 -1.00000 1.42887
Projection
(Geodesic,1,1)
Vertex 0.68825
x 0.00000
y 1.70332
z
(Geodesic,2,0)
(Geodesic,0,0) 0.57735
0.00000 1.00000
0.00000 1.42887
2.12132
(Geodesic,0,3)
(Geodesic,0,1) 0.86603
0.36380 -1.50000
-0.36380 0.61237
2.05798
(Geodesic,1,2)
(Geodesic,1,0) 1.35680
0.36380 -0.78335
0.36380 0.95940
2.05798
(Geodesic,2,1)
(Geodesic,0,2) 1.35680
0.83205 0.78335
-0.83205 0.95940
1.76505
(Geodesic,3,0) 0.86603
0.90453 1.50000
(Geodesic,1,1) Spherical
Circumscribed 0.00000 0.61237
1.91881
Projection
(Geodesic,0,4)
(Geodesic,2,0) 0.91499
0.83205 -1.58481
0.83205 -0.16175
1.76505
Vertex x y z
(Geodesic,1,3)
(Geodesic,0,3)
(Geodesic,0,0) 1.37649
1.24808
0.00000 -1.19208
-1.24808
0.00000 -0.24333
1.17670
2.85317
(Geodesic,2,2)
(Geodesic,1,2)
(Geodesic,0,1) 1.80907
1.50000
0.45513 0.00000
-0.50000
-0.33067 -0.31980
1.41421
2.79716
(Geodesic,3,1)
(Geodesic,2,1)
(Geodesic,1,0) 1.37649
1.50000
0.45513 1.19208
0.50000
0.33067 -0.24333
1.41421
2.79716
(Geodesic,4,0)
(Geodesic,3,0)
(Geodesic,0,2) 0.91499
1.24808
0.96349 1.58481
1.24808
-0.70001 -0.16175
1.17670
2.59273
(Geodesic,0,5)
(Geodesic,0,4)
(Geodesic,1,1) 0.86603
1.45521
0.99386 -1.50000
-1.45521
0.00000 -0.61237
0.51450
2.67447
(Geodesic,1,4)
(Geodesic,2,0) 1.14374
(Geodesic,1,3) 0.96349 -1.18861
1.80907 0.70001 -0.80875
-0.90453 0.63960
2.59273
(Geodesic,2,3) 1.44338 -0.50000 -1.02062
Visualizing the Bulge in Geodesic Projections
David Anderson
July 1998

A few folks have sent me mail asking me what I meant by the difference in bulges encountered in
geodesic projections. I claimed the icosahedral geodesic bulged less than the octahedral, which in turn
bulged less than the tetrahedral.

The idea is that since all points on the geodesic sphere must be an equal distance from the center, a
geodesic based on a primitive volume with fewer sides must bulge more since the center of the side must
be projected further to reach the geodesic sphere. A reasonable bulge factor probably could therefore be
defined as the distance the center of the side had to be projected divided by the area of the side. Since all
of the primitives we're considering have sides which are equilateral triangles, for a side with a length of 1
the area is /4. This gives a bulge factor of 0.451 for the icoshedron, 0.691 for the octahedron, and 0.943
for the terahedron. Taken this way, the octahedral projection makes bulges 53% more than the icosahedral
projection, and the tetrahedral projection 110% more than the icosahedral and 45% more than the
octahedral projections.

To visually demonstrate this amount of bulge, I created three series of VRML worlds, each based on a
different primitive, featuring green and yellow balls. The red-green-blue axis gives the a reference to the
VRML X-Y-Z directions respectively. In each world, the set of green balls make up the unprojected mesh
which constitute an n-frequency side of the underlying primitive. The centers of these balls align on the
mesh. The centers of the set of yellow balls lie on the geodesic, projected in a straight line from the center
of the primitive. In addition to all this, the size of each of the yellow balls has been scaled in direct
proportion to the distance they were projected to reach the sphere. You should note that since the balls on
the corners of the patch are already on the surface of the geodesic, they do not need to be projected, and
thus are green.

2 frequency 5 frequency 10 frequency 20 frequency


Tetrahedral tetra-2-4.wrl tetra-5-4.wrl tetra-10-4.wrl tetra-20-4.wrl
Octahedral octa-2-4.wrl octa-5-4.wrl octa-10-4.wrl octa-20-4.wrl
Icosahedral icosa-2-4.wrl icosa-5-4.wrl icosa-10-4.wrl icosa-20-4.wrl

So, if this helps you visualize what is meant by bulge, great. If not, then simply enjoy the most excellent
graphics.
Geodesic Constructions
or
How To Hurt Your Hands Via Mathematics
David Anderson
November 1998

Doing geodesic mathematics is one thing; actually making stuff is art. The following pictures are some of
the models and structures I've made over the last year. It's a lot of fun, but it's also intricate work
sometimes... And you can skin a few knuckles, and turn your fingers to raw meat bending pipe cleaners...

Note that this document may take time to download; if you get tired of waiting, feel free to grab a cup of
coffee.

Also, many thanks to my friend Bob Schulze, who scanned the images for me. I owe you a beer, Bob.

The first dome I tried building was made of popsicle sticks and wire. It was a good idea, but the sticks
weren't long enough to distribute the error of the hieghts of the stack at a vertex. I saved it for posterity...

Most of the world's geodesics are based on the icosahedron. Here is a soda straw and pipe cleaner model...
The main project was the bolted PVC pipe framework for the greenhouse. The dome is 2-frequency, semi-
spherical and 11 feet in diameter...
The vertices are connected with a 1/4 inch bolt through the front and fastened in the back with a wing nut
for quick assembly. The front of a joint...

The back of a joint...


The most interesting work I did was the planning of a large dome. This required the warping of the octet
truss; the truss is warped proportionally though, maintaining its maximum strength to resist radially
applied forces. The large dome was planned at 10-frequency with an internal truss; the coffee stirrer and
pipe cleaner model is 6-frequency. Two patches were constructed and connected by a ladder of struts.

Front view, straight on...

Front 3/4 side view...


Rear 3/4 side view at an angle...

Finally, a semi-completed tetrahedral geodesic sphere is modeled, with an internal truss...


Constructing Geodesic Patch Surfaces, Part I
David Anderson
December 1998

Once the chord lengths of a geodesic patch have been determined, models have been created, and
structures of various sizes, frequencies, and underlying geometries have been designed and built, the mind
drifts to other things. Over the summer and in early fall, I slipped into a correspondence mode; I spent
time answering questions and instructing others in the Geodesic Arts rather than creating new techniques.

But recently my flames have been stoked by my collaborator, and I have turned my attentions back to
creative mathematics.

Since the mathematical problem of building a multi-layer geodesic skeleton is now generally solved,
developing a covering for the skeleton is a logical next step. The unit of construction for our geodesic
frames has been a patch - a single side of a triangularly-tesselated icosahedron, octahedron or tetrahedron.
This patch may include an internal or external supporting truss system to resist radially applied forces, but
the surfaces we intend to cover all have the similar characteristics. By replicating patches for each
triangular surface of the underlying polyhedron (20 for the icosahedron, 8 for the octahedron, or 4 for the
tetrahedron) the entire volume can be uniformally covered.

My mind is always on economy, of course: call me cheap, but I want my experiments to be affordable!
What we look to do is to construct a covering for a patch with a single sheet of material - a sheet which
has been cut to the right shape and size so it can be "stitched" together into a geodesic skin which will
exactly fit the underlying framework - with a minimum amount of waste. Every bit of the covering which
must be cut away and discarded is money down the tubes, and I'd rather spend my money on the ones I
love than to throw it away on unused materials. Mathematically, it is unimportant what material we use,
as long as it can be cut from a pattern and folded into the right shape.

Our other goal is not to do this for just a given-frequency geodesic - but for any frequency. The
development of the surfaces should be simple; complexity should emerge out of a simple schematic
pattern. In order to make a covering from a single sheet, a path made of a number of straight cuts must be
made so that it may be folded into shape. The simpler the path, the simpler the pattern, the easier it will be
to fabricate, and the quicker satisfaction will come. Satisfaction should never be neglected - it is a very
important aspect of life in the geodesic age!

Probably the simplest pattern for the cutting of a path is a spiral:


The spiral pattern

This 24-frequency skin has a single spiral cut in it, indicated by the red line, starting at the bottom left and
proceding clockwise to the center. Or, looked at the other way around, we have a cut spiralling outward
counter-clockwise from the center. This second perspective is especially useful; embedded in this 24-
frequency template are all of the lower frequency templates. The center triangle (the small green one) has
no cuts, the 2-frequency triangle (the green triangle plus the three pink ones) also has no cuts, and the
three-frequency triangle (formed by adding the five blue ones) has a single cut in it. As sides are added to
the center triangle in the clockwise direction, you can see how the spiral lengthens.

Notice that this figure represents the path in an unprojected schematic - it is easier to think about the form
this way, before the projection of vertices onto the circumscribing sphere has taken place. Our technique
will be to determine where the cuts on our n-frequency schematic will be, project it onto the
circumscribing sphere, and then flatten it out into a pattern which may be cut from the material of choice.
Once projected, each of these triangles will have a different size, and after being mathematically flattened
into a pattern and reproduced, geodesic patches will be able to be cut out and folded into shape.
There are a few interesting things to notice about the cutting. Because a flat shape will be projected onto a
curved three dimensional surface, the sum of the angles around any vertex will be less than 360 degrees.
When the projected face is flattened to become the template for making our covering, the cuts will widen
and the area in-between will be waste. A pie-slice will need to be removed at each vertex to get rid of the
overlap. Translating this logic back to our template, this says that since each internal vertex in a patch
must have a pie-slice extracted, there must be a cut to it. As you can see by
inspecting the spiral case, this is true. However, the spiral case wastes a lot
of material. Imagine the projection of the spiral schematic and its
subsequent flattening onto a sheet for cutting. As the spiral moves away
from the center, the gap along the cut edge widens more and more - as the
frequency increases, this waste increases dramatically. In fact, the spiral is
the worst case scenario: it is the upper bound on waste when cutting from
one sheet.

Since the number of internal vertices V in an n-frequency triagular mesh is


there must be V cuts to reach all the vertices in a single sheet. Fewer cuts and all vertices could not
be reached; more cuts and the sheet would be cut into two or more pieces. If you care to count in the 24-
frequency case above, there are 253 internal vertices, and 253 cuts.

Using an engineering eye, it seems that in this kind of growth, the corners of each progessively
frequencied surface get progressively further from the center. If a line is drawn from the outermost corner
to the center triangle without crossing a cut, in the spiral case it must pass through every triangle! In the
case of our 24-frequency example, that is 576 triangles - quite a distance.

To waste less material, it is suggested that if the corners were kept closer to the center (in terms of
shortest triangle-distance) then there would be less overall pattern growth and hence less waste. Since
there are three corners, then the three straight lines from the corners to the centers indicate the paths
which should not be cut. If cuts were made across these lines, then the corner-to-center non-cut-
intersecting path would be longer than the minimum and there would be more waste than necessary.

Since these boundaries extend from center to corner, there are three subareas of the triangle to consider:
the red, green, and blue areas as shown in the diagram. And of course, since minimizing waste in one
subarea means minimizing waste in all three subareas, they should be symmetric. This symmetry implies
that the subareas must grow uniformally - if a new row of triangles is added to one, it must also be added
to the other two. This symmetry-preserving constraint implies that the frequency of the template must
grow in steps of three rather than in steps of one, as in the spiral case. We must therefore partition our
frequency-template space into three groups:

Group-1, which is centered around a single triangle,

Group-2, which is centered around a 2-frequency triangle, and

Group-3, which is centered around a 3-frequency triangle.

A nice feature to add to these groups would be the notion of incremental growth; there is no reason not to
expect it: at the next frequency interval, the pattern should extend outward in-concert with what has come
before. By implementing a recursive, incremental growth scheme, little work will need to be done to
arrive at the cutting pattern for the next-higher frequency-increment.

So we'll take a first stab; we'll call this set of recursive patterns Stagger since they seem to stagger left and
then right in subsequent increments...

A Group-1 partition
Stagger-1
(1, 4, 7, 10, 13, 16, 19, and 22 frequencies shown)

A Group-2 partition
Stagger-2
(2, 5, 8, 11, 14, 17, 20, and 23 frequencies shown)
A Group-3 partition
Stagger-3
(3, 6, 9, 12, 15, 18, 21, and 24 frequencies shown)

The cut-colors differentiate the symmetrical sets of the separate subareas: red, green, and blue. The only
non-symmetric cut occurs in Group-3, in the center, where only a single internal vertex exists; this one
asymmetry does not affect the symmetric growth of any of the subsequent frequency-increments. This cut
must be present in all Group-3 variants.

Looking at these and comparing them with the spiral, another interesting notion comes to mind: the
shorter a path is, the less it can spread out into wasted space. As we can see in the Stagger partitions, the
paths are relatively short, but not optimal. By adjusting the branches a little, we can come up with a
shorter set of paths - we'll label them as Shortest since they seem to be at least one of the instances of the
schematics with the shortest possible total cut-path length.

A Group-1 shortest-cuts-path partition


Shortest-1
(1, 4, 7, 10, 13, 16, 19, and 22 frequencies shown)

A Group-2 shortest-cuts-path partition


Shortest-2
(2, 5, 8, 11, 14, 17, 20, and 23 frequencies shown)

A Group-3 shortest-cuts-path partition


Shortest-3
(3, 6, 9, 12, 15, 18, 21, and 24 frequencies shown)

This pattern is optimal for the path length, because each internal vertex is linked to the edge with the
minimum number of intervening vertices. But when we take the number of schematic cuts into account
(used as a rough measure of the schematic's complexity) we find we are still doing more cutting than we'd
like. The fewer cuts we need to make, the easier it should be to fabricate, at least conceptually. By
adjusting the branches once more, we come up with an optimal set of recursive groups with a minimum
number of cuts - they'll be called Sweetest.

A Group-1 fewest-shortest-cut-path partition


Sweetest-1
(1, 4, 7, 10, 13, 16, 19, and 22 frequencies shown)

A Group-2 fewest-shortest-cut-path partition


Sweetest-2
(2, 5, 8, 11, 14, 17, 20, and 23 frequencies shown)
A Group-3 fewest-shortest-cut-path partition
Sweetest-3
(3, 6, 9, 12, 15, 18, 21, and 24 frequencies shown)

A metric of the average distance of cuts in the different patterns can be developed as the sum of the
lengths from an edge divided by the total number of paths. The pattern with the smallest value of this
metric should yield the least waste.

Average Distance to Internal


Internal Number of Straight Cuts
Frequency Vertex
Vertices
Spiral Stagger Shortest Sweetest Spiral Stagger Shortest Sweetest

3 1 1.0 1.00 1.00 1.00 1 1 1 1


4 3 2.0 1.00 1.00 1.00 2 3 3 3
5 6 3.5 1.50 1.00 1.00 3 6 6 6
6 10 5.5 1.40 1.10 1.10 4 10 10 9
7 15 8.0 1.60 1.20 1.20 5 12 12 12
8 21 11.0 1.71 1.29 1.29 6 18 18 15
9 28 14.5 1.82 1.39 1.39 7 22 22 18
10 36 18.5 1.92 1.50 1.50 8 27 27 21
11 45 23.0 2.06 1.60 1.60 9 36 36 24
12 55 28.0 2.14 1.71 1.71 10 40 40 27
13 66 33.5 2.27 1.82 1.82 11 45 45 30
14 78 39.5 2.34 1.92 1.92 12 57 57 33
15 91 46.0 2.49 2.03 2.03 13 61 61 36
16 105 53.0 2.60 2.14 2.14 14 69 69 39
17 120 60.5 2.73 2.25 2.25 15 84 84 42
18 136 68.5 2.82 2.36 2.36 16 88 88 45
19 153 77.0 2.94 2.47 2.47 17 96 96 48
20 171 86.0 3.05 2.58 2.58 18 114 114 51
21 190 95.5 3.16 2.69 2.69 19 118 118 54
22 210 105.5 3.27 2.80 2.80 20 129 129 57
23 231 116.0 3.39 2.91 2.91 21 150 150 60
24 253 127.0 3.51 3.02 3.02 22 154 154 63

As can be seen from the table, of the symmetric-recursive patterns, the Sweetest groups win on both our
average cut length metric and has the simplest schematic straight-cut structure.

Up to this point we've made a lot of assumptions about the results of applying connectivity, group theory,
and a bunch of other mathematics. Although I believe all these ideas make sense, they deserve some
validation before time is spent projecting and flattening the figures. Part 2 of this series will concern itself
with proving some of these geometric ideas; once we have some surity, we will continue onto making the
templates in Part 3.
Constructing Geodesic Patch Surfaces, Part II
David Anderson
March 1999

How can the waste of a geodesic covering be calculated? That question has a straightforward answer and
the calculations are not too difficult. And the identfication and derivation of some characteristic constants
for the platonic solids make it all very interesting.

When we are going to manufacture a geodesic covering from a template, waste is everything we cut away
and don't need. Waste has a special status from the Fullerean geodesic perspective - minimum waste is
important since it represents the natural state; nature tries to minimize energy expenditure and material
usage - it gets the most out of the least. This idea has a lot of appeal and seems like a reasonable goal for
our efforts.

By using this waste-is-unused-material definition, the calculation of waste may be made directly: the
waste of a geodesic patch covering when cut from a single sheet is equal to the fraction of the flattened
surface area of the sphere the patch covers minus the total area of the subfaces of the patch. The
calculation for each type of geodesic patch may be approached the same way - it does not matter whether
the patch is tetrahedral, octahedral, or icosahedral; the waste always equals the flattened spherical surface
fraction minus the total subface area.

In our derivation we will use either the shortest or sweetest configurations from Part I. The number of cuts
to an internal vertex along subface edges is minimum in these configurations, and the line between a
corner and a center is uninterrupted. These characteristics insure that the average schematic length of a
path to an internal vertex is minimized. Other cutting schemes which have this property may be used; they
will have the same minimal average schematic path length. Without this sort of requirement, the convex
hull of the schematic patch could grow unbounded as frequency increases.

Before we descend deeper into the wasteland, we will get geodesic surface area convergence out of the
way.

It seems reasonable that as the frequency of a geodesic patch increases, there is a limit to its surface area -
otherwise as the frequency increased it would cover an infinite region. The limit is the corresponding
fraction of the surface area of the circumscribed sphere which the patch approaches. As the geodesic
subfaces are successively divided into smaller and smaller triangles the projection more and more closely
approaches the surface of the circumscribing sphere, and the difference between the sphere's surface area
and the surface area of the geodesic will decrease. At the limit, when the geodesic frequency becomes
infinite, the difference will vanish.

One of the conveniences of working with a patch is that the basic projection mathematics is the same for
each equilaterally-faced platonic solid; only the fraction of coverage of the circumscribing sphere is
different. It takes four patches to cover a sphere tetrahedrally, eight octahedrally, and twenty
icosahedrally. Since the surface area of a sphere is , the tetrahedral patch covers , the octahedral
patch covers , and the icosahedral patch covers .

To show the convergence of the geodesic to the ideal, this table illustrates how increasing the frequency
of the geodesic patch brings the surface area closer to the theoretical limit. We set the radius of the solid
equal to one to make the results easier to see:

Surface Area Covergence for Geodesic Patches with respect to Frequency

Geodesic Tetrahedral Octahedral Icosahedral


Frequency Patch Area Patch Area Patch Area

1 1.15471 36.756 % 0.86602 55.133 % 0.47873 76.192 %


2 2.11258 67.246 % 1.30221 82.902 % 0.58329 92.833 %
3 2.60632 82.962 % 1.44066 91.716 % 0.60753 96.691 %
4 2.76482 88.007 % 1.49332 95.068 % 0.61645 98.111 %
5 2.88451 91.817 % 1.52008 96.772 % 0.62027 98.719 %
6 2.95679 94.118 % 1.53513 97.729 % 0.62299 99.152 %
7 3.00137 95.537 % 1.54439 98.319 % 0.62439 99.375 %
8 3.03247 96.527 % 1.55047 98.706 % 0.62531 99.521 %
9 3.05430 97.221 % 1.55468 98.974 % 0.62594 99.621 %
10 3.07023 97.729 % 1.55771 99.167 % 0.62639 99.693 %

20 3.12322 99.415 % 1.56749 99.790 % 0.62783 99.922 %

50 3.13865 99.906 % 1.57026 99.966 % 0.62824 99.987 %

100 3.14088 99.977 % 1.57066 99.992 % 0.63830 99.996 %

3.14159 100 % 1.57079 100 % 0.62832 100 %


It is interesting to note the rate of convergence. Though all the surfaces converge as the frequency
increases, they converge at different rates. The icosahedron starts out closer to the shape of a sphere than
either the tetrahedron or octahedron, and by the time the
frequency is six, the surface area is within 1% of the
maximum surface area. However, this statistic must be
tempered with the observation that the same frequency
icosahedral geodesic sphere contains 2.5 times more
subfaces than an octahedral geodesic sphere, and 5
times more subfaces than a tetrahedral geodesic sphere.

The calculation of waste is centered around flattening a


geodesic patch by making cuts to each internal vertex.
We end up with a template which can be used to create
many patches. Patches are cut from pieces of the
desired material, folded, and then attached along the
cuts. The material which is cut away is the waste we
wish to minimize.

What we are searching for is the theoretical minimum-waste boundary for the template designs which we
determined were the most efficient. As we saw in the convergence table, the surface area of a geodesic
shell converges to a given value for a dome of a given radius. We are able to flatten a spherical section by
modeling it with an infinite-frequency geodesic patch cut according to our template strategy. Since this
infinite-frequency geodesic section has the greatest possible surface area, its flattening should define the
minimum hull which contains all the lower-frequency flattened geodesics and from which the minimum
waste may be calculated.

But how do we flatten an infinite-frequency geodesic patch?

The answer is, of course, not by doing it in any finite way. Since we know the efficient-template strategy
keeps the distance between the edge and center of a geodesic patch at a minimum by cutting the shortest
distance from the edge of the patch to each internal vertex, we can determine the boundary analytically as
a geodesic projection.

What we need to do is determine the boundary of the flattened spherical secion. Once we have this, we
can determine the area contained in this hull. Then we can combine it with the area of the geodesic at
various frequencies - the waste is the difference between this minimum flattened area and the surface area
of the geodesic.

The boundary can be formulated as the distance from the center of the spherical section to its edge in each
direction along the surface of the sphere. We will end up with 360 degrees of distances around the center
which define the boundary we may use to determine area of the flattened region.
We start with an equilateral triangle ABC which has been projected onto the circumscribing sphere.
This becomes an equilateral spherical section corresponding to the projected geodesic patch (either a
quarter of a tetrahedron, an eighth of an octahedron, or a twentieth of an
icosahedron.) The side of
the platonic solid being
projected has corner points
A, B, and C, and a point at
its center D. We make the
point E on the surface of the
sphere the projection of D.
E is the center of the
spherical section from
which we will measure the
distance to the boundary's
edge. The center of the solid
itself is O. The lines OA,
OB, OC, and OE, are all
the same length, the radius
of the sphere.

Again, it is not important which solid we use as a base - each of the tetrahedron, octahedron, and
icosahedron use the same mesh and the same projective geometery; the only difference in our calculations
is the length of the edge for a solid of a given diameter.

Edge Length Scaling Factor

Platonic Solid Radius Multiplier s Numeric Value

Tetrahedron 1.632993
Octahedron 1.414214

Icosahedron 1.051462

The boundary thus becomes the projected boundary of the underlying equilateral triangular side of the
platonic solid. Since the projection is onto a sphere, the shortest path between two points along the
sphere's surface is a part of a great circle - the length of the path is the , where is the angle subtended
by the arc between the points. Of course, will vary depending on the angle which aligns the great circle
in the direction we wish to measure. Therefore is a function of , and we must work through to get the
boundary.

To find the edges of boundary to project, we take a look at ABC. We need to let range completely
around the center to obtain the entire boundary. By conecting the corners A, B, and C to the center D, and
knowing that ABC is equilateral, we find we now have three symmetric triangular regions, ADB,
BDC, CDA. Each of these regions is also symmetric; subdividing BDC, for instance, gives us the
symmetric triangles BDF and CDF, where F is the midpoint of BC.
This substantially reduces the work we need to do to find our
answer - we only need to find the area on the sphere
corresponding to one of the symmetric areas, say CDF and
multiply it by six - need only range over sixty degrees. And
since CDF is a 30-60-90 triangle, and we know the length
of CF is half the length of a side of ABC, , we know the
length of DC is and the length of DF is .

Now things begin to get interesting. As we swing from 0 to


60 degrees, the length of the CF-intercept from D varies. If
we strategically position D at (0,0), then the CF-intercept is at
( , ). The value of is the distance from D to
the CF-interception point:

The key to all this is the value , the length of the CF-
intercept, because we need this to calculate for values in
the range of 0o to 60o. We also need to find d, the distance from
the center of the solid O to the center of the equilateral side
ABC we are projecting. Once we know d, we can find as
.

We find d by considering at 60o. In this situation, the CF-


intercept is coincident with the line DC, the length of the CF-
intercept is , and the distance OC is the radius of the
underlying solid. Knowing this we can calculate d simply from
the Pythagorean theorem.

It is good to see that pops out of the equation so nicely, since


when we combine it with to calculate the arctangent, needs to
cancel out - the angle is independent of the radius of the solid,
of course!

Now we know and d, and thus we know for any between 0o


and 60o. Whew! We shall take it just a little further,

and with a little judicious simplification end up with

If we let , then k is a characteristic constant for each solid, and

a simple result, indeed! For each of our solids, then


Sphere Coverage Scaling Factor

Platonic Solid Characteristic k Numeric Value

Tetrahedron 1.414214
Octahedron 1/ 0.707107

Icosahedron 0.381966

So, now we know the analytic form of the flattened boundary b for a symmetric sixth of the spherical
section:

where ranges from 0o to 60o.

At this point we can take a look at the boundaries. We plot b from 0o to 60o:

By flipping these boundaries and rotating them to get 360o worth:


The red, green and blue areas indicate the symmetric portions of the plot which correspond to the
symmetric portions of our templates in the previous paper.

Some interesting properties about these curves are


apparent when you look at them - the flattened
tetrahedral boundary bulges more than the
octahedral, which in turn bulges more than the
icosahedral. Thinking about it, we'd expect this.
Since the tetrahedral patch has to "wrap" more of the
sphere (twice as much as an octahedral path, and five
times as much as an icosahedral patch) it should have
to be distorted more.

Also notice the scale factors; these diagrams have all


beein normalized so that the distance between the
corners is the same for each boundary. If we
superimpose the boundaries without normalizing, we
can see that for platonic solids with the same radius,
the flattened icosahedral patch is smaller than the
octahedral patch, which in turn is smaller than the
tetrahedral patch. Looking at these superimposed
patches you can see that they form a progression - the
bulge is purely dependent on the characteristic value
k. It leads one to consider whether or not there are
hidden geodesics that would correspond to other k values. But what platonic solids might these
correspond to? Perhaps complex ones which lie in complex space - or maybe even a fractal geodesic
space, where an integral number of faces is not required. Hmmm... That may become the basis for some
further study.

To find the area a of the boundary b, we merely need to solve a radial integral and multiply by six:
Now, the unsatisfying part of this is that there is no known closed-form analytic solution of this integral. I
tried for a while, then I went to integrals.com, then I sent some mail to the folks at Wolfram, the makers
of Mathematica. No luck anywhere. So we have this wonderful integral which I would love to have a nice
simple solution for, but will admit none. Rats. It seems we are stuck using numerical integration to get a
non-exact numeric answer.

Of course, "stuck" is a relative term. Using our friend, the programmable electronic digital computer, we
can do numerical integration to calculate the result pretty closely. Close enough for me, anyway. The
following results are calculated from the sum of 6000 hundreth-degree triangles from 0o to 60o with a
radius of one.

Numeric Integration of Boundary Areas

Flattened Flattened Flattened


Platonic Solid
60o Area Boundary Area Sphere Area

Tetrahedron 0.57564 x6 3.45383 x4 13.81532


Octahedron 0.27449 x6 1.64693 x8 13.17544
Icosahedron 0.10678 x6 0.64066 x 20 12.81323

These values are very close to those we would calculate if we knew a closed form solution of the integral -
the results above were calculated at various angular resolutions to make sure there was convergence.

Given these values, we finally know what we need to know to calculate the waste!

Waste: the Difference between the Boundary Areas


and the Infinite-Frequency Geodesic

Flattened Flattened Percent


Platonic Solid
60o Area Boundary Area Waste

Tetrahedron 0.05204 x6 0.31225 9.04


Octahedron 0.01269 x6 0.07614 4.62
Icosahedron 0.00206 x6 0.01236 1.93
The waste values in this table are the minimums, since frequencies lower than infinity do not as closely
approach a sphere, and the overall waste will be greater. We also see that in terms of waste, the
icosahedral geodesics are the most efficient it terms of coverings. A covering made of patches which are
cut from our icosahedral template will have a theoretical minimum waste of less than two percent - a very
efficient use of materials!

We can see that although we are not going to be creating infinite frequency geodesics, we can use the
results with our convergence data to calculate waste values for lower frequency geodesics. The important
point is that we can predict our use of materials and the waste of the most efficient patch templates - and
also that if we manufacture our geodesic skins from flat sheets, there must be waste!

So it seems we have it!

We can now proceed comfortably to making our geodesic coverings. We know that our designs will scale
with the radius of the geodesic, and that the area of the covering will increase as the square of the radius.
Our intention will be to create scalable geodesic patch templates so that we can have some fun making
geodesic domes and balls.
Constructing Geodesic Patch Surfaces, Part III
David Anderson
April 1999

We know what the geodesic surface templates look like from Part I. We know that they are naturally
efficient. We found characteristic constants and solved the flattening problem for geodesic patches in Part
II. We found the minimum values that bound the waste in these flattened surfaces. We spent some time
pushing the academic envelope.

But that's enough theory - let's make some geodesic shells!

By merging and expanding the same basic geodesic projection Java program I have been carrying around
for over a year, I made it produce the angles between the chords of the geodesic subfaces. Puting together
these figures, the sweetest flattening template, a technical drawing program, scissors, and tape - kazaam!
Geodesic shells, any frequency, scalable to any size.

The following pages feature the flattened shells which you may print, cut out, fold along the lines, and
tape together into a geodesic ball. The first five frequencies of the shell patches for each of the equilateral-
triangularly-faced Platonic solids are given below. (Note the 1-frequency templates are just equilateral
triangles, of course.) Higher frequency patterns or patterns for a particular size implementation might be
had by contacting me about a special arrangement.

Tetrahedron Octahedron Icosahedron

1 frequency Tetra1.gif Octa1.gif Icosa1.gif


2 frequency Tetra2.gif Octa2.gif Icosa2.gif
3 frequency Tetra3.gif Octa3.gif Icosa3.gif
4 frequency Tetra4.gif Octa4.gif Icosa4.gif
5 frequency Tetra5.gif Octa5.gif Icosa5.gif

To make a sphere, you will need to make some additional copies of the octahedral and icosahedral pages -
you need a total of four tetrahedral patches, eight octahedral patches, and twenty icosahedral patches. You
should cut them out carefully - above three-frequency the patterns contain notches. The material in the
notch needs to be removed as well.

Once cut out, all the pieces need to be folded carefully along the lines. These folds should all be in the
same direction, away from you. Next the notches should be taped closed - I always tape from underneath
so it doesn't show. You now have assembled patches.
To finish, the patches need to be connected along their edges. Connect three tetrahedral patches at a
corner, four octahedral patches at a corner, or five icosahedral patches at a corner - remember that the
patches are just projections of the sides of the underlying Platonic solid so the basic geometry of the solid
needs to be preserved for this all to work. Attaching most of the edges is easy; again I tape from
underneath and take care to align the edges precisely. When you get to the last few patches, you are
reaching into the ball to tape it closed, which can be a bit tricky. I end up using a letter opener slid into an
open part of an edge to help.

While you're working (or once it is finished) you may dimple the geodesic accisentally. I have used the
same letter opener to press out deep dimples from inside, but sometimes a little pressure on adjoining
edges can pop a dimple back out. Printing the design on card stock instead of thinner paper will give a
more rigid geodesic structure, less likely to dimple.

I've now constructed many of these shells, as well as many higher frequency geodesics.

The goal of producing these coverings was as a sheath to cover a geodesic skeleton. This sheath could be
for a single-layered geodesic hull, or a multi-layered hull, like the warped octet truss. The skin can go on
an inside or outside surface, but measuring well is an important prerequisite - otherwise the skin will be
baggy or stretched too tight.

But even without a framework to be attached to, making simple models from patches made of folded
paper is quick, easy, and leaves you with a very clean, mathematical artifact.
Calculating Geodesic Radial Vertex
Angles
David Anderson
April 1999

One of the calculations I've neglected to this point is the angle at a vertex between the
center of the circumscribed sphere and it's neighboring vertices. This is not a complex calculation,
especially given all the things that we've been through in some of the other papers, but it used in the
creation of the hubs used in many popular geodesic designs.

Each hub in the geodesic structure points to different set of vertices and is potentially different - we know
the angles between the vertices, but not the angles that adjust the direction below the normal plane at the
vertex on the radial line from the center.

Given the radius and chord length between vertices, we have an isoceles triangle; the distance between the
vertices is the base, the distances between each vertex and the center is the radius. We can find the angle
easily using the law of cosines:

This angle is the same at each vertex of the chord, of course, in accordance with the nature of the isoceles
triangle.

Because this paper is so short, and because I just love to write code, I decided to do it some justice by
adapting the java chordlength code to produce the radial angles. These angles are independent of the size
of the geodesic - as are all angles. The calculation merely depends on the frequency of the geodesic and
the choice of underlying Platonic solid.

The Java code will calculate the radial angles for all the hubs in an n-frequency patch of a given geodesic
type (tetrahedral, octahedral, or icosahedral.) The values for the first five frequencies of each type are
precomputed for your convenience.

Tetrahedron Octahedron Icosahedron

1 frequency Tetra1.html Octa1.html Icosa1.html


2 frequency Tetra2.html Octa2.html Icosa2.html
3 frequency Tetra3.html Octa3.html Icosa3.html
4 frequency Tetra4.html Octa4.html Icosa4.html
5 frequency Tetra5.html Octa5.html Icosa5.html
// Icos.java Copyright 1998 David J. Anderson

// computes the chord lengths and radial angles for an n-frequency geodesic
// patch of a given type

// to compile: javac Geodesic.java

// to execute: java Geodesic t n


// where t is the type (i = icoshedral, o = octahedral, t = tetrahedral),
// n is the frequency

// outputs an html document containing the vertex and radial angle information

import java.lang.Math;
import java.util.Hashtable;

class Rounding
{
public static String toString (double d, int place)
{
if (place <= 0)
return ""+(int)d;
String s = "";
if (d < 0)
{
s += "-";
d = -d;
}
d += 0.5*Math.pow(10,-place);
if (d > 1)
{
int i = (int)d;
s += i;
d -= i;
}
else
s += "0";
if (d > 0)
{
d += 1.0;
String f = ""+(int)(d*Math.pow(10,place));
s += "."+f.substring(1);
}
return s;
}
}

class SPoint // Spherical coordinate point


{
public double radius;
public double theta;
public double phi;

public SPoint (double radius, double theta, double phi)


{
this.radius = radius;
this.theta = theta;
this.phi = phi;
}

public CPoint cPoint ()


{
double x;
double y;
double z;
x = radius*Math.cos(theta)*Math.sin(phi);
y = radius*Math.sin(theta)*Math.sin(phi);
z = radius*Math.cos(phi);
return new CPoint(x,y,z);
}
}

class CPoint // Cartesian coordinate point


{
public static final CPoint origin = new CPoint(0.0,0.0,0.0);

public double x;
public double y;
public double z;

public CPoint (double x, double y, double z)


{
this.x = x;
this.y = y;
this.z = z;
}

public double distanceTo (CPoint cPoint)


{
double xdiff = cPoint.x-x;
double ydiff = cPoint.y-y;
double zdiff = cPoint.z-z;
return Math.sqrt((xdiff*xdiff)+(ydiff*ydiff)+(zdiff*zdiff));
}

public SPoint sPoint ()


{
double radius;
double theta;
double phi;
radius = distanceTo(CPoint.origin);
theta = (x == 0.0)? 0.0 : Math.atan2(y,x);
phi = Math.acos(z/radius);
return new SPoint(radius,theta,phi);
}

public void translate (double dx, double dy, double dz)


{
x += dx;
y += dy;
z += dz;
}
}

class IcosahedralGeodesic
extends Geodesic
{
public IcosahedralGeodesic (int n, double s)
{
this.n = n;
this.s = s;
d = s*0.9510565162951534;
topCorner = new CPoint(0,0,d);
leftCorner = (new SPoint(d,-Math.PI/5.0,1.107148717940909)).cPoint();
rightCorner = (new SPoint(d,Math.PI/5.0,1.107148717940909)).cPoint();
}

public String getTypeName ()


{
return "Icosahedral";
}
}

class OctahedralGeodesic
extends Geodesic
{
public OctahedralGeodesic (int n, double s)
{
this.n = n;
this.s = s;
d = s*0.7071067811865;
topCorner = new CPoint(0,0,d);
SPoint leftCornerS = new CPoint(.5,-.5,0).sPoint();
leftCornerS.radius = d;
leftCorner = leftCornerS.cPoint();
SPoint rightCornerS = new CPoint(.5,.5,0).sPoint();
rightCornerS.radius = d;
rightCorner = rightCornerS.cPoint();
}

public String getTypeName ()


{
return "Octahedral";
}
}

class TetrahedralGeodesic
extends Geodesic
{
public TetrahedralGeodesic (int n, double s)
{
this.n = n;
this.s = s;
d = s*0.6123724356958;
topCorner = new CPoint(0,0,d);
SPoint leftCornerS =
new CPoint(.2886751345948,-.5,-.2041241452319).sPoint();
leftCornerS.radius = d;
leftCorner = leftCornerS.cPoint();
SPoint rightCornerS =
new CPoint(.2886751345948,.5,-.2041241452319).sPoint();
rightCornerS.radius = d;
rightCorner = rightCornerS.cPoint();
}

public String getTypeName ()


{
return "Tetrahedral";
}
}

abstract public class Geodesic


{
protected int n;
protected double s;
protected double d;
protected Hashtable cPoints = new Hashtable();
protected CPoint topCorner;
protected CPoint rightCorner;
protected CPoint leftCorner;

abstract public String getTypeName ();

public void mesh ()


{
double incX = (leftCorner.x-topCorner.x)/n;
double incY = (rightCorner.y-leftCorner.y)/n;
double incZ = (leftCorner.z-topCorner.z)/n;
double x;
double y;
double z;
String label;
for (int i = 0; i <= n; i++)
{
z = topCorner.z+(incZ*i);
x = topCorner.x+(incX*i);
for (int j = 0; j <= i; j++)
{
y = -((incY*i)/2.0)+(incY*j);
label = getLabel(j,i-j);
cPoints.put(label,new CPoint(x,y,z));
}
}
}

public String getLabel (int row, int column)


{
return "("+row+","+column+")";
}

public void project ()


{
String label;
SPoint sPoint;
CPoint cPoint;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
sPoint = ((CPoint)cPoints.get(label)).sPoint();
sPoint.radius = d;
cPoint = sPoint.cPoint();
cPoints.put(label,cPoint);
}
}

public String getAboveLeftLabel (int row, int column)


{
int destinationRow = row-1;
if (destinationRow < 0)
return null;
return getLabel(destinationRow,column);
}

public String getAboveRightLabel (int row, int column)


{
int destinationColumn = column-1;
if (destinationColumn < 0)
return null;
return getLabel(row,destinationColumn);
}

public String getLeftLabel (int row, int column)


{
int destinationRow = row-1;
int destinationColumn = column+1;
if ((destinationRow < 0)||(destinationColumn > n))
return null;
return getLabel(destinationRow,destinationColumn);
}

public String getBelowLeftLabel (int row, int column)


{
int destinationColumn = column+1;
if (row+destinationColumn > n)
return null;
return getLabel(row,destinationColumn);
}

public String getBelowRightLabel (int row, int column)


{
int destinationRow = row+1;
if (destinationRow+column > n)
return null;
return getLabel(destinationRow,column);
}

public String getRightLabel (int row, int column)


{
int destinationRow = row+1;
int destinationColumn = column-1;
if ((destinationRow > n)||(destinationColumn < 0))
return null;
return getLabel(destinationRow,destinationColumn);
}

protected double labelAngle (CPoint cPoint, String pointLabel)


{
return Math.acos(chordLength(cPoint,pointLabel)/(2*d));
}

protected double chordLength (CPoint cPoint, String pointLabel)


{
return cPoint.distanceTo((CPoint)cPoints.get(pointLabel));
}

public void angles ()


{
String label;
String aboveLeftLabel;
String aboveRightLabel;
String leftLabel;
String rightLabel;
String belowLeftLabel;
String belowRightLabel;
CPoint cPoint;
double angle;
int count;
boolean putRow;

System.out.println();
System.out.println
("<CENTER><P><TABLE BORDER=1 CELLPADDING=3 CELLSPACING=3 BGCOLOR=ffffdd>");
System.out.println
("<TR
ALIGN=CENTER><TD><B>Radial<BR>Vertex<TD><B>Neighbor<BR>Vertex<TD><B>Angle</B><BR>radi
ans (degrees)<TD><B>Chord Length</B><BR>(platonic edge = 1)");

for (int i = 0; i <= n; i++)


for (int j = 0; j <= i; j++)
{
label = getLabel(j,i-j);
cPoint = (CPoint)cPoints.get(label);
count = 0;
aboveLeftLabel = getAboveLeftLabel(j,i-j);
if (aboveLeftLabel != null)
count++;
aboveRightLabel = getAboveRightLabel(j,i-j);
if (aboveRightLabel != null)
count++;
leftLabel = getLeftLabel(j,i-j);
if (leftLabel != null)
count++;
rightLabel = getRightLabel(j,i-j);
if (rightLabel != null)
count++;
belowLeftLabel = getBelowLeftLabel(j,i-j);
if (belowLeftLabel != null)
count++;
belowRightLabel = getBelowRightLabel(j,i-j);
if (belowRightLabel != null)
count++;
putRow = false;
System.out.print
("<TR ALIGN=CENTER VALIGN=TOP><TD ROWSPAN="+count+">"+label);
if (aboveLeftLabel != null)
{
angle = labelAngle(cPoint,aboveLeftLabel);
System.out.println
("<TD>"+aboveLeftLabel+"<TD>"+Rounding.toString(angle,5)+
" ("+Rounding.toString(angle*180.0/Math.PI,3)+")<TD>"+
Rounding.toString(chordLength(cPoint,aboveLeftLabel),5));
putRow = true;
}
if (aboveRightLabel != null)
{
if (putRow == true)
System.out.print("<TR ALIGN=CENTER>");
angle = labelAngle(cPoint,aboveRightLabel);
System.out.println
("<TD>"+aboveRightLabel+"<TD>"+Rounding.toString(angle,5)+
" ("+Rounding.toString(angle*180.0/Math.PI,3)+")<TD>"+
Rounding.toString(chordLength(cPoint,aboveRightLabel),5));
putRow = true;
}
if (leftLabel != null)
{
if (putRow == true)
System.out.print("<TR ALIGN=CENTER>");
angle = labelAngle(cPoint,leftLabel);
System.out.println
("<TD>"+leftLabel+"<TD>"+Rounding.toString(angle,5)+
" ("+Rounding.toString(angle*180.0/Math.PI,3)+")<TD>"+
Rounding.toString(chordLength(cPoint,leftLabel),5));
putRow = true;
}
if (rightLabel != null)
{
if (putRow == true)
System.out.print("<TR ALIGN=CENTER>");
angle = labelAngle(cPoint,rightLabel);
System.out.println
("<TD>"+rightLabel+"<TD>"+Rounding.toString(angle,5)+
" ("+Rounding.toString(angle*180.0/Math.PI,3)+")<TD>"+
Rounding.toString(chordLength(cPoint,rightLabel),5));
putRow = true;
}
if (belowLeftLabel != null)
{
if (putRow == true)
System.out.print("<TR ALIGN=CENTER>");
angle = labelAngle(cPoint,belowLeftLabel);
System.out.println
("<TD>"+belowLeftLabel+"<TD>"+Rounding.toString(angle,5)+
" ("+Rounding.toString(angle*180.0/Math.PI,3)+")<TD>"+
Rounding.toString(chordLength(cPoint,belowLeftLabel),5));
putRow = true;
}
if (belowRightLabel != null)
{
if (putRow == true)
System.out.print("<TR ALIGN=CENTER>");
angle = labelAngle(cPoint,belowRightLabel);
System.out.println
("<TD>"+belowRightLabel+"<TD>"+Rounding.toString(angle,5)+
" ("+Rounding.toString(angle*180.0/Math.PI,3)+")<TD>"+
Rounding.toString(chordLength(cPoint,belowRightLabel),5));
putRow = true;
}
}

System.out.println("</TABLE></CENTER>");
}

public static void main (String[] arguments)


{
Geodesic geodesic = null;
int n = Integer.valueOf(arguments[1]).intValue();
switch (arguments[0].charAt(0))
{
case 'i':
geodesic = new IcosahedralGeodesic(n,1);
break;
case 'o':
geodesic = new OctahedralGeodesic(n,1);
break;
case 't':
geodesic = new TetrahedralGeodesic(n,1);
break;
}
System.out.println
("<TITLE>Calculations for a "+n+"-frequency "+geodesic.getTypeName()+
" Geodesic Patch</TITLE>");
System.out.println
("<CENTER><H1>Radial Angle Calculations<BR>for a "+n+
"-frequency<BR>"+geodesic.getTypeName()+
" Geodesic Patch</H1></CENTER>");
geodesic.mesh();
geodesic.project();
geodesic.angles();
}
}
Superprojected, Semiprojected and Subprojected
Geodesics
David Anderson
May 1999

One of the reasons I like mathematics is that you can look at something for a long time, examining it from
many different perspectives, but then suddenly slip around and look from the side to notice something
new and bizarre! Geodesics have been boiled down to mathematics in my papers - and now I have snuck
around to one side to change my point of view...

My take on geodesics has been to use a single equilateral side of either the icosahedron, octahedron, or
tetrahedron, tesselate it with a triangular mesh, and project the mesh vertices onto its circumscribing
sphere. To this point, all of the work I've done has centered around the development and use of this of
projection mechanism, and then determining lengths and angles from the results. But like Euclid's
geometric postulates, if one part of the foundation gets modified then an entirely new take on the
mathematics can arise leading to bizarre new forms.

I decided to reformulate the geodesic patch shells as a family of parameterized surfaces. The parameters
describing the platonic solid, geodesic frequency, and edge length had all already been made part of the
calculations - but not the parameters that control the projection.

I've talked about quantifying the bulge of a geodesic projection before - the closer the point being
projected is to the center of the underlying solid the farther it has to be projected to reach the
circumscribing sphere. The distance a point needs to be projected is:

d = rs - ro

where d is the projected radial distance, rs is the radius of the circumscribing sphere, and ro is the original,
unprojected radial distance. The radial distances are found in spherical coordinates - the projected radial
distance is the difference between the projected and unprojected distances.

When we put it in these terms, we can create a parameter p that indicates the "state" of the projection:

r = ro + pd

When the value of p is 0, the patch is unprojected, r = ro. When the value of p is 1, the patch is projected
onto it's circumscribing sphere, r = rs.

We are immediately given to consider what we get when the value of p is not 0 or 1. It is easy to imagine
what this must be like:
 When p is between 0 and 1, the surface is in an intermediate state between the solid and the
sphere; as the parameter varies from 0 to 1, the flat-faced solid inflates to become the sphere. The
geodesic is semiprojected.
 When p is greater than 1, the surface puffs out - the projected distance is exagerated. The higher
the value of the parameter, the more the bulging. The geodesic is superprojected.
 When p is less than 0, the surface puckers. The centers of the sides draw in until they reach the
critical point where p is equal to -ro/d. When this happens the side touches the solid's origin. The
geodesic is subprojected.
 When p is less than -ro/d, the geodesic is degenerate, it's sides passing through each other.

These parametric-projected geodesics make up a continuous family of mathematical forms, and are a lot
of fun to build!

The following pictures are paper models of 7-frequency octahedral "hemispheres", made up of four
patches. The actual patch patterns are available by clicking each picture. If you'd like to make your own,
just make four copies, cut them out, and tape them together, as you did in Constructing Geodesic Patch
Surfaces, Part III. If you want to construct a "sphere", make eight copies.

subprojected

projection parameter = -0.3


The surface puckers.

unprojected

projection parameter = 0.0


The original platonic solid.

semiprojected

projection parameter = 0.5


Inflating to the geodesic.

projected

projection parameter = 1.0


The traditional projection onto the
circumscribing sphere.
superprojected

projection parameter = 2.0


The surface bulges.

The remaining consideration I have is to figure the effect of the parameterization on the warped octet
truss. The trick comes down to recalculating the "stretch factor" - the scalar of the distance above or
below the warped plane of geodesics. The new stretch factor s becomes

s = pd / ro
The new stretch factor maintains the tetrahedral strength of the warped octet truss as the bulge factor
changes.

The following table contains links to VRML worlds featuring 5-frequency tetrahedral geodesic patches
with internal and external warped octet trusses. By clicking a link you will be put into VRML, where the
3D models may be manipulated.

internal external
parameter
truss truss
-0.3 tetra 5 5 -0.3 i tetra 5 5 -0.3 e
0.0 tetra 5 5 0.0 i tetra 5 5 0.0 e
0.5 tetra 5 5 0.5 i tetra 5 5 0.5 e
1.0 tetra 5 5 1.0 i tetra 5 5 1.0 e
2.0 tetra 5 5 2.0 i tetra 5 5 2.0 e

Although the parameterized geodesics are not necessarily anything special, certainly not in the sense that
Fuller developed the spherical geodesic structures, they do have some particular charm. By evolving a
continuous progression of surfaces, an interesting perspective on the projective mathematics has become
apparent - and a new set of buildable structures with interesting characteristic for geodesicists to examine
is now available.

Just the sort of thing that keeps me exploring all this stuff.
Connecting Superprojected and Subprojected
Geodesics Patches
David Anderson
June 1999

As soon as I parameterized the projection of the geodesic patch and


created my first puckered and puffy domes, as described in
Superprojected, Semiprojected and Subprojected Geodesics, I was
struck with the thought of building a dome out of differently-projected
geodesic patches. Some interesting structures could be created: some
parts bulging, some parts dimpling, some almost flat, and some
spherical - the possibilities were tremendous. Of course there were
likely to be mechanical considerations, but these were certainly worth
fighting through! That's what these efforts are all about.

The big problem with the parameterization is that the edges of


differently projected patches do not have the same curvature. The edge needs to be the same for all
patches (which are generated with the same platonic solid, frequency and unprojected edge length) or else
they won't connect together without a seam. For different values of the parameter p, the edges are
differently shaped:

p<0 subprojected the edge dimples


p=0 unprojected the edge is flat
0 < p < 1 semiprojected the edge is rounded
p=1 projected the edge is circular
p>1 superprojected the edge bulges

Unless the values of p are the same, the edges will be mismatched. Only the corners of a patch are
coincident; to connect the mismatched edges, a series of struts would have to be used between the edge
vertices of adjacent patches. This just won't do at all - we dont want connecting stuts on the geodesic
shell.

The first step must be to reformulate the edges. In order to keep the edges the same, the parameterization
must leave them alone. The rest of the projection should blend into the edge smoothly, not abruptly -
some function needs to be found which can be used to bias the projection.
A straightforward solution presents itself. If we use the perpendicular distance from a vertex to an edge,
then the distance function works as a nice, linear multiplier. Since we have three edges of a patch, we
have three distances functions. We will use their normalized product as the blending function:

fv=dadbdc/N

For each vertex in the geodesic mesh, the blending function produces a value that can be used to scale the
projection - scaled so that the vertices on the edges of the patch are not adjusted but the patch's internal
vertices are scaled in proportion to their normalized distance from the edges. The value of N normalizes
the values of the blending functions to be between 0 and 1.

This blending function keeps the shape of the edge the same as it starts from; in the case of our
projections from platonic solids, the edges are unprojected and straight. I decided that I'd like to use
something different. Since I like geodesics, I thought a circular edge was appropriate. So, before applying
the blending function with the projection parameter, I decided to pre-project the platonic vertices onto the
geodesic sphere. By doing this, the our projection changes; we can call it the PFG projection, for
Parameter From Geodesic. The new projection has a different, simpler nomenclature than our original
one:

p<0 subprojected the edge is circular the surface dimples


p=0 projected the edge is circular the surface is spherical
p > 0 superprojected the edge is circular the surface bulges

There is no longer a semiprojected type; the geodesic becomes the single, special basis for the PFG
projection.

It is a simple matter to adjust the software to use the PFG projection. The projected distance is set equal to
the circumscribed sphere's radius plus the product of the projection parameter, the distance between the
platonic solid and the geodesic at that vertex, and the blending function at that vertex. Because the value
of the blending function along the edge is 0, the projected edges will lie on the geodesic.

In transfering the designs to paper shells, we find that the superprojected geodesics follow the same
sweetest pattern we determined previously. I laid it out according to the templates which were developed
in Constructing Geodesic Patch Surfaces, Part I and had no problem at all. However, when I tried laying
out the subprojected patches I ran into a problem - saddle points!

On a concave or convex surface, the plane which is normal to a point lies completely on one side of the
the surface: the surface curves away in the same manner around the point. When a surface is concave
along one direction at a point, and convex in another, the normal plane divides the surface. If you imagine
orienting yourself to straddle this point, both legs ride the surface down, while the surface bends up ahead
and behind you - just like a saddle.

Saddle points have an interesting consequence when making geodesic paper models. The angles around
regular concave or convex points always total less then 360o in a geodesic because a wedge needs to be
removed to lift it up or sink it below the 2D template plane when it is folded and the gap is closed. When
the vertex is near a saddle point, the angles around it can total more than 360o. Unless the vertex is
bisected, not just opened by a wedge, the flattened pattern cannot be drawn on a flat sheet - you can't fit
more than 360o of angles around a point on a plane.

So, this all means you have to design the template in a much more ad hoc way. Instead of a simple
pattern, you have to work around the saddle points. In some cases, it may even be necessary to divide a
pattern into several pieces and join the resulting subsurfaces.

In order to test joining the patches, I decided to do a little building. I created a few octahedral patch
templates.

I decided to go back to the 7 frequency patches and designed one with a parameter of 2.0, and another
with a parameter of -1.0. The first patch bulges out significantly; the second patch dimples in. I made four
of each and alternated them around the octahedron.

An interesting shape... a tetrahedrally-lobed octahedral geodesic.

Since the edges all join precisely, any projection will work and can be used to create domes with a variety
of shaped patches. Although they don't look traditional, they are certainly fun to build, and add a new
dimension of geodesically-derived shapes.
Blending Functions and Projecting
Geodesic Patches
David Anderson
June 1999

The beauty of the blending function as it applies to projecting geodesic patches is that any smooth
function with a value of zero on the edges can be used. In the previous paper, Connecting Superprojected
and Subprojected Geodesic Patches, the blending function was developed as the normalized product of
three simple distance components: each was the respective perpendicular distance of an unprojected
vertex from an unprojected edge of the geodesic patch. This composite blending function was used to
seamlessly combine patches with different projection parameters.

The simple blending function causes the shape of the patch to change smoothly across its surface, and yet
keep its edges untransformed. Edges of patches with different projection paramters align, and may be
joined together in the same structure without a seam. Unfortunately, the simple blending function is
otherwise uninteresting. Although the product of three variables, it simply changes smoothly and
uniformally, at least from the edge of the patch to its center.

Edge distance is a perfectly good component blending function, of course, but it is effectively only a
simple identity function: b(x) = x, where x is the perpendicular distance of the vertex from the edge. The
essential properties of the component blending function are that it is continuous across the surface of the
patch, and that it's value is 0 on the edge. The simple distance function satisfies these requirements, but
there are other component blending
functions which can produce more
interesting results.

For example, the 15-frequency


icoshedral patch pictured on the left has
a component blending function b(x) =
x2-x3, where x again is the perpendicular
distance of the vertex from the edge.
Instead of a simple smooth curve, we
now see hills and valleys. Click here for
a vrml model of the patch. Though the
component blending function is a only a
polynomial, when it is used in the
composite blending function, effectively
multiplied by itself after being rotated
equilaterally - mixing with itself at 120o
and 240o - a more complex landscape
emerges.

Polynomials are especially nice component blending functions because of all the different curves that can
arise: most any function can be approximated using a polynomial of a high enough degree. However, the
higher the degree, the more the error in the polynomial increases, so other functions may also be useful to
a surface designer. A transcendental function could be used: for instance, b(x) = sin(x) is a function that
meets the blending component requirements. A shifted logarithmic function also qualifies: b(x) = ln(x+1)
will work when x > -1. In fact, there are many other functions that fit the requirements - each potentially
gives a new, interesting shape to the patch.

It also must be noted that the same component blending functions need not be used for each equilateral
direction. Using different component blending functions in the different directions will generally lead to
assymetrically-shaped surfaces. This may be very important if determining a surface that will surround an
irregular volume is required. However, these patches will still be able to be mated with their adjoining
neighbors since the position of the edges is not modified by the projection.

One of the important emergent properties of component blending functions is that since the values are
continuous and the edge boundary condition is set up the way it is, then if b1(x) and b2(x) are component
blending functions, then so is b1(b2(x)). This implies that polynomials, transcendentals, and other
qualifying component blending functions may be convolved without any problems.

Of course, just because we now have a


means to generate geodesic patches with
irregular surfaces doesn't mean we have
to sacrifice structural strength. The
patch pictured on the right has the same
mathematical structure as the previous
patch, but also includes an external
warped octet truss to keep it rigid. This
truss follows the contour of the smooth
hills and valleys of the patch, and it's
hieght varies directly with it's projected
distance.

The truss can be internal or external; it


is based on the same principals that
were used for it's development in
Planning a Bigger Dome, Part II. In these bumpy-patches, the deformation of the constituent
octahedron/tetrahedron matrix is locally regular, despite being relatively irregular globally. As the
frequency of the patch increases, it becomes smoother locally, and the truss system is not projected as far
away from the surface. In the limit, where the frequency of the geodesic becomes infinite, the patch and
truss become one, a solid surface.

At this point, the rest of the exploration is empirical. Different component blending functions may give
very different results, and the resulting surfaces may have applications in many different areas. Cataloging
the composite blending functions would be an entertaining mathematical endeavor, and would lead to a
tremendous repositiory of design information.
Flat-edged Projected
Geodesic Patches
David Anderson
July 1999

Geodesic domes are fun, geodesic domes are cool. But they
are not the only geodesic structures based on projection.

Domes are formulated on the different platonic solids, the twenty-sided icosahedron, the eight-sided
octahedron, and the four-sided tetrahedron. The faces of these structures are equilateral triangles - each is
divided into a mesh of smaller equilateral triangles. When the vertices of these subfaces are all projected
on to sphere that circumscribes the solid, the result is a geodesic structure.

I approached the creation of these structures through geodesic patches: one tesselated face of the solid is
created, replicated, and then is placed edge-to-edge around a vertex to form the surface of the solid. There
are three around a vertex for the tetrahedral geodesic, four for the octahedral, and five for the icosahedral.
As the number of number of subfaces that the face is divided into increases, when they are projected the
figures more and more closely approach their circumscribing spheres.

With the addition of the concepts of projection parameterization, which gave us superprojection and
subprojection, and the creation of the blending function, which enabled us to join differently projected
patches and alter the shapes of patch surfaces, a different universe of geodesic-based forms has been
created. What was formerly simple spherical projection has now evolved into regularly-generated, but
bizarre, geometry.

This patch-based construction is valid for geodesic structures based on the tetrahedron, octahedron, and
icosahedron. The patches are all based on tesselating equilateral triangles: the edges of equilateral faces
are kept in place by the blending function. We've previously projected them onto the circumscribing
sphere and then applied the blending function to hold them in place during the application of the
projection parameter. They need not be held to the sphere; the edges of the faces can be projected onto
any surface prior to application of the blending function.

One of the important parts of building geodesic structures is that they generally need to sit on a flat
surface. Each of the platonic-based geodesics and be divided on such a way that it can sit naturally on a
plane; this can happen either by slicing through certain vertices on the geodesic, or by slicing through
other vertices and sides, and distorting the surface.

For instance, a natural hemispherical geodesic can be realized by cutting along given edges of platonics
with a certain frequency. From the notes in the diagram, an icosahedron of even frequency can be divided
into two equal halves along a great circle; an octahedral half is simply four patches with a common
vertex; and the multiple-of-four frequency tetrahedron can be naturally cleaved by cutting 3/4 of the way
down three patches with a common vertex. The tetrahedral case is even more interesting because the two
halves are not symmetric: one has a single patch vertex at the top of the dome, while the other has three
vertices spaced evenly around the dome, a little up from the bottom. In all of these, the bottoms are
naturally flat; and since this is an angular phenomenon, not a scaling one, patches with different
projection characteristics but that are still based on the same underlying solid and frequency from the
table will still have a flat base.

Since we have worked out the projection mathematics and blending functions for a patch, there is another
way to get a geodesic-projection-based flat patch: we can simply use the blending function prior to the
spherical projection. This will keep the edges of the equilateral face flat. Such a face will have a triangular
footprint, but can be made with all the same strength and materials properties as a part of a geodesic
dome, complete with warped octet truss structures.

For example, the model on the right is a flat-


edged icosahedral patch with a simple third-
order polynomial blending function
modifying a projection parameter. This is
augmented with a warped octet truss. The
structure has a flat triangular base, rises
steeply at the center of the sides, and flattens
nicely for most of its span. (Clicking on the
picture will bring up a VRML world without
the external truss.)

This kind of enclosure reminds me very much


of a covered stadium - it exhibits a strong
structural framework over a large unobstructed area. The truss system would be particularly effective for
snowy areas where the load would challenge many conventional structures. The frequency here has been
kept low for file-size purposes, but if it were pushed up to thirty, the curves would be much more gradual
and the truss profile would be lower.

Flat-edged patches are a different sort of geodesic form. Made up of equilateral trianglular tesselations
which are projected outward onto a surface, they are an animal in the same family; simpler than a dome,
but exhibiting many features which are important for construction in the large.

I'm not saying that cities of the future will have their transitways laid out in a triangular mesh with patch
structures in the blocks, but then again, who knows...
Full Sphere Geodesic Surfaces
David Anderson
August 1999

I have always seemed to end my work with the creation of geodesic patches; I say the patches may be
constructed to fit together into a geodesic shell and pretty much leave it at that. However, building real
structures requires more than just a good word and the wave of a hand. It is time to properly visualizes the
geodesic structures.

So, once again I tore down my geodesic patch code and resurrected it in a compatable, but more capable
form. The new development can create the geometry with any size, frequency, projection parameter, and
blending function coefficients, in either a spherical-edge or flat-edge projection.

But instead of just a single patch, the new code builds all the faces of a sphere: the icosahedral geodesic's
twenty faces, the octahedrals eight, and the tetrahedrals four. The structures may then be rendered into
VRML for a viewer's inspection.

The following images are screen captures of the VRML display:

5 frequency icosahedral geodesic


sphere

5 frequency octahedral geodesic


sphere
5 frequency tetrahedral geodesic
sphere

7 frequency icosahedral geodesic


sphere, with the stadium blending
function, projection parameter of
0.7, and spherical edge projection
7 frequency icosahedral geodesic
sphere, with the stadium blending
function, projection parameter of
0.7, and flat edge projection

The intention of this visualization, as is most computer graphics, is to virtually build viewable models of a
world - instead of actually having to realize them physically. These generation tools may be used to build
virtual models prior to their realization in real materials; these models may be refined and customized to
the needs of a particular real structure.
Spaceframes Part I: Rectangular Spaceframes
David Anderson
August 1999

Recently I have been communitcating with the good folks at StarNet International about Geodesic and
Spaceframe structues. Over the last few months, the president of StarNet, Wendel R. Wendel, has been
kind enough to send me a lot of material on solid geometry, polyhedra construction, and spaceframes.
Given the work I've done lately on generalizing the Java architecture I've written to build and render
geodesics, I found that I could easily make these spaceframes using in the same system by just expanding
the geometry generation mechanisms. This paper is the first part of a series which describes and illustrates
these spaceframes.

Before I go further, you may be asking "Just what is a spaceframe, Dave?" A spaceframe is much like the
geodesic structures I've talked about in other papers. It is a regular system of struts, hubs and panels that is
generally light and strong, and through its use of trianguled supports can support high loads and span
relatively large areas. Spaceframes generally start out flat, and can form a wall, floor or ceiling. However,
they may be curved, and form an arched structure, with the curvature in two or three dimensions; or they
may be bent, twisted, turned - whatever is called for by an application. Simply imagine all the ways you
might take a two dimensional surface and projected it into three dimensions; Spaceframes can be very
versatile indeed!

Wendel's book Spaceframe Basics (available from the StarNet site) describes the geometry and
application of spaceframes. Rather than reproduce it's content here, I cite it now and direct the reader to it
for much more complete information. My treatment of spaceframes is much less detailed...

Spaceframes are based on different geometries. The class of spaceframes I consider in this first paper is
the square/rectangular structures. Generally these structures are based on half of an octahedron, a vertex
supported by its four neighbors. The basic building block figure is a four-sided pyramid; the base of this
pyramid is a square, or a rectangle when scaled.

There are four of these square/rectangular spaceframe architectures: Square1/Rec1, Square2/Rec2,


Square2A/Rec2A, and Square3/Rec3. (The naming convention is standardized SNI nomenclature taken
from Spaceframe Basics.) The rectangular spaceframes are pictured and summarized below; clicking on
the image will bring up a VRML rendering of the frame.

Square2/Rec2 Spaceframe
6 x 8, scaled 1.2:1

Square outer layer over the same square inner


layer set at 45o

This is the classic square/rectangular


spaceframe, fully connected. It is very
regular, strong, but tends to use a lot of
material.

Square2A/Rec2A Spaceframe
6 x 8, scaled 1.2:1

Square outer layer set at 45o over the same


square inner layer

The classic square/rectangular spaceframe


with a half turn, set to fit into a corner.

Square1/Rec1 Spaceframe
6 x 8, scaled 1.2:1

A square outer layer set diagonally on a larger


square inner layer

This is the Square2/Rec2 with the edge cells


left intact, but alternating cells in the rest of
the structure removed. This gives a much
more open feel.

Square3/Rec3 Spaceframe
6 x 8, scaled 1.2:1

Square outer layer over large square inner


layer

This is the Square2/Rec2 with the edge cells


left intact, but with cells only on alternating
rows and columns. This seems to give an
even more open feel than Square1/Rec1, but
is only symmetric if the number of rows and
columns are both odd. (For example, note the
extra row and column that seem out of place
in this 6 x 8 figure.)

Note that these renderings are all scaled to the same degree and have the same number of cells. This is
done only to make comparison easy; any size spaceframe may be readily generated. The limits to the size
of real spaceframes are the types of materials available and the engineering limits of those materials.
Mathematically speaking, these things could go on forever.
All of these structures, and the other classes of spaceframes as well, can be subject to modification - either
through projecting the "surface" into three dimensions, combining multiple spaceframes together, or by
simply moving things around manually. Before considering these manipulations, I will generate the other
spaceframe geometries in the next papers in the series.
Spaceframes Part II: Triangular Spaceframes
David Anderson
September 1999

We now turn our attention from square/rectangular spaceframes to spaceframes based on the geometry of
the triangle. The layers of these spaceframes are fully or partially triangulated; the more the triangulation,
the stronger the structure. The Tri1 - Tri6 structures (again in the SNI nomenclature of StarNet
International) are presented here for your inspection. My treatment again is fairly minimal; the reader is
directed to Wendel's Spaceframe Basics (available through the StarNet web site) for more information.

People do not exist simply on bread and water. The first three triangular spaceframe architectures tend to
be strong and more for structural support, while the last three variations are attempts to be more aesthetic
pleasing. It really comes down to particular application: sometimes a purist perspective of geometry will
win over a more unconventional form, while other times structural strength is not a premium. The world
would certainly be a dull place without variety - even with the added variety of spaceframe and geodesic
structures in the world of standard construction.

The six triangular spaceframe architectures depicted here may be viewed and manipulated in VRML by
clicking on the image.

Tri1 Spaceframe
6 x 8, scaled 1.2:1

Triangular outer layer over offset triangular


inner layer

This is the classic octet truss: alternating


upward and downward pointing tetrahedrons
surrounding octahedrons. It is one of the most
efficient structures ever developed.
Tri2 Spaceframe
6 x 8, scaled 1.2:1

Triangular outer layer over hexagonal inner


layer

The frame is less efficient that the Tri1


architecture, but provides an aesthetically
pleasing hexagonal inner layer.

Tri3 Spaceframe
6 x 8, scaled 1.2:1

Triangular outer layer over large hexagonal


outer layer

This frame is as efficient as the octet truss,


but provides open areas through the large
hexagons.

Tri4 Spaceframe
6 x 8, scaled 1.2:1

Triangular and hexagonal outer layer over


triangular inner layer.

The mix of triangles and hexagons has a


strong appeal, but the strength is reduced
overall.
Tri5 Spaceframe
6 x 8, scaled 1.2:1

Large and small triangular outer layer over


hexagonal inner layer.

The large and small triangles are striking in


this frame, but again, strength has been
sacrificed for looks. The open feel is very
appealing.

Tri6 Spaceframe
6 x 8, scaled 1.2:1

Triangular and hexagonal outer layer over


large triangular inner layer.

Here strength has been reduced substancially,


but the structure is very open and light.

Again, these renderings are all scaled to the same degree and have the same number of cells to make
comparison easy. The spaceframes may be readily generated at any size. These frames may be modified
just as can the square and rectangular spaceframes.

The final installment of this series will consider hexagonal and octagonal architectures.
Geodesic Artifacts
David Anderson
August 2000

Being conspicuously absent from writing papers within the geodesic community for nearly a year due to a
divorce and subsequent work on a geometry creation tool, I've decided it's high time to get back on the
wagon. My first endevour will be to illustrate some of the sorts of geodesic-mathematical artifacts I've
created quickly with the tool, without going into too much detail about their development - that'll come
later.

I've been dealing mostly in the area of transformation - what you get when you modify geometric
structures manually or algebraically. For instance: What do you get when you re-project a geodesic
through an arbitrary point? What does a bent spaceframe look like? What do I need to do to square-off the
edges of a dome? In what interesting ways can I reshape a structure?

And then, how can these structures be realized and actually constructed?

Starting with these thoughts, I've been developing a general geometry-editor. The direction is to allow a
designer to quickly scheme up structures through a mixture of art and mathematics. Since I consider
myself both an engineer and an artist, and a reasonable software developer, I've dedicated the last six
months to following the dream.

Here are some examples of the sorts of structures I've been thinking about. The display of these structures
is done with a nifty little Java applet called Live3D, the brainchild of Martin Kraus. He put it together
while doing some work at Wolfram Research (makers of the wonderful Mathematica product) and it is
used to animate the graphics on Eric Weisstein's masterful World of Mathematics, the best resource I've
ever seen for math.

If you have Java enabled on your browser, you can move the Live3D drawings below simply by using
your mouse. But there is much more in Live3D... see these instructions.

If you have a slow line, these may take a little while to load, but I think it's worth it...
Simple color-coded 4-frequency Icosahedral
Geodesic

No transformations or anything. But isn't it


pretty?

Square2 Spaceframe warped to a region of an


ellipsoid

I created a spaceframe and applied a simple


transform. Fifteen seconds of work.

8-frequency octahedral half sphere, squared


off

Just the thing to cover the plot of land in your


back yard.
Skewed Triangle2 Spaceframe

The beautiful triangle2 spaceframe form, 8x5, with


it's dimensioned skewed from orthogonal.

Modified Terahedral Dome

This one is a little more representative. An 8-


frequency tetrahedral sphere was created, it's bottom
was removed, the bottom layer was evened-up to a
fixed height, and then the same layer was projected
to a constant cylindrical radius. Finally, the smallest
triangles were eliminated, and the struts were
colored according to a length threshhold. Very
simple, very easy.

My next papers will start to detail some of the guts of transformation... Although the stuff is more strictly
mathematical in nature, I'm taking license since I'm applying the to geodesic-geometric structures.
Monkey House Recipes

Chicken poppers take a while to make, but they are really good. You'll end up making a little bit of a mess
if you make them right. My daughter came up with the name, and it suits it. They're like popcorn chicken,
but the coating is different, and they aren't very oily if you let them drain. Although you use a lot of oil,
most of it remains in the pan or drains onto paper towels.

If you like you can put them into salad or serve them over rice to formalize your dining experience. At the
monkey house's kitchen table, we just pop them in; we don't stand on a lot of ceremony here...

Chicken Poppers
Preparation time: 15 minutes
Cooking time: 15 minutes
Serves 4

16 oz Boneless chicken breasts 2 cups Canola oil


1 cup Flour 3 Egg-beater egg-equivalents
2 Tbsp Cayene peper 1 Tbsp Chervil
1 Tbsp Mustard powder 1/2 tsp Ginger
Chop the chicken into bite-sized peices. Place them in a mixing bowl and pour the
eggs over them, stiring them around until they're coated.

In a separate bowl, add the flour, cayene pepper, chervil, mustard powder, and
ginger. Mix them all together.

Pour the oil into a deep pan (I use a wok) and heat it to medium high. If it's hot
enough, a drop of water tossed into it will spit like crazy. Be careful - hot oil will
cook you just like a piece of chicken if you spill it on yourself...

Using a slotted spoon, gather up about a third of the chicken pieces and dredge them
though the flour mixture, coating them completely. Then scoop them into hot oil;
Wow - listen to it crackcle! Stir them after about 2 minutes to make sure no stray
chicken gets away. After about 5 minutes, spoon them out onto a drying rack with a
paper towel underneath. Dredge and cook the next third, and then the last.

Serve the poppers with your favorite sauces. I like mustard-based mictures, or horse
radish; my son likes ketchup. Salad dressings work well too; I'm partial to blue
cheese, myself... I've made many different sauces for them over the years - just go
wild!

This recipe is for chicken, but any meat will work. I prefer poultry myself, but
shrimp is good, and I have used fish and steak too. I use more spices with beef,
usually harder stuff. And a spicy barbeque sauce makes for a nice complement. For
seafood and shrimp, I add a few tablespoons of Old Bay seasoning into the flour
mixture and drop the chervil and ginger. Tarter or cocktail sauce is tasty if your a
traditionalist; I like mixing up some lemon juice and no-fat sour cream.

Das könnte Ihnen auch gefallen