package com.mathorama.wumpus; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; public class Dodectrahedron { private Vertex[] v; private Face[] f; private int [][] adjacentNodes; private double yAxisAngle, xAxisAngle; public static final double PI_5 = 2.0*Math.PI/5.0; public static final double PHI=1.618033988749894848204586834365638; public Dodectrahedron(){ v = new Vertex[20]; v[0]=new Vertex(1,1,1); v[1]=new Vertex(1,1,-1); v[2]=new Vertex(1,-1,1); v[3]=new Vertex(1,-1,-1); v[4]=new Vertex(-1,1,1); v[5]=new Vertex(-1,1,-1); v[6]=new Vertex(-1,-1,1); v[7]=new Vertex(-1,-1,-1); v[8]=new Vertex(0,1.0/PHI,PHI);//green v[9]=new Vertex(0,1.0/PHI,-PHI); v[10]=new Vertex(0,-1.0/PHI,PHI); v[11]=new Vertex(0,-1.0/PHI,-PHI); v[12]=new Vertex(PHI,0,1/PHI);//red v[13]=new Vertex(PHI,0,-1/PHI); v[14]=new Vertex(-PHI,0,1/PHI); v[15]=new Vertex(-PHI,0,-1/PHI); v[16]=new Vertex(1.0/PHI,PHI,0);//blu v[17]=new Vertex(1.0/PHI,-PHI,0); v[18]=new Vertex(-1.0/PHI,PHI,0); v[19]=new Vertex(-1.0/PHI,-PHI,0); f = new Face[12]; f[0] = new Face(v[18], v[16], v[1], v[9],v[5]);//ok f[1] = new Face(v[18], v[16], v[0], v[8],v[4]);//ok f[2] = new Face(v[16], v[1], v[13], v[12],v[0]); f[3] = new Face(v[1], v[9], v[11], v[3],v[13]); f[4] = new Face(v[9], v[5], v[15], v[7],v[11]); f[5] = new Face(v[5], v[18], v[4], v[14],v[15]); f[6] = new Face(v[10], v[2], v[17], v[19],v[6]); f[7] = new Face(v[10], v[2], v[12], v[0],v[8]); f[8] = new Face(v[2], v[17], v[3], v[13],v[12]); f[9] = new Face(v[17], v[19], v[7], v[11],v[3]); f[10] = new Face(v[19], v[6], v[14], v[15],v[7]); f[11] = new Face(v[6], v[10], v[8], v[4],v[14]); for (Face side:f) side.setColor(randomColor()); this.adjacentNodes = new int [20][3]; //clockwise initNode(0,8,12,16); initNode(1,16,13, 9); initNode(2,12,10, 17); initNode(3,13, 17, 11); initNode(4,18, 14, 8); initNode(5,18, 9,15); initNode(6,14,19, 10); initNode(7,15,11,19); initNode(8,4,10,0); initNode(9,5,1,11); initNode(10,8,6,2); initNode(11,3,7,9); initNode(12,0,2,13); initNode(13,1,12,3); initNode(14,4,15,6); initNode(15,5,7,14); initNode(16,0,1,18); initNode(17,3,2,19); initNode(18,16,5,4); initNode(19,7,17,6); } public void nodeTest(Graphics g, Rectangle screen, int n){ g.setColor(Color.BLACK); for(int i=0; i<3;i++) connect(g, n, adjacentNodes[n][i], screen, true); } private void initNode(int n, int v0, int v1,int v2){ adjacentNodes[n][0]=v0; adjacentNodes[n][1]=v1; adjacentNodes[n][2]=v2; } /** * from a node, facing a node get the left node * @return -1 if not possible to face from the node from that node error */ public int getLeft(int from, int facing){ int currentIndex=0; if(from==facing)// select first if same node facing=adjacentNodes[from][0]; while (currentIndex<3 && facing!=adjacentNodes[from][currentIndex]) currentIndex++; if (adjacentNodes[from][currentIndex]!=facing) return -1; int i=(currentIndex-1+3)%3; return adjacentNodes[from][i]; } /** * from a node, facing a node get the left node * @return -1 if not possible to face from the node from that node error */ public int getRight(int from, int facing){ int currentIndex=0; if(from==facing)// select first if same node facing=adjacentNodes[from][0]; while (currentIndex<3 && facing!=adjacentNodes[from][currentIndex]) currentIndex++; if (adjacentNodes[from][currentIndex]!=facing) return -1; int i=(currentIndex+1+3)%3; return adjacentNodes[from][i]; } /** * Returns the array of 5 nodes of the pentagan from a node facing a node. * @param from * @param facing * @param leftOrRight * @return null if not facing properly */ public int[] getFaceNodes(int from, int facing, String leftOrRight){ if (from==facing) return null; if (getRight(from,facing)==-1) return null; int[] p=new int[5]; p[0]=from; p[1]=facing; if (leftOrRight.equalsIgnoreCase("left")){ for (int i=2; i<5;i++) p[i]=getRight(p[i-1],p[i-2]); }else{ for (int i=2; i<5;i++) p[i]=getLeft(p[i-1],p[i-2]); } return p; } public Color randomColor(){ return new Color((int)(255*Math.random()), (int)(255*Math.random()), (int)(255*Math.random())); } public void rotateY(double yAxisDeg){ for (Vertex n:v) n.rotateAxisY(yAxisDeg); } public void rotateX( double xAxisDeg){ for (Vertex n:v) n.rotateAxisX(xAxisDeg); } public Face getFace(int i){ return f[i]; } public Face[] getFaces(){ return f; } public Vertex getVertex(int i){ return v[i]; } public double getyAxisAngle() { return yAxisAngle; } public void setyAxisAngle(double yAxisAngle) { this.yAxisAngle = yAxisAngle; } public double getxAxisAngle() { return xAxisAngle; } public void setxAxisAngle(double xAxisAngle) { this.xAxisAngle = xAxisAngle; } public void drawEdges(Graphics g, Rectangle screen, boolean ortho){ connect(g, 18, 16, screen, ortho); connect(g, 16, 1, screen, ortho); connect(g, 1, 9, screen, ortho); connect(g, 9, 5, screen, ortho); connect(g, 5, 18, screen, ortho); connect(g, 16, 0, screen, ortho); connect(g, 0, 8, screen, ortho); connect(g, 8, 4, screen, ortho); connect(g, 4, 18, screen, ortho); connect(g, 0, 12, screen, ortho); connect(g, 12, 13, screen, ortho); connect(g, 13, 1, screen, ortho); connect(g, 13, 3, screen, ortho); connect(g, 3, 11, screen, ortho); connect(g, 11, 9, screen, ortho); connect(g, 11, 7, screen, ortho); connect(g, 7, 15, screen, ortho); connect(g, 15, 5, screen, ortho); connect(g, 15, 14, screen, ortho); connect(g, 14, 4, screen, ortho); connect(g, 10, 8, screen, ortho); connect(g, 2, 12, screen, ortho); connect(g, 17, 3, screen, ortho); connect(g, 19, 7, screen, ortho); connect(g, 6, 14, screen, ortho); connect(g, 10, 2, screen, ortho); connect(g, 2, 17, screen, ortho); connect(g, 17, 19, screen, ortho); connect(g, 19, 6, screen, ortho); connect(g, 6, 10, screen, ortho); } public void drawCenter2Vertex(Graphics g, Rectangle area, int i,boolean ortho, double offset){ Vertex o=new Vertex(0,0,0); Point p1,p2; if(ortho){ p1=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } g.drawLine(p1.x, p1.y, p2.x, p2.y); } public void point2Vertex(Graphics g, Rectangle area, int from, int to, boolean ortho, double offset){ Vertex o=Vertex.spike(getVertex(from), .25); Point p1,p2, p3; if(ortho){ p1=Vertex.midpoint(getVertex(from), getVertex(to)).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(from).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p3=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=Vertex.midpoint(getVertex(from), getVertex(to)).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(from).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p3=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } Polygon flag = new Polygon(); flag.addPoint(p1.x, p1.y); flag.addPoint(p2.x, p2.y); flag.addPoint(p3.x, p3.y); g.fillPolygon(flag); } /** * * @param g * @param area * @param i the node * @param percent how long the spike * @param ortho whether or not ortho or perspectve projectoin * @param offset rotation offset for stereo use */ public void spikeVertex(Graphics g, Rectangle area, int i, double percent, boolean ortho, double offset){ Vertex o=Vertex.spike(getVertex(i), percent); Point p1,p2; if(ortho){ p1=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } g.drawLine(p1.x, p1.y, p2.x, p2.y); } public void connect(Graphics g,int i, int j, Rectangle screen, boolean ortho, double offset){ Point p1,p2; if (ortho){ p1=getVertex(i).orthoXY(screen, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(j).orthoXY(screen, getyAxisAngle()+offset, getxAxisAngle()); }else { p1=getVertex(i).screenXY(screen, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(j).screenXY(screen, getyAxisAngle()+offset, getxAxisAngle()); } g.drawLine(p1.x, p1.y, p2.x, p2.y ); } public void connect(Graphics g, int i, int j, Rectangle screen, boolean ortho){ connect(g,i,j,screen,ortho,0); } public void drawDot(Graphics g, Rectangle area, int i, double percent, boolean ortho, double offset){ Vertex o=Vertex.spike(getVertex(i), percent); Point p1,p2; if(ortho){ p1=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } int size=(int)Math.round(Math.sqrt(Math.pow(p1.x-p2.x,2)+Math.pow(p1.y-p2.y,2))); size=Math.max(5, size); g.fillOval(p1.x-size, p1.y-size, 2*size, 2*size); } }