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