001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021/** 022 * 023 */ 024package org.biojava.nbio.structure.symmetry.geometry; 025 026import javax.vecmath.Matrix3d; 027import javax.vecmath.Point3d; 028import java.util.ArrayList; 029import java.util.List; 030 031 032/** 033 * @author Peter 034 * 035 */ 036public class Prism implements Polyhedron { 037 private int n = 3; 038 private double circumscribedRadius = 1.0; 039 private double height = 1.0; 040 041 public Prism(int n) { 042 this.n = n; 043 } 044 045 /** 046 * @return the height 047 */ 048 public double getHeight() { 049 return height; 050 } 051 052 /** 053 * @param height the height to set 054 */ 055 public void setHeight(double height) { 056 this.height = height; 057 } 058 059 /** 060 * Returns the radius of a circumscribed sphere, that goes 061 * through all vertices 062 * @return the cirumscribedRadius 063 */ 064 @Override 065 public double getCirumscribedRadius() { 066 return circumscribedRadius; 067 } 068 069 /** 070 * Set the radius of a circumscribed sphere, that goes 071 * through all vertices 072 * @param cirumscribedRadius the cirumscribedRadius to set 073 */ 074 public void setCirumscribedRadius(double cirumscribedRadius) { 075 this.circumscribedRadius = cirumscribedRadius; 076 } 077 /** 078 * Returns the radius of an inscribed sphere, that is tangent to each 079 * of the icosahedron's faces 080 * @return the inscribedRadius 081 */ 082 public double getInscribedRadius() { 083 double side = getSideLengthFromCircumscribedRadius(circumscribedRadius, n); 084 return getInscribedRadiusFromSideLength(side, n); 085 } 086 087 /** 088 * Sets the radius of an inscribed sphere, that is tangent to each 089 * of the icosahedron's faces 090 * @param inscribedRadius the inscribedRadius to set 091 */ 092 public void setInscribedRadius(double radius) { 093 double side = getSideLengthFromInscribedRadius(radius, n); 094 this.circumscribedRadius = getCircumscribedRadiusFromSideLength(side, n); 095 } 096 097 /** 098 * Returns the vertices of an n-fold polygon of given radius and center 099 * @return 100 */ 101 @Override 102 public Point3d[] getVertices() { 103 Point3d[] polygon = new Point3d[2*n]; 104 Matrix3d m = new Matrix3d(); 105 106 Point3d center = new Point3d(0, 0, height/2); 107 108 for (int i = 0; i < n; i++) { 109 polygon[i] = new Point3d(0, circumscribedRadius, 0); 110 m.rotZ(i*2*Math.PI/n); 111 m.transform(polygon[i]); 112 polygon[n+i] = new Point3d(polygon[i]); 113 polygon[i].sub(center); 114 polygon[n+i].add(center); 115 } 116 117 return polygon; 118 }; 119 120 @Override 121 public List<int[]> getLineLoops() { 122 List<int[]> list = new ArrayList<int[]>(); 123 int[] l1 = new int[2*n+2]; 124 for (int i = 0; i < n; i++) { 125 l1[i] = i; 126 } 127 l1[n] = 0; 128 for (int i = 0; i < n; i++) { 129 l1[n+i+1] = n+i; 130 } 131 l1[2*n+1] = l1[n+1]; 132 list.add(l1); 133 134 for (int i = 1; i < n; i++) { 135 int[] l2 = new int[2]; 136 l2[0] = i; 137 l2[1] = n+i; 138 list.add(l2); 139 } 140 return list; 141 } 142 143 /** 144 * Returns the vertices of an n-fold polygon of given radius and center 145 * @return 146 */ 147 public static Point3d[] getPolygonVertices(int n, double radius, Point3d center) { 148 Point3d[] polygon = new Point3d[n]; 149 Matrix3d m = new Matrix3d(); 150 151 for (int i = 0; i < n; i++) { 152 polygon[i] = new Point3d(0, radius, 0); 153 m.rotZ(i*2*Math.PI/n); 154 m.transform(polygon[i]); 155 polygon[i].add(center); 156 } 157 return polygon; 158 } 159 160 @Override 161 public int getViewCount() { 162 return 4; 163 } 164 165 @Override 166 public String getViewName(int index) { 167 String name; 168 switch (index) { 169 case 0: name = "Front C" + n + " axis"; 170 break; 171 case 1: name = "Side edge-centered"; 172 break; 173 case 2: name = "Side face-centered"; 174 break; 175 case 3: name = "Back C" + n + " axis"; 176 break; 177 default: throw new IllegalArgumentException("getViewMatrix: index out of range:" + index); 178 } 179 return name; 180 } 181 182 @Override 183 public Matrix3d getViewMatrix(int index) { 184 Matrix3d m = new Matrix3d(); 185 switch (index) { 186 case 0: 187 m.setIdentity(); // front 188 break; 189 case 1: 190 m.rotX(Math.PI/2); // side edge-centered 191 break; 192 case 2: 193 m.rotY(Math.PI/n); // side face-centered 194 Matrix3d m1 = new Matrix3d(); 195 m1.rotX(Math.PI/2); 196 m.mul(m1); 197 break; 198 case 3: 199 m.set(flipX()); // back 200 break; 201 default: 202 throw new IllegalArgumentException("getViewMatrix: index out of range:" + index); 203 } 204 return m; 205 } 206 207 // http://www.mathopenref.com/polygonincircle.html 208 private static double getSideLengthFromInscribedRadius(double radius, int n) { 209 if (n == 2) { 210 return radius; 211 } 212 return radius * 2 * Math.tan(Math.PI/n); 213 } 214 215 private static double getInscribedRadiusFromSideLength(double length, int n) { 216 if (n == 2) { 217 return length; 218 } 219 return length / (2 * Math.tan(Math.PI/n)); 220 } 221 222 // http://www.mathopenref.com/polygonradius.html 223 private static double getSideLengthFromCircumscribedRadius(double radius, int n) { 224 if (n == 2) { 225 return radius; 226 } 227 return radius * (2 * Math.sin(Math.PI/n)); 228 } 229 230 private static double getCircumscribedRadiusFromSideLength(double length, int n) { 231 if (n == 2) { 232 return length; 233 } 234 return length / (2 * Math.sin(Math.PI/n)); 235 } 236 237 private static Matrix3d flipX() { 238 Matrix3d rot = new Matrix3d(); 239 rot.m00 = 1; 240 rot.m11 = -1; 241 rot.m22 = -1; 242 return rot; 243 } 244 245}