// 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("
Vertexxyz"); 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("
VertexVertexchord"); 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(); } }