// 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("
Circumscribed Spherical Projection
");
System.out.println
("");
System.out.println("Vertex | x | y | 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
(""+label+" | "+Rounding.toString(cPoint.x,5)+" | "+
Rounding.toString(cPoint.y,5)+" | "+Rounding.toString(cPoint.z,5));
}
System.out.println(" | |
");
}
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("Chord Lengths
");
System.out.println
("");
System.out.println("Vertex | Vertex | 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
(""+label+" | "+belowLeftLabel+" | "+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowLeftLabel)),5));
belowRightLabel = getBelowRightLabel(j,i-j);
if (belowRightLabel != null)
System.out.println
(" | "+label+" | "+belowRightLabel+" | "+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(belowRightLabel)),5));
rightLabel = getRightLabel(j,i-j);
if (rightLabel != null)
System.out.println
(" | "+label+" | "+rightLabel+" | "+
Rounding.toString
(cPoint.distanceTo((CPoint)cPoints.get(rightLabel)),5));
}
System.out.println(" | |
");
}
public static void main (String[] arguments)
{
int n = Integer.valueOf(arguments[0]).intValue();
double s = Double.valueOf(arguments[1]).doubleValue();
System.out.println
("Calculations for a "+n+"-frequency Icosahedral Geodesic Patch");
Icos icos = new Icos(n,s);
icos.mesh();
icos.project();
icos.chords();
}
}