import java.applet.Applet; import java.awt.event.*; import java.awt.*; import java.awt.geom.*; public class ListenTriangle { Complex[] z=new Complex[3]; int history; /** Construct a ListenTriangle where all the vertices are the origin */ public ListenTriangle() { z[0]=new Complex(); z[1]=new Complex(); z[2]=new Complex(); } /** Construct a ListenTriangle initializing all the vertices. *

* You can initialize a triangle like this:
     * ListenTriangle=new ListenTriangle(new Complex(0,0), 
     *                                   new Complex(1,0),
     *                                   new Complex(0,1));
*/ public ListenTriangle(Complex a, Complex b, Complex c) { z[0]=a; z[1]=b; z[2]=c; } /** Copy Constructor. *

* Note: The correct way to make a copy of a ListenTriangle is
     * A=new ListenTriangle(B); 
     * 

* The point is that if you were to use
     * A=B; 
     * 

* then you get two triangles which share data. That is, a change * to A results in a change to B as well. **/ public ListenTriangle(ListenTriangle T) { z[0]=T.z[0]; z[1]=T.z[1]; z[2]=T.z[2]; } /**tells if a point is in the triangle*/ public int inside(Point p) { int i,j,k,G1,G2; double x0,x1,x2,y0,y1,y2; double test; G1=0; G2=0; for(i=0;i<=2;++i) { x0=p.x; y0=p.y; j=i; k=i+1; if(j>=3) j=j-3; if(k>=3) k=k-3; x1=z[i].x; y1=z[j].y; x2=z[k].x; y2=z[k].y; test=x0*y1+x1*y2+x2*y0-y0*x1-y1*x2-y2*x0; if(test>0) G2=1; if(test<=0) G2=-1; if((G1!=0)&&(G1!=G2)) return(0); G1=G2; } return(1); } /**initializes a triangle using McBilliards coordinates*/ public static ListenTriangle init(Complex z) { ListenTriangle T=new ListenTriangle(); double x=0; double y=0; x=Math.PI*z.x/2.0; y=Math.PI*z.y/2.0; double xx=(Math.tan(x)*Math.tan(y))/(Math.tan(x)+Math.tan(y)); double yy= (Math.tan(y))/(Math.tan(x)+Math.tan(y)); T.z[0]=new Complex(0.0,0.0); T.z[1]=new Complex(0.0,1.0); T.z[2]=new Complex(xx,yy); T.history=0; return(T); } /**reflects in the jth edge for j=0,1,2*/ public ListenTriangle reflect(int j) { Complex w[]=new Complex[20]; ListenTriangle S=new ListenTriangle(); for(int i=1;i<=10;++i) w[i]=new Complex(); int a1,a2,a3; a1=(j+0)%3; a2=(j+1)%3; a3=(j+2)%3; w[1]=new Complex(z[a1].x,z[a1].y); w[2]=new Complex(z[a2].x,z[a2].y); w[3]=new Complex(z[a3].x,z[a3].y); w[4]=w[1].minus(w[1],w[2]); w[5]=w[1].conjugate(w[4]); w[6]=w[1].minus(w[3],w[2]); w[7]=w[1].conjugate(w[6]); w[8]=w[1].divide(w[6],w[7]); w[9]=w[1].times(w[5],w[8]); w[10]=w[1].plus(w[9],w[2]); S.z[a2].x=z[a2].x; S.z[a2].y=z[a2].y; S.z[a3].x=z[a3].x; S.z[a3].y=z[a3].y; S.z[a1].x=w[10].x; S.z[a1].y=w[10].y; S.history=j+1; return(S); } /**scales by r and translates by w*/ public ListenTriangle scale(Complex w,double r) { ListenTriangle T=new ListenTriangle(); T.history=this.history; for(int i=0;i<=2;++i) { T.z[i].x=r*z[i].x+w.x; T.z[i].y=r*z[i].y+w.y; } return(T); } /**complex multiplies by z*/ public ListenTriangle rotate(Complex w) { ListenTriangle T=new ListenTriangle(); T.history=this.history; for(int i=0;i<=2;++i) { T.z[i]=w.times(w,z[i]); } return(T); } /**draws the triangle */ public void render(Graphics g,Color C1,Color C2) { Polygon P=new Polygon(); int X1[]={(int)(z[0].x),(int)(z[1].x),(int)(z[2].x)}; int Y1[]={(int)(z[0].y),(int)(z[1].y),(int)(z[2].y)}; P.xpoints=X1; P.ypoints=Y1; P.npoints=3; g.setColor(C1); g.fillPolygon(P); g.setColor(C2); g.drawPolygon(P); } /**draws the triangle */ public void renderSmooth(Graphics2D g,Color C1,Color C2) { Polygon P=new Polygon(); float X[]={(float)(z[0].x),(float)(z[1].x),(float)(z[2].x)}; float Y[]={(float)(z[0].y),(float)(z[1].y),(float)(z[2].y)}; GeneralPath path=new GeneralPath(); path.moveTo(X[0],Y[0]); for(int i=1;i<3;++i) path.lineTo(X[i],Y[i]); path.closePath(); g.setColor(C1); g.fill(path); g.setColor(C2); g.draw(path); } /**draws the selected edge */ public void edgeRender(Graphics g,int k,Color C1) { Polygon P=new Polygon(); int X1[]={(int)(z[0].x),(int)(z[1].x),(int)(z[2].x)}; int Y1[]={(int)(z[0].y),(int)(z[1].y),(int)(z[2].y)}; g.setColor(C1); if(k==1) g.drawLine(X1[2],Y1[2],X1[0],Y1[0]); if(k==2) g.drawLine(X1[0],Y1[0],X1[1],Y1[1]); if(k==0) g.drawLine(X1[1],Y1[1],X1[2],Y1[2]); } /**draws the selected edge */ public void edgeRenderSmooth(Graphics2D g,int k,Color C1) { Polygon P=new Polygon(); float X[]={(float)(z[0].x),(float)(z[1].x),(float)(z[2].x)}; float Y[]={(float)(z[0].y),(float)(z[1].y),(float)(z[2].y)}; GeneralPath path=new GeneralPath(); int a1=(k+1)%3; int a2=(k+2)%3; path.moveTo(X[a1],Y[a1]); path.lineTo(X[a2],Y[a2]); g.setColor(C1); g.draw(path); } /** Returns a GeneralPath that travels around the triangle. * This is useful for drawing with a Graphics2D object, or modifying * by an AffineTransform. * @see java.awt.geom.AffineTransform * @see java.awt.Graphics2D */ public GeneralPath getPath() { GeneralPath p=new GeneralPath(); p.moveTo((float)z[0].x, (float)z[0].y); p.lineTo((float)z[1].x, (float)z[2].y); p.lineTo((float)z[1].x, (float)z[2].y); p.closePath(); return p; } /** Returns a Line2D.Double representing the edge i * which is opposite vertex i (i=0,1,2). * This is useful for drawing with a Graphics2D object, or modifying * by an AffineTransform. * @see java.awt.geom.AffineTransform * @see java.awt.Graphics2D */ public Line2D.Double getEdge(int i) { return new Line2D.Double(z[(i+1)%3].x,z[(i+1)%3].y, z[(i+2)%3].x,z[(i+2)%3].y); } }