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