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);
}
}