import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class test1 extends Applet { DisplayCanvas C; GroupSelector G; public void init() { C=new DisplayCanvas(); G=new GroupSelector(C); C=C.add(G); C.setSize(300,552); C.setBackground(Color.black); add(G); add(C); setBackground(Color.black); } public void paint(Graphics g) { } } class DBCanvas extends Canvas { public void update(Graphics g) { Graphics g2; Image offscreen = null; offscreen = createImage(getSize().width, getSize().height); g2 = offscreen.getGraphics(); paint(g2); g.drawImage(offscreen, 0, 0, this); g2.dispose(); offscreen.flush(); } } class DisplayCanvas extends DBCanvas implements MouseListener,MouseMotionListener { GroupSelector X; int init; String[] St=new String[200]; int pos; ListenSquare scroll; int SCROLL; DisplayCanvas() { init=0; for(int i=1;i<=199;++i) St[i]=""; pos=0; addMouseListener(this); addMouseMotionListener(this); scroll=new ListenSquare(281,120,19,20); SCROLL=0; St[0]="(drag the blue square to scroll the text.)"; St[1]="This applet lets you investigate the complex"; St[2]="hyperbolic reflection triangle groups."; St[3]="Such a group is specified by choosing"; St[4]="a triple points p1,p2,p3 in CH^2."; St[5]="Here CH^2 is the unit ball in C^2,"; St[6]="Equipped with a certain Riemannian"; St[7]="metric which is invariant under the group"; St[8]="of complex projective automorphisms."; St[10]="Once these points are chosen, there"; St[11]="are 3 complex lines C1,C2,C3 such that"; St[12]="C1 contains p2,p3;"; St[13]="C2 contains p3,p1;"; St[14]="C3 contains p1,p2;"; St[15]="The type of the triangle group is (a1,a2,a3),"; St[16]="Where the angle between C1 and C2 is Pi/a3"; St[17]="Where the angle between C2 and C3 is Pi/a1"; St[18]="Where the angle between C3 and C1 is Pi/a2"; St[19]="The case of interest is when a1,a2,a3"; St[20]="are all integers and (1/a1)+(1/a2)+(1/a3)<1"; St[22]="Using the red,green,blue buttons at the"; St[23]="bottom of the applet you can select a1,a2,a3"; St[24]="subject to the constraints that 2=130)&&(SCROLL==1)) { pos=4*(p.y-130); scroll.y=p.y-10; repaint(); } } void doubleRender(double d,Graphics g,int x,int y) { g.setColor(Color.white); if(d>1000000000) g.drawString(">1000000000",x,y); if((d>=0)&&(d<=1000000000)) { Integer I=new Integer(0); int big=(int)(d); g.drawString(I.toString(big),x+10,y); double rem=d-big; int small=(int)(rem*100000); g.fillOval(x+135,y,2,2); g.drawOval(x+135,y,2,2); g.drawString(I.toString(small),x+140,y); } if(d<0) { Integer I=new Integer(0); int big=(int)(-d+.000001); g.drawString("-",x,y); g.drawString(I.toString(big),x+10,y); } } double evaluate(int i) { double ev=X.G.evaluate(X.W[i].W); return(ev); } } class Complex { double x,y; Complex() { this.x=0.0; this.y=0.0; } Complex(double x,double y) { this.x=x; this.y=y; } Complex random() { Complex z=new Complex(); z.x=2.0*Math.random()-1.0; z.y=2.0*Math.random()-1.0; return(z); } Complex randomUnit() { Complex z=new Complex(); z=z.random(); z=z.unit(z); return(z); } double norm(Complex z) { double d; d=z.x*z.x+z.y*z.y; d=Math.sqrt(d); return(d); } Complex unit(Complex z) { Complex w=new Complex(); double d; d=z.norm(z); w.x=z.x/d; w.y=z.y/d; return(w); } Complex plus(Complex z1,Complex z2) { Complex w= new Complex(); w.x=z1.x+z2.x; w.y=z1.y+z2.y; return(w); } Complex minus(Complex z1,Complex z2) { Complex w= new Complex(); w.x=z1.x-z2.x; w.y=z1.y-z2.y; return(w); } Complex times(Complex z1,Complex z2) { Complex w= new Complex(); w.x=z1.x*z2.x-z1.y*z2.y; w.y=z1.x*z2.y+z1.y*z2.x; return(w); } Complex inverse(Complex z) { Complex w=new Complex(); double d; d=z.x*z.x+z.y*z.y; w.x=z.x/d; w.y=-z.y/d; return(w); } Complex divide(Complex z1,Complex z2) { Complex w= new Complex(); w=w.times(z1,w.inverse(z2)); return(w); } Complex conjugate(Complex z) { Complex w=new Complex(); w.x=x; w.y=-y; return(w); } double disc(Complex z) { double d1,d2,d3,d4,d5; d1=norm(z);d3=d1*d1; d1=d1*d1*d1*d1; Complex zzz=z.times(z.times(z,z),z); d2=zzz.x; d3=d1-8.0*d2+18.0*d3-27.0; return(d3); } void print() { System.out.println(x+" "+y+" I"); } } class Vector { Complex x,y,z; Vector() { this.x=new Complex(); this.y=new Complex(); this.z=new Complex(); } Vector(Complex x,Complex y,Complex z) { this.x=x; this.y=y; this.z=z; } Vector plus(Vector v1,Vector v2) { Vector w=new Vector(); w.x=w.x.plus(v1.x,v2.x); w.y=w.y.plus(v1.y,v2.y); w.z=w.z.plus(v1.z,v2.z); return(w); } Vector minus(Vector v1,Vector v2) { Vector w=new Vector(); w.x=w.x.minus(v1.x,v2.x); w.y=w.y.minus(v1.y,v2.y); w.z=w.z.minus(v1.z,v2.z); return(w); } Complex dot21(Vector v,Vector w) { Complex z[]=new Complex[5]; for(int i=1;i<=4;++i) z[i]=new Complex(); z[1]=z[1].times(v.x,w.x.conjugate(w.x)); z[2]=z[2].times(v.y,w.y.conjugate(w.y)); z[3]=z[3].times(v.z,w.z.conjugate(w.z)); z[4]=z[4].minus(z[4].plus(z[1],z[2]),z[3]); return(z[4]); } Complex dot30(Vector v,Vector w) { Complex z[]=new Complex[5]; for(int i=1;i<=4;++i) z[i]=new Complex(); z[1]=z[1].times(v.x,w.x.conjugate(w.x)); z[2]=z[2].times(v.y,w.y.conjugate(w.y)); z[3]=z[3].times(v.z,w.z.conjugate(w.z)); z[4]=z[4].plus(z[4].plus(z[1],z[2]),z[3]); return(z[4]); } Complex dot30real(Vector v,Vector w) { Complex z[]=new Complex[5]; for(int i=1;i<=4;++i) z[i]=new Complex(); z[1]=z[1].times(v.x,w.x); z[2]=z[2].times(v.y,w.y); z[3]=z[3].times(v.z,w.z); z[4]=z[4].plus(z[4].plus(z[1],z[2]),z[3]); return(z[4]); } Vector random() { Vector v=new Vector(); v.x=v.x.random(); v.y=v.y.random(); v.z=v.z.random(); return(v); } double norm21(Vector v) { Complex z=new Complex(); z=v.dot21(v,v); return(z.x); } double norm30() { Complex z=new Complex(); z=this.dot30(this,this); return(z.x); } double dist21(Vector v,Vector w) { Complex z[]=new Complex[6]; for(int i=1;i<=5;++i) z[i]=new Complex(); z[1]=v.dot21(v,w); z[2]=v.dot21(w,v); z[3]=v.dot21(v,v); z[4]=v.dot21(w,w); z[5]=z[1].divide(z[1].times(z[1],z[2]),z[3].times(z[3],z[4])); return(z[5].x); } Vector scale(Complex z,Vector v) { Vector w=new Vector(); w.x=z.times(z,v.x); w.y=z.times(z,v.y); w.z=z.times(z,v.z); return(w); } Vector box(Vector v,Vector w) { Vector x=new Vector(); Complex z1=new Complex(); Complex z2=new Complex(); Complex z3=new Complex(); z1=z1.minus(z1.times(v.z,w.y),z1.times(v.y,w.z)); z2=z1.minus(z1.times(v.x,w.z),z1.times(v.z,w.x)); z3=z1.minus(z1.times(v.x,w.y),z1.times(v.y,w.x)); x.x=z1.conjugate(z1); x.y=z2.conjugate(z2); x.z=z3.conjugate(z3); return(x); } Vector reflect(Vector w) { Vector v1=new Vector(); Vector v2=new Vector(); Complex z1=new Complex(); Complex z2=new Complex(); Complex z3=new Complex(); Vector v3=this; z1=v3.dot21(w,v3); z2=v3.dot21(v3,v3); z3=z1.divide(z1,z2); z3.x=2.0*z3.x; z3.y=2.0*z3.y; v1=v1.scale(z3,v3); v2=v2.minus(v1,w); return(v2); } Vector e1() { Vector v=new Vector(); v.x.x=1.0;v.x.y=0.0; v.y.x=0.0;v.y.y=0.0; v.z.x=0.0;v.z.y=0.0; return(v); } Vector e2() { Vector v=new Vector(); v.x.x=0.0;v.x.y=0.0; v.y.x=1.0;v.y.y=0.0; v.z.x=0.0;v.z.y=0.0; return(v); } Vector e3() { Vector v=new Vector(); v.x.x=0.0;v.x.y=0.0; v.y.x=0.0;v.y.y=0.0; v.z.x=1.0;v.z.y=0.0; return(v); } void print() { System.out.println(x.x+"+"+x.y+" I "+y.x+"+"+y.y+" I "+z.x+"+"+z.y+" I"); } void realPrint() { System.out.println(x.x+" "+y.x+" "+z.x); } } class Matrix { Vector x,y,z; Matrix() { this.x=new Vector(); this.y=new Vector(); this.z=new Vector(); } Matrix(Vector x,Vector y,Vector z) { this.x=x; this.y=y; this.z=z; } Matrix identity() { Matrix m=new Matrix(); m.x=m.x.e1(); m.y=m.y.e2(); m.z=m.z.e3(); return(m); } Matrix transpose(Matrix m) { Matrix w=new Matrix(); w.x.x=m.x.x; w.x.y=m.y.x; w.x.z=m.z.x; w.y.x=m.x.y; w.y.y=m.y.y; w.y.z=m.z.y; w.z.x=m.x.z; w.z.y=m.y.z; w.z.z=m.z.z; return(w); } Matrix times(Matrix m1,Matrix m2) { Matrix w=new Matrix(); Vector v=new Vector(); Matrix mm2=m2.transpose(m2); w.x.x=v.dot30real(m1.x,mm2.x); w.x.y=v.dot30real(m1.x,mm2.y); w.x.z=v.dot30real(m1.x,mm2.z); w.y.x=v.dot30real(m1.y,mm2.x); w.y.y=v.dot30real(m1.y,mm2.y); w.y.z=v.dot30real(m1.y,mm2.z); w.z.x=v.dot30real(m1.z,mm2.x); w.z.y=v.dot30real(m1.z,mm2.y); w.z.z=v.dot30real(m1.z,mm2.z); return(w); } Matrix reflect(Vector v) { Matrix m=new Matrix(); m.x=v.reflect(v.e1()); m.y=v.reflect(v.e2()); m.z=v.reflect(v.e3()); m=m.transpose(m); return(m); } Complex trace() { Complex z=new Complex(); Matrix m=this; z=z.plus(m.x.x,z.plus(m.y.y,m.z.z)); return(z); } double disc() { double d; Complex z=this.trace(); d=z.disc(z); return(d); } void print() { Matrix m=this; m.x.print(); m.y.print(); m.z.print(); } } class TriangleGroup { Matrix I1,I2,I3; Triangle T; TriangleGroup() { I1=new Matrix(); I2=new Matrix(); I3=new Matrix(); } TriangleGroup(Matrix I1,Matrix I2,Matrix I3) { this.I1=I1; this.I2=I2; this.I3=I3; } TriangleGroup(Triangle T) { this.T=T; double a=T.a; Complex b=T.b; double x=T.x; Vector v1=new Vector(); Vector v2=new Vector(); Vector v3=new Vector(); v1.z.x=1.0; v2.x.x=a; v2.z.x=1.0; v3.x.x=b.x*Math.cos(Math.PI/x); v3.x.y=b.y*Math.cos(Math.PI/x); v3.y.x=b.x*Math.sin(Math.PI/x); v3.y.y=b.y*Math.sin(Math.PI/x); v3.z.x=1.0; Vector c1=v1.box(v2,v3); Vector c2=v2.box(v3,v1); Vector c3=v3.box(v1,v2); Matrix i1=new Matrix(); Matrix i2=new Matrix(); Matrix i3=new Matrix(); i1=i1.reflect(c1); i2=i2.reflect(c2); i3=i3.reflect(c3); I1=i1; I2=i2; I3=i3; } Vector angle(Vector v1,Vector v2,Vector v3) { Vector c1=v1.box(v2,v3); Vector c2=v2.box(v3,v1); Vector c3=v3.box(v1,v2); double d1=c1.dist21(c2,c3); double d2=c1.dist21(c3,c1); double d3=c1.dist21(c1,c2); Vector w=new Vector(); w.x.x=Math.sqrt(d1); w.y.x=Math.sqrt(d2); w.z.x=Math.sqrt(d3); return(w); } double evaluate(Word w) { Matrix M=new Matrix(); M=M.identity(); for(int i=1;i<=w.l;++i) { if(w.n[i]==1) M=M.times(M,I1); if(w.n[i]==2) M=M.times(M,I2); if(w.n[i]==3) M=M.times(M,I3); } double d=M.disc(); return(d); } int hypTest() { Word[] w= new Word[4]; for(int i=0;i<=3;++i) { w[i]=new Word(); } w[0].l=3; w[0].n[1]=1; w[0].n[2]=2; w[0].n[3]=3; w[1].l=4; w[1].n[1]=1; w[1].n[2]=2; w[1].n[3]=1; w[1].n[4]=3; w[2].l=4; w[2].n[1]=2; w[2].n[2]=1; w[2].n[3]=2; w[2].n[4]=3; w[3].l=4; w[3].n[1]=3; w[3].n[2]=2; w[3].n[3]=3; w[3].n[4]=1; int test=0; for(int i=0;i<=3;++i) { if(evaluate(w[i])<0.0) test=1; } return(test); } } class Triangle { double x,a; double memory; Complex b; double d; double PARABOLIC; int a1,a2,a3; Triangle () { this.x=0.0; this.a=1.0; this.d=0.0; this.b=new Complex(); this.memory=memory; a1=1; a2=1; a3=1; } Triangle (int aa,int bb,int cc) { double C=0.0; double B=0.0; double aaa=Math.PI/aa; double bbb=Math.PI/bb; double ccc=Math.PI/cc; B=(Math.cos(ccc)*Math.cos(aaa) + Math.cos(bbb)); B=B/(Math.sin(ccc)*Math.sin(aaa)); C=(Math.cos(aaa)*Math.cos(bbb) + Math.cos(ccc)); C=C/(Math.sin(aaa)*Math.sin(bbb)); B=Math.sqrt(1-1/(B*B)); C=Math.sqrt(1-1/(C*C)); this.x=aa; this.a=B; b=new Complex(); this.b.x=C; this.b.y=0; memory=B; this.d=(1.0-this.b.x)/4.0; a1=aa; a2=bb; a3=cc; PARABOLIC=parabolicParameter(); } Vector angle() { TriangleGroup G=new TriangleGroup(); Vector v1=new Vector(); Vector v2=new Vector(); Vector v3=new Vector(); v1.z.x=1.0; v2.x.x=a; v2.z.x=1.0; v3.x.x=b.x*Math.cos(Math.PI/x); v3.x.y=b.y*Math.cos(Math.PI/x); v3.y.x=b.x*Math.sin(Math.PI/x); v3.y.y=b.y*Math.sin(Math.PI/x); v3.z.x=1.0; return(G.angle(v1,v2,v3)); } Vector angle2() { Vector v=this.angle(); v.x.x=Math.PI/Math.acos(v.x.x); v.y.x=Math.PI/Math.acos(v.y.x); v.z.x=Math.PI/Math.acos(v.z.x); return(v); } int match() { Vector V=angle2(); Vector W=new Vector(); W.x.x=a1; W.y.x=a2; W.z.x=a3; Vector X=W.minus(W,V); int test=1; double d=X.norm30(); if(d<.000000001) test=0; return(test); } double lowerLimit() { double b1,b2,b3; b1=a; b2=Math.cos(Math.PI/a1); b3=Math.sin(Math.PI/a1)*Math.cos(Math.PI/a2)/Math.sin(Math.PI/a2); b3=b3*Math.sqrt(1.0-a*a); return((b2+b3)/b1); } double upperLimit() { double b1,b2,b3; b1=a; b2=Math.cos(Math.PI/a1); b3=Math.sin(Math.PI/a1)*Math.cos(Math.PI/a2)/Math.sin(Math.PI/a2); b3=b3*Math.sqrt(1.0-a*a); return((b2-b3)/b1); } double test(double u) { double d1,d2,d3,d4; Triangle T=this; double t=1.0; Complex z=new Complex(); d1=lowerLimit(); d2=upperLimit(); d3=(d1+d2)/2.0; /*center*/ d4=d2-d3; /*radius*/ z.x=d3+d4*Math.cos(Math.PI*u); z.y=-d4*Math.sin(Math.PI*u); z=z.inverse(z); if(z.norm(z)<1.0) { T.b=z; Vector V=T.angle2(); t=-a3+V.z.x; } return(t); } Complex convert(double u) { double d1,d2,d3,d4; Complex z=new Complex(); d1=lowerLimit(); d2=upperLimit(); d3=(d1+d2)/2.0; /*center*/ d4=(d2-d1)/2.0; /*radius*/ z.x=d3+d4*Math.cos(Math.PI*u); z.y=d4*Math.sin(Math.PI*u); z=z.inverse(z); return(z); } Triangle flow() { Triangle T=this; double u1=0.0; double u2=1.0; double u3=0.5; double test=0.0; for(int i=1;i<=50;++i) { u3=(u1+u2)/2.0; test=T.test(u3); if(test<0) u2=u3; if(test>=0) u1=u3; } Complex z=this.convert(u3); T.b=z; return(T); } int hypTest(double u) { Triangle T=new Triangle(); T.a=u*a; T.b=b; T.x=x; T.a1=a1; T.a2=a2; T.a3=a3; T=T.flow(); TriangleGroup G=new TriangleGroup(T); int test1=G.hypTest(); int test2=T.match(); int test3=1; if((test1==0)&&(test2==0)) test3=0; return(test3); } double parabolicParameter() { double u1=0.0; double u2=1.0; double u3=0.5; double test=0.0; for(int i=1;i<=50;++i) { u3=(u1+u2)/2.0; test=hypTest(u3); if(test==0) u2=u3; if(test==1) u1=u3; } return(u3); } } class WordSelector extends DBCanvas implements MouseListener { Word W; GroupSelector X; int n; Color C1,C2,C3; WordSelector(GroupSelector X,int n,Color C1,Color C2,Color C3) { this.X=X; this.n=n; this.C1=C1; this.C2=C2; this.C3=C3; W=new Word(); W=W.reset(); this.setSize(n,20); addMouseListener(this); } public void paint(Graphics g) { g.setColor(C1); g.fillRect(0,0,n,20); g.setColor(C2); g.fillRect(0,0,n-100,20); g.setColor(C3); g.translate(n-20,0); g.drawRect(1,1,18,18); g.drawString("*",5,15); g.translate(-20,0); g.drawRect(1,1,18,18); g.drawString("3",5,15); g.translate(-20,0); g.drawRect(1,1,18,18); g.drawString("2",5,15); g.translate(-20,0); g.drawRect(1,1,18,18); g.drawString("1",5,15); g.translate(-20,0); g.drawRect(1,1,18,18); g.drawString("-",5,15); g.translate(-n+100,0); g.drawRect(0,0,n-102,19); W.render(g,n); } public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseClicked(MouseEvent e) { e.consume(); Point P=new Point(); P.x=e.getX(); P.y=e.getY(); int val; val=0; if((P.x>n-20)&&(P.x0)&&(P.y<20)) val=4; if((P.x>n-40)&&(P.x0)&&(P.y<20)) val=3; if((P.x>n-60)&&(P.x0)&&(P.y<20)) val=2; if((P.x>n-80)&&(P.x0)&&(P.y<20)) val=1; if((P.x>n-100)&&(P.x0)&&(P.y<20)) val=0; if(val==0) W=W.strip(); if(val==1) W=W.compose1(); if(val==2) W=W.compose2(); if(val==3) W=W.compose3(); if(val==4) W=W.reset(); repaint(); } } class Word { int l; int[] n=new int[300]; Word() { l=0; } Word reset() { Word w=this; w.l=0; return(w); } Word strip() { Word w=this; if(w.l>0) --w.l; return(w); } Word compose1() { Word w=this; int ll=l; if(n[ll]==1) w.l=l-1; if(n[ll]!=1) {w.l=l+1;w.n[l]=1;} return(w); } Word compose2() { Word w=this; int ll=l; if(n[ll]==2) w.l=l-1; if(n[ll]!=2) {w.l=l+1;w.n[l]=2;} return(w); } Word compose3() { Word w=this; int ll=l; if(n[ll]==3) w.l=l-1; if(n[ll]!=3) {w.l=l+1;w.n[l]=3;} return(w); } void render(Graphics g,int nn) { g.setColor(Color.white); if(l==0) g.drawString("e",nn-115,15); int ll=1; int space=0; while(ll<=l) { if(n[ll]==1) g.drawString("1",nn-115-space,15); if(n[ll]==2) g.drawString("2",nn-115-space,15); if(n[ll]==3) g.drawString("3",nn-115-space,15); space=space+8; ++ll; } } } class TriangleSelector extends DBCanvas implements MouseListener { GroupSelector X; ParameterSelector P; int a,b,c; Color C1,C2,C3; Color[] COL=new Color[4]; String S; int error; ListenSquare[][] L=new ListenSquare[4][6]; TriangleSelector(GroupSelector X, Color C1,Color C2, int a,int b,int c) { S=new String(); this.X=X; this.a=a; this.b=b; this.c=c; this.C1=C1; this.C2=C2; error=0; COL[1]=new Color(255,0,0); COL[2]=new Color(0,0,255); COL[3]=new Color(0,230,0); S=""; addMouseListener(this); this.setSize(400,17); for(int j=1;j<=3;++j) { for(int i=1;i<=2;++i) { L[j][i]=new ListenSquare(150*j-150+16*i-16,1,14,15); }} for(int j=1;j<=3;++j) { for(int i=3;i<=4;++i) { L[j][i]=new ListenSquare(150*j-120+16*i-16,1,14,15); }} } public void paint(Graphics g) { g.setColor(Color.black); g.fillRect(0,0,400,20); g.setColor(COL[1].darker()); g.fillRect(0,0,93,17); g.setColor(COL[2].darker()); g.fillRect(150,0,93,17); g.setColor(COL[3].darker()); g.fillRect(300,0,93,17); for(int j=1;j<=3;++j) { for(int i=1;i<=4;++i) { L[j][i].render(g,COL[j]); }} g.setColor(Color.white); g.setFont(new Font("TimesRoman",Font.PLAIN,14)); Integer aa=new Integer(a); Integer bb=new Integer(b); Integer cc=new Integer(c); g.drawString(aa.toString(a),35,15); g.drawString(bb.toString(b),185,15); g.drawString(cc.toString(c),335,15); if(error==1) g.drawString("error",105,12); } public void mouseClicked(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); if(L[1][1].inside(p)==1) a=a-10; if(L[1][2].inside(p)==1) a=a-1; if(L[1][3].inside(p)==1) a=a+1; if(L[1][4].inside(p)==1) a=a+10; if(L[2][1].inside(p)==1) b=b-10; if(L[2][2].inside(p)==1) b=b-1; if(L[2][3].inside(p)==1) b=b+1; if(L[2][4].inside(p)==1) b=b+10; if(L[3][1].inside(p)==1) c=c-10; if(L[3][2].inside(p)==1) c=c-1; if(L[3][3].inside(p)==1) c=c+1; if(L[3][4].inside(p)==1) c=c+10; if(a<3) a=3; if(b<3) b=3; if(c<3) c=3; if(a>999) a=999; if(b>999) b=999; if(c>999) c=999; if((a==3)&&(b==3)&&(c==3)) { a=3;b=3;c=4; } repaint(); X.T=new Triangle(a,b,c); X.G=new TriangleGroup(X.T); X.PS.parameter=1.0; X.PS.H.POS=383; X.PS.repaint(); X.K.repaint(); } public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} } class ParameterSelector extends DBCanvas implements MouseListener { int par[]=new int[20]; double parameter; GroupSelector X; HorizontalSlider H; ListenSquare L1,L2; ParameterSelector(GroupSelector X) { addMouseListener(this); this.setSize(400,16); this.X=X; H=new HorizontalSlider(17,0,366,16,383,new Color(100,0,150)); L1=new ListenSquare(0,1,15,17); L2=new ListenSquare(385,1,17,17); } public void paint(Graphics g) { g.setColor(Color.black); g.fillRect(0,0,400,20); H.render(g); L1.render(g,new Color(0,150,100)); L2.render(g,new Color(0,150,100)); g.setColor(new Color(140,220,200)); g.setFont(new Font("TimesRoman",Font.PLAIN,12)); g.drawString("parameter",30,10); } public void mousePressed(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); if(H.inside(p)==1) H.ACTIVE=1; } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mouseReleased(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); if(L1.inside(p)==1) { H.POS=17; parameter=X.T.PARABOLIC; repaint(); } if(L2.inside(p)==1) { H.POS=383; parameter=1.0; repaint(); } if(H.ACTIVE==1) { double pp=0.0; H.configure(p); repaint(); H.ACTIVE=0; pp=1.0*(H.POS-H.x)/H.w; parameter=(1.0-pp)*X.T.PARABOLIC+pp; } X.T=new Triangle(X.TS.a,X.TS.b,X.TS.c); X.T.a=parameter*X.T.a; repaint(); X.T=X.T.flow(); X.K.repaint(); X.G=new TriangleGroup(X.T); double ev=0.0; int test=X.T.match(); if(test==0) {X.TS.error=0;} if(test==1) {X.TS.error=1;} X.TS.repaint(); X.C.init=1; X.C.repaint(0,0,500,120); } } class SketchPad extends DBCanvas { GroupSelector X; Complex[] z=new Complex[300]; int count; SketchPad(GroupSelector X) { this.X=X; this.setSize(402,402); for(int i=0;i<=299;++i) z[i]=new Complex(); count=1; } public void paint(Graphics g) { g.setColor(new Color(150,0,150)); g.fillRect(0,0,400,400); g.setColor(Color.white); g.setFont(new Font("TimesRoman",Font.PLAIN,18)); g.drawString("Rich: Applet 29",230,20); g.drawString("complex hyperbolic",230,40); g.drawString("triangle groups",230,60); g.setColor(Color.black); g.fillOval(-400,0,800,800); g.setColor(Color.white); g.drawOval(-400,0,800,800); g.translate(0,400); int x=(int)(400*X.T.b.x); int y=(int)(-400*X.T.b.y); double d1=1.0/X.T.lowerLimit(); d1=400*d1; double d2=1.0/X.T.upperLimit(); d2=400*d2; double d3=(-d1+d2)/2; if(d3<0) d3=-d3; double d4=d1; if (d20)&&(A2>0)&&(A3>0)) val=1; return(val); } int inside(Complex p) { double v1x,v1y,v2x,v2y; double A1,A2,A3; int val; v1x=p.x-this.x1; v1y=p.y-this.y1; v2x=p.x-this.x2; v2y=p.y-this.y2; A3=v1x*v2y-v1y*v2x; v1x=p.x-this.x2; v1y=p.y-this.y2; v2x=p.x-this.x3; v2y=p.y-this.y3; A1=v1x*v2y-v1y*v2x; v1x=p.x-this.x3; v1y=p.y-this.y3; v2x=p.x-this.x1; v2y=p.y-this.y1; A2=v1x*v2y-v1y*v2x; val=0; double tol=0.0; if((A1-tol)&&(A2>-tol)&&(A3>-tol)) val=1; return(val); } void render(Graphics g,Color C) { int x[]={(int)(x1),(int)(x2),(int)(x3)}; int y[]={(int)(y1),(int)(y2),(int)(y3)}; g.setColor(C); g.fillPolygon(x,y,3); } } class ListenSquare { int x,y,w,h; Color C; String S; ListenSquare(int x,int y,int w,int h) { this.x=x; this.y=y; this.h=h; this.w=w; this.C=C; } void render(Graphics g,Color C) { g.setColor(C); g.fillRect(x,y,w,h); g.drawRect(x,y,w,h); g.setColor(Color.black); } int inside(Point p) { int test=0; if((p.x>x)&&(p.xy)&&(p.yx)) POS=p.x; } int inside(Point p) { int test=0; if((p.x>x)&&(p.xy)&&(p.y