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 radius 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 radius 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 * @return 096 */ 097 @Override 098 public Point3d[] getVertices() { 099 Point3d[] octahedron = new Point3d[6]; 100 octahedron[0] = new Point3d(-cirumscribedRadius, 0, 0); 101 octahedron[1] = new Point3d( cirumscribedRadius, 0, 0); 102 octahedron[2] = new Point3d(0, -cirumscribedRadius, 0); 103 octahedron[3] = new Point3d(0, cirumscribedRadius, 0); 104 octahedron[4] = new Point3d(0, 0, -cirumscribedRadius); 105 octahedron[5] = new Point3d(0, 0, cirumscribedRadius); 106 107 return octahedron; 108 }; 109 110 @Override 111 public List<int[]> getLineLoops() { 112 return Arrays.asList(lineLoop1); 113 } 114 115 public Point3d getC4Axis(double scale) { 116 return new Point3d(0, 0, cirumscribedRadius*scale); 117 } 118 public Point3d getC3Axis(double scale) { 119 double s = 1/Math.sqrt(1 + Math.sqrt(2)); 120 return new Point3d(cirumscribedRadius*scale*s, cirumscribedRadius*scale*s, cirumscribedRadius*scale*s); 121 } 122 public Point3d getC2Axis(double scale) { 123 double s = 1/Math.sqrt(2); 124 return new Point3d(cirumscribedRadius*scale*s, cirumscribedRadius*scale*s, 0); 125 } 126 127 @Override 128 public int getViewCount() { 129 return 3; 130 } 131 132 @Override 133 public String getViewName(int index) { 134 String name; 135 switch (index) { 136 case 0: name = "4-fold axis vertex-centered"; 137 break; 138 case 1: name = "3-fold axis face-centered"; 139 break; 140 case 2: name = "2-fold axis edge-centered"; 141 break; 142 default: throw new IllegalArgumentException("getViewMatrix: index out of range:" + index); 143 } 144 return name; 145 } 146 147 @Override 148 public Matrix3d getViewMatrix(int index) { 149 Matrix3d m = new Matrix3d(); 150 switch (index) { 151 case 0: 152 m.setIdentity(); // C4 vertex-centered 153 break; 154 case 1: 155 m.rotX(-0.5 * TETRAHEDRAL_ANGLE); // C3 face-centered 2.0*Math.PI/3 156 Matrix3d m1 = new Matrix3d(); 157 m1.rotZ(Math.PI/4); 158 m.mul(m1); 159 break; 160 case 2: 161 m.rotY(Math.PI/4); // side face-centered 162 break; 163 default: 164 throw new IllegalArgumentException("getViewMatrix: index out of range:" + index); 165 } 166 return m; 167 } 168 169 private static double getSideLengthFromInscribedRadius(double radius) { 170 return radius * 6 / Math.sqrt(6); 171 } 172 173 private static double getInscribedRadiusFromSideLength(double sideLength) { 174 return sideLength / 6 * Math.sqrt(6); 175 } 176 177 private static double getSideLengthFromMiddleRadius(double radius) { 178 return radius * 2; 179 } 180 181 private static double getMiddleRadiusFromSideLength(double sideLength) { 182 return sideLength / 2; 183 } 184 185 private static double getSideLengthFromCircumscribedRadius(double radius) { 186 return radius * 2 / Math.sqrt(2); 187 } 188 189 private static double getCircumscribedRadiusFromSideLength(double sideLength) { 190 return sideLength / 2 * Math.sqrt(2); 191 } 192}