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 */ 021package org.biojava.nbio.structure.symmetry.geometry; 022 023import javax.vecmath.Matrix3d; 024import javax.vecmath.Point3d; 025import java.util.Arrays; 026import java.util.List; 027 028 029public class Octahedron implements Polyhedron { 030 private static double TETRAHEDRAL_ANGLE = Math.acos(-1.0/3.0); 031 private static int[] lineLoop1 = {2,4,3,5,2,1,3,0,5,1,4,0,2}; 032 private double cirumscribedRadius = 1.0; 033 034 /** 035 * Returns the radius of a circumscribed sphere, that goes 036 * through all vertices 037 * @return the cirumscribedRadius 038 */ 039 @Override 040 public double getCirumscribedRadius() { 041 return cirumscribedRadius; 042 } 043 044 /** 045 * Set the radius of a circumscribed sphere, that goes 046 * through all vertices 047 * @param cirumscribedRadius the cirumscribedRadius to set 048 */ 049 public void setCirumscribedRadius(double cirumscribedRadius) { 050 this.cirumscribedRadius = cirumscribedRadius; 051 } 052 /** 053 * Returns the radius of an inscribed sphere, that is tangent to each 054 * of the octahedron's faces 055 * @return the inscribedRadius 056 */ 057 public double getInscribedRadius() { 058 double side = getSideLengthFromCircumscribedRadius(cirumscribedRadius); 059 return getInscribedRadiusFromSideLength(side); 060 } 061 062 /** 063 * Sets the radius of an inscribed sphere, that is tangent to each 064 * of the octahedron's faces 065 * @param inscribedRadius the inscribedRadius to set 066 */ 067 public void setInscribedRadius(double radius) { 068 double side = getSideLengthFromInscribedRadius(radius); 069 this.cirumscribedRadius = getCircumscribedRadiusFromSideLength(side); 070 } 071 072 /** 073 * Returns the radius of a sphere, that is tangent to each 074 * of the octahedron's edges 075 * 076 * @return the midRadius 077 */ 078 public double getMidRadius() { 079 double side = getSideLengthFromCircumscribedRadius(cirumscribedRadius); 080 return getMiddleRadiusFromSideLength(side); 081 } 082 083 /** 084 * Sets the radius of radius of a sphere, that is tangent to each 085 * of the octahedron's edges 086 * @param midRadius the midRadius to set 087 */ 088 public void setMidRadius(double radius) { 089 double side = getSideLengthFromMiddleRadius(radius); 090 this.cirumscribedRadius = getCircumscribedRadiusFromSideLength(side); 091 } 092 093 /** 094 * Returns the vertices of an n-fold polygon of given radius and center 095 * @param n 096 * @param radius 097 * @param center 098 * @return 099 */ 100 @Override 101 public Point3d[] getVertices() { 102 Point3d[] octahedron = new Point3d[6]; 103 octahedron[0] = new Point3d(-cirumscribedRadius, 0, 0); 104 octahedron[1] = new Point3d( cirumscribedRadius, 0, 0); 105 octahedron[2] = new Point3d(0, -cirumscribedRadius, 0); 106 octahedron[3] = new Point3d(0, cirumscribedRadius, 0); 107 octahedron[4] = new Point3d(0, 0, -cirumscribedRadius); 108 octahedron[5] = new Point3d(0, 0, cirumscribedRadius); 109 110 return octahedron; 111 }; 112 113 @Override 114 public List<int[]> getLineLoops() { 115 return Arrays.asList(lineLoop1); 116 } 117 118 public Point3d getC4Axis(double scale) { 119 return new Point3d(0, 0, cirumscribedRadius*scale); 120 } 121 public Point3d getC3Axis(double scale) { 122 double s = 1/Math.sqrt(1 + Math.sqrt(2)); 123 return new Point3d(cirumscribedRadius*scale*s, cirumscribedRadius*scale*s, cirumscribedRadius*scale*s); 124 } 125 public Point3d getC2Axis(double scale) { 126 double s = 1/Math.sqrt(2); 127 return new Point3d(cirumscribedRadius*scale*s, cirumscribedRadius*scale*s, 0); 128 } 129 130 @Override 131 public int getViewCount() { 132 return 3; 133 } 134 135 @Override 136 public String getViewName(int index) { 137 String name; 138 switch (index) { 139 case 0: name = "4-fold axis vertex-centered"; 140 break; 141 case 1: name = "3-fold axis face-centered"; 142 break; 143 case 2: name = "2-fold axis edge-centered"; 144 break; 145 default: throw new IllegalArgumentException("getViewMatrix: index out of range:" + index); 146 } 147 return name; 148 } 149 150 @Override 151 public Matrix3d getViewMatrix(int index) { 152 Matrix3d m = new Matrix3d(); 153 switch (index) { 154 case 0: 155 m.setIdentity(); // C4 vertex-centered 156 break; 157 case 1: 158 m.rotX(-0.5 * TETRAHEDRAL_ANGLE); // C3 face-centered 2.0*Math.PI/3 159 Matrix3d m1 = new Matrix3d(); 160 m1.rotZ(Math.PI/4); 161 m.mul(m1); 162 break; 163 case 2: 164 m.rotY(Math.PI/4); // side face-centered 165 break; 166 default: 167 throw new IllegalArgumentException("getViewMatrix: index out of range:" + index); 168 } 169 return m; 170 } 171 172 private static double getSideLengthFromInscribedRadius(double radius) { 173 return radius * 6 / Math.sqrt(6); 174 } 175 176 private static double getInscribedRadiusFromSideLength(double sideLength) { 177 return sideLength / 6 * Math.sqrt(6); 178 } 179 180 private static double getSideLengthFromMiddleRadius(double radius) { 181 return radius * 2; 182 } 183 184 private static double getMiddleRadiusFromSideLength(double sideLength) { 185 return sideLength / 2; 186 } 187 188 private static double getSideLengthFromCircumscribedRadius(double radius) { 189 return radius * 2 / Math.sqrt(2); 190 } 191 192 private static double getCircumscribedRadiusFromSideLength(double sideLength) { 193 return sideLength / 2 * Math.sqrt(2); 194 } 195}