import java.applet.Applet; import java.awt.event.*; import java.awt.*; /**************************** Strip Manipulator by Rich Schwartz March 2004 For Michelle Fornabai *****************************/ /****************************************** This first routine lays out the playing board. There are 5 basic panels: - west panel: ControlCanvas - east panel: Manager - north panel: StripCanvas - south panel: Strip Canvas - middle panel: View Canvas **************************************************/ public class test1 extends Applet { GridBagLayout board; GridBagConstraints c; ControlCanvas C; ViewCanvas V; Manager M; StripCanvas S1; StripCanvas S2; Panel P; public void init() { board=new GridBagLayout(); c=new GridBagConstraints(); c.gridwidth=GridBagConstraints.REMAINDER; setLayout(board); setBackground(Color.black); /*objects*/ V=new ViewCanvas(); C=new ControlCanvas(); S1=new StripCanvas(1); S2=new StripCanvas(2); V=new ViewCanvas(); M=new Manager(C,S1,S2,V); /*geometry*/ C.setSize(180,350); V.setSize(540,350); M.setSize(180,350); S1.setSize(900,150); S2.setSize(900,150); /*colors*/ V.setBackground(new Color(0,0,0)); C.setBackground(new Color(0,0,220)); M.setBackground(new Color(0,0,220)); S1.setBackground(new Color(0,0,220)); S2.setBackground(new Color(0,0,220)); /*packing of objects*/ c.gridwidth=GridBagConstraints.REMAINDER; board.setConstraints(S2,c); c.gridwidth=1; board.setConstraints(C,c); board.setConstraints(V,c); c.gridwidth=GridBagConstraints.REMAINDER; board.setConstraints(M,c); board.setConstraints(S1,c); add(S2); add(C); add(V); add(M); add(S1); C=C.addManager(M); V=V.addManager(M); S1=S1.addManager(M); S2=S2.addManager(M); } } class DocumentCanvas extends DBCanvas { int message; DocumentCanvas() { message=0; } } class Manager extends DBCanvas implements MouseListener,MouseMotionListener { ControlCanvas C; StripCanvas S1; StripCanvas S2; ViewCanvas V; ListenSquare[][] L=new ListenSquare[11][11]; ListenTriangle T; double step1,step2,distance,twist,bend; int toggle; Manager() { this.C=C; this.S1=S1; this.S2=S2; this.V=V; } Manager(ControlCanvas C,StripCanvas S1,StripCanvas S2,ViewCanvas V) { this.C=C; this.S1=S1; this.S2=S2; this.V=V; addMouseListener(this); addMouseMotionListener(this); step1=.015; step1=.015; distance=1.0; twist=1.0; bend=1.0; /*Annealing method controls*/ for(int i=1;i<=2;++i) { for(int j=1;j<=6;++j) { L[3-i][j]=new ListenSquare(-7+17*j,17*i,17,17); L[3-i][j].C=new Color(0,160,0); } } L[7][1]=new ListenSquare(112,17,34,34); L[7][1].C=new Color(0,200,0); L[9][1]=new ListenSquare(146,17,17,17); L[9][1].C=new Color(0,200,0); L[9][2]=new ListenSquare(146,34,17,17); L[9][2].C=new Color(0,200,0); /*Annealing step size controls*/ L[3][1]=new ListenSquare(10,60,110,20); L[3][1].C=Color.magenta; L[3][2]=new ListenSquare(50,62,4,16); L[3][2].C=Color.white; L[8][1]=new ListenSquare(10,95,110,20); L[8][1].C=Color.orange; L[8][2]=new ListenSquare(50,97,4,16); L[8][2].C=Color.white; T=new ListenTriangle(); T.x1=30; T.y1=160; T.x2=90; T.y2=250; T.x3=150; T.y3=160; /*twist toggle*/ L[10][1]=new ListenSquare(20,220,20,20); L[10][1].C=Color.red; L[10][2]=new ListenSquare(20,240,20,20); L[10][2].C=new Color(100,100,255); /*objective function controls: distance component*/ for(int j=1;j<=5;++j) { L[4][j]=new ListenSquare(134,215-15*j,35-5*j,15); L[4][j].C=new Color(100,100,255); } L[4][1].C=Color.red; /*objective function controls: bend component*/ for(int j=1;j<=5;++j) { L[5][j]=new ListenSquare(16,215-15*j,35-5*j,15); L[5][j].C=new Color(100,100,255); } L[5][4].C=Color.red; /*objection function controls: twist component*/ for(int j=1;j<=5;++j) { L[6][j]=new ListenSquare(75,215-15*j,35-5*j,15); L[6][j].C=new Color(100,100,255); } L[6][4].C=Color.red; /*numerical displays*/ } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(new Color(50,50,255)); g.drawRect(1,1,178,348); g.drawRect(2,2,176,346); /*the buttons*/ L[9][1].render(g); L[9][2].render(g); L[10][1].render(g); L[10][2].render(g); for(int i=1;i<=2;++i) { for(int j=1;j<=6;++j) { L[i][j].render(g); }} for(int j=1;j<=2;++j) L[3][j].render(g); for(int j=1;j<=2;++j) L[8][j].render(g); L[7][1].render(g); T.render(g); /*triangle markings*/ g.setColor(Color.green); g.fillRect(154,156,5,5); g.setColor(Color.magenta); g.fillRect(88,252,5,5); g.setColor(Color.yellow); g.fillRect(24,156,5,5); g.setColor(Color.white); g.drawString("d",154,154); g.drawString("b",23,154); g.drawString("t",95,257); double xx=(bend*T.x1+twist*T.x2+distance*T.x3)/(bend+twist+distance); double yy=(bend*T.y1+twist*T.y2+distance*T.y3)/(bend+twist+distance); g.setColor(Color.red); g.drawRect((int)(xx-2),(int)(yy-2),4,4); DoubleDisplay D1=new DoubleDisplay(8,275,3,2); D1.C=Color.green; DoubleDisplay D2=new DoubleDisplay(8,297,3,2); D2.C=Color.magenta; DoubleDisplay D3=new DoubleDisplay(8,319,3,2); D3.C=Color.yellow; if(V.state==1) { double d1=V.tipDistance(V.F); double d2=V.tipTwist(V.F); double d3=V.tipBend(V.F); D1.toDisplay(d1); D2.toDisplay(d2); D3.toDisplay(d3); } D1.render(g); D2.render(g); D3.render(g); g.setColor(Color.white); g.translate(0,-10); g.drawString("distance",120,300); g.drawString("twist",120,320); g.drawString("bend",120,340); g.translate(0,10); g.drawString("angle",130,72); g.drawString("crease",130,107); g.drawString("+",10,92); g.drawString("-",110,92); } void REPAINT() { repaint(); V.repaint(); S1.repaint(); S2.repaint(); } /*mouse events*/ /*pressing is only active on the first press, at most.*/ public void mousePressed(MouseEvent e) { if(V.state==0) { V.s1=V.s1.adapt(S1.C,1,S1.length); V.s2=V.s2.adapt(S2.C,2,S2.length); V.state=1; REPAINT(); } } public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseDragged(MouseEvent e) { /*Annealing step size selectors*/ e.consume(); Point P=new Point(); P.x=e.getX(); P.y=e.getY(); S1.message=600; if(L[3][1].inside(P)==1) { double x=(P.x-L[3][1].x1)/L[3][1].x2; x=10.0*x; step1=0.25*Math.pow(.5,x); L[3][2].x1=11.0*x+8; } if(L[8][1].inside(P)==1) { double x=(P.x-L[8][1].x1)/L[8][1].x2; x=10.0*x; step2=0.25*Math.pow(.5,x); L[8][2].x1=11.0*x+8; } repaint(); } public void mouseMoved(MouseEvent e) { e.consume(); Point P=new Point(); P.x=e.getX(); P.y=e.getY(); S1.message=600; for(int i=1;i<=2;++i) { for(int j=1;j<=6;++j) { if(L[i][j].inside(P)==1) S1.message=601; } } for(int j=1;j<=2;++j) { if(L[3][j].inside(P)==1) S1.message=605; if(L[8][j].inside(P)==1) S1.message=606; } if(L[7][1].inside(P)==1) S1.message=602; if(L[9][1].inside(P)==1) S1.message=603; if(L[9][2].inside(P)==1) S1.message=604; if(L[10][1].inside(P)==1) S1.message=607; if(L[10][2].inside(P)==1) S1.message=608; if(T.inside(P)==1) S1.message=609; if((P.x<110)&&(P.y>278)) S1.message=610; S1.repaint(); } public void mouseClicked(MouseEvent e) { e.consume(); Point P=new Point(); P.x=e.getX(); P.y=e.getY(); /* interactive Annealing method.*/ for(int i=1;i<=2;++i) { for(int j=1;j<=6;++j) { if(L[i][j].inside(P)==1) anneal(i,j); } } /*Annealing step size selectors*/ if(L[3][1].inside(P)==1) { double x=(P.x-L[3][1].x1)/L[3][1].x2; x=10.0*x; step1=0.25*Math.pow(.5,x); L[3][2].x1=11.0*x+8; } if(L[8][1].inside(P)==1) { double x=(P.x-L[8][1].x1)/L[8][1].x2; x=10.0*x; step2=0.25*Math.pow(.5,x); L[8][2].x1=11.0*x+8; } if(L[10][1].inside(P)==1) { toggle=1; L[10][1].C=Color.red; L[10][2].C=new Color(100,100,255); } if(L[10][2].inside(P)==1) { toggle=2; L[10][2].C=Color.red; L[10][1].C=new Color(100,100,255); } if(T.inside(P)==1) { double x1=T.x1; double x2=T.x2; double x3=T.x3; double y1=T.y1; double y2=T.y2; double y3=T.y3; double x=P.x; double y=P.y; bend=(x2*y-x3*y-x*y2+x3*y2+x*y3-x2*y3)/(x2*y1-x3*y1-x1*y2+x3*y2+x1*y3-x2*y3); twist=-((x1*y-x3*y-x*y1+x3*y1+x*y3-x1*y3)/(x2*y1-x3*y1-x1*y2+x3*y2+x1*y3-x2*y3)); distance=1-twist-bend; } /*automatic Annealing method selectors*/ if(L[7][1].inside(P)==1) anneal(); if(L[9][2].inside(P)==1) anneal2(1); if(L[9][1].inside(P)==1) anneal2(2); REPAINT(); } /*NOTE: doesn't move the first bend. This can be easily altered by changing the i&j range*/ void anneal() { for(int i=1;i<=2;++i) { for(int j=1;j<=6;++j) { anneal(i,j); } } } void anneal2(int k) { for(int i=k;i<=k;++i) { for(int j=1;j<=6;++j) { anneal(i,j); } } } void anneal(int i,int j) { double twist1=0.0; Vector VV=new Vector(distance,twist,bend); double d=VV.dot(VV,V.tipGoal(V.F)); for(int i1=-1;i1<=1;++i1) { for(int i2=-1;i2<=1;++i2) { for(int i3=-1;i3<=1;++i3) { flow(i,j,d*i1*step2,d*i2*step2,d*i3*step1); }}} } void flow(int i,int j,double d1,double d2,double d3) { double dd1=goal(i,j,0,0,0,toggle); double dd2=goal(i,j,d1,d2,d3,toggle); if(dd2S1.C[j+1].top) dd=1000000; if(C1[j].topS1.C[j+1].bot) dd=1000000; if(C1[j].bot360) dd=100000; } if(i==2) { C2[j].top=C2[j].top+d1; C2[j].bot=C2[j].bot+d2; C2[j].a=C2[j].a+d3; if(C2[j].top>S2.C[j+1].top) dd=1000000; if(C2[j].topS2.C[j+1].bot) dd=1000000; if(C2[j].bot360) dd=100000; } Strip s1=V.s1.adapt(C1,1,S1.length); Strip s2=V.s2.adapt(C2,2,S2.length); Vector WW=new Vector(distance,twist,bend); d=WW.dot(WW,V.tipGoal(s1,s2,tog)); return(d+dd); } } /*Double Buffering for good graphics*/ 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 StripCanvas extends DBCanvas implements MouseListener,MouseMotionListener { Manager M; String St[]=new String[10]; int number,message,history; ListenTriangle[][] T=new ListenTriangle[10][10]; ListenTriangle[][] S=new ListenTriangle[20][20]; ListenSquare[] L=new ListenSquare[10]; ListenSquare[] MEM=new ListenSquare[25]; ListenSquare NUM[][] = new ListenSquare[4][12]; ListenSquare TUT1,TUT2; Bend[] C=new Bend[9]; Bend[][] CC=new Bend[23][9]; Bend[] RECORD =new Bend[5000]; int bend,mem,undo; double length; double top1,top2,bot1,bot2,a1,a2; StripCanvas addManager(Manager MM) { StripCanvas X=this; X.M=MM; return(X); } StripCanvas(int k) { addMouseListener(this); addMouseMotionListener(this); setBackground(Color.black); this.bend=7; this.number=k; this.length=480.0; undo=0; message=0; history=1; /* bend line control keys*/ /*top*/ for(int j=1;j<=5;++j) { T[1][j]=new ListenTriangle(); T[1][j].C=new Color(50,50,255); T[1][j].x1=356+14*j; T[1][j].y1=12; T[1][j].x2=373+14*j; T[1][j].y2=20; T[1][j].x3=356+14*j; T[1][j].y3=28; } for(int j=1;j<=5;++j) { T[2][j]=new ListenTriangle(); T[2][j].C=new Color(50,50,255); T[2][j].x1=383-14*j; T[2][j].y1=12; T[2][j].x2=366-14*j; T[2][j].y2=20; T[2][j].x3=383-14*j; T[2][j].y3=28; } /*bottom*/ for(int j=1;j<=5;++j) { T[3][j]=new ListenTriangle(); T[3][j].C=new Color(50,50,255); T[3][j].x1=356+14*j; T[3][j].y1=138; T[3][j].x2=373+14*j; T[3][j].y2=130; T[3][j].x3=356+14*j; T[3][j].y3=122; } for(int j=1;j<=5;++j) { T[4][j]=new ListenTriangle(); T[4][j].C=new Color(50,50,255); T[4][j].x1=383-14*j; T[4][j].y1=138; T[4][j].x2=366-14*j; T[4][j].y2=130; T[4][j].x3=383-14*j; T[4][j].y3=122; } for(int i=1;i<=2;++i) { for(int j=1;j<=5;++j) { T[i][j].translate(-129,16); }} for(int i=3;i<=4;++i) { for(int j=1;j<=5;++j) { T[i][j].translate(-129,-16); }} /*alternate entry system*/ NUM[1][0]=new ListenSquare(520,27,20,20); NUM[1][0].C=Color.red; NUM[1][1]=new ListenSquare(520,5,95,20); NUM[1][1].C=new Color(0,0,255); NUM[1][2]=new ListenSquare(520,7,4,16); NUM[1][2].C=Color.white; NUM[1][3]=new ListenSquare(620,5,95,20); NUM[1][3].C=new Color(0,0,255); NUM[1][4]=new ListenSquare(620,7,4,16); NUM[1][4].C=Color.white; NUM[1][5]=new ListenSquare(568,26,11,11); NUM[1][5].C=new Color(0,0,255); NUM[1][6]=new ListenSquare(568,37,11,11); NUM[1][6].C=new Color(0,0,255); NUM[1][7]=new ListenSquare(663,26,11,11); NUM[1][7].C=new Color(0,0,255); NUM[1][8]=new ListenSquare(663,37,11,11); NUM[1][8].C=new Color(0,0,255); NUM[2][0]=new ListenSquare(520,77,20,20); NUM[2][0].C=Color.green; NUM[2][1]=new ListenSquare(520,55,95,20); NUM[2][1].C=new Color(0,0,255); NUM[2][2]=new ListenSquare(520,57,4,16); NUM[2][2].C=Color.white; NUM[2][3]=new ListenSquare(620,55,95,20); NUM[2][3].C=new Color(0,0,255); NUM[2][4]=new ListenSquare(620,57,4,16); NUM[2][4].C=Color.white; NUM[2][5]=new ListenSquare(548,76,11,11); NUM[2][5].C=new Color(0,0,255); NUM[2][6]=new ListenSquare(548,87,11,11); NUM[2][6].C=new Color(0,0,255); NUM[2][7]=new ListenSquare(663,76,11,11); NUM[2][7].C=new Color(0,0,255); NUM[2][8]=new ListenSquare(663,87,11,11); NUM[2][8].C=new Color(0,0,255); NUM[3][0]=new ListenSquare(520,127,20,20); NUM[3][0].C=Color.orange; NUM[3][1]=new ListenSquare(520,105,95,20); NUM[3][1].C=new Color(0,0,255); NUM[3][2]=new ListenSquare(520,107,4,16); NUM[3][2].C=Color.white; NUM[3][3]=new ListenSquare(620,105,95,20); NUM[3][3].C=new Color(0,0,255); NUM[3][4]=new ListenSquare(620,107,4,16); NUM[3][4].C=Color.white; NUM[3][5]=new ListenSquare(568,126,11,11); NUM[3][5].C=new Color(0,0,255); NUM[3][6]=new ListenSquare(568,137,11,11); NUM[3][6].C=new Color(0,0,255); NUM[3][7]=new ListenSquare(663,126,11,11); NUM[3][7].C=new Color(0,0,255); NUM[3][8]=new ListenSquare(663,137,11,11); NUM[3][8].C=new Color(0,0,255); top1=0; bot1=0; a1=0; top2=0; bot2=0; a2=0; /*memory buttons*/ mem=1; for(int j=0;j<=1;++j) for(int i=0;i<=9;++i) { MEM[1+10*j+i]=new ListenSquare(348+15*i,116+15*j,15,15); MEM[1+10*j+i].C=new Color(50,50,255); } MEM[21]=new ListenSquare(460,8,20,20); MEM[21].C=Color.yellow; MEM[22]=new ListenSquare(460,28,20,20); MEM[22].C=new Color(50,50,255); MEM[24]=new ListenSquare(375,8,20,20); MEM[24].C=Color.magenta; MEM[23]=new ListenSquare(375,28,20,20); MEM[23].C=Color.magenta; /*bend angle controls*/ for(int j=1;j<=5;++j) { S[1][j]=new ListenTriangle(); S[1][j].x1=690+14*j; S[1][j].y1=14; S[1][j].x2=706+14*j; S[1][j].y2=22; S[1][j].x3=690+14*j; S[1][j].y3=30; S[1][j].C=new Color(50,50,255); } for(int j=1;j<=5;++j) { S[2][j]=new ListenTriangle(); S[2][j].x1=716-14*j; S[2][j].y1=14; S[2][j].x2=702-14*j; S[2][j].y2=22; S[2][j].x3=716-14*j; S[2][j].y3=30; S[2][j].C=new Color(50,50,255); } for(int i=1;i<=2;++i) { for(int j=1;j<=5;++j) { S[i][j].translate(-628,92); }} /*documentation strings*/ for(int i=0;i<=7;++i) St[i]=new String(); /*initial bend data*/ for(int i=0;i<=20;++i) { for(int j=1;j<=6;++j) { CC[i][j]=new Bend(); CC[i][j].x1=-15+25*j; CC[i][j].y1=10; CC[i][j].x2=20; CC[i][j].y2=20; CC[i][j].a=180; CC[i][j].C=Color.orange; CC[i][j].top=60+60*j; CC[i][j].bot=60+60*j; CC[i][j].s=0; CC[i][1].a=180; }} for(int i=1;i<=6;++i) C[i]=CC[0][i]; for(int i=0;i<=20;++i) { CC[i][7]=new Bend(); CC[i][7].x1=2; CC[i][7].y1=65; CC[i][7].x2=20; CC[i][7].y2=20; CC[i][7].C=new Color(0,150,0); CC[i][7].a=360.0; CC[i][7].top=-10; CC[i][7].bot=-10; CC[i][7].s=1; } for(int i=1;i<=7;++i) C[i]=CC[0][i]; C[0]=new Bend(); C[0].top=0.0; C[0].bot=0.0; C[0].a=0; C[7].top=length; C[7].bot=length; C[7].a=0.0; /*tutorial control*/ TUT1=new ListenSquare(158,128,20,20); TUT2=new ListenSquare(158,108,20,20); TUT1.C=Color.white; TUT2.C=new Color(50,50,255); } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(new Color(50,50,255)); g.drawRect(0,0,600,149); g.drawRect(1,1,599,147); /*numerical entry and display system*/ g.setColor(new Color(0,0,255)); g.fillRect(518,0,202,160); g.setColor(new Color(50,50,250)); g.drawRect(518,0,202,149); g.drawRect(519,1,200,147); for(int i=1;i<=3;++i) { for(int j=0;j<=8;++j) { NUM[i][j].render(g); }} DoubleDisplay N1=new DoubleDisplay(581,27,2,2); N1.C=Color.red; N1.toDisplay(top1+top2); N1.render(g); DoubleDisplay N2=new DoubleDisplay(561,77,3,2); N2.C=Color.green; N2.toDisplay(a1+a2); N2.render(g); DoubleDisplay N3=new DoubleDisplay(581,127,2,2); N3.C=Color.orange; N3.toDisplay(bot1+bot2); N3.render(g); DoubleDisplay X1=new DoubleDisplay(200,3,2,2); X1.C=Color.red; if(M.V.state==1) { X1.toDisplay(C[bend].top/10.0); } X1.render(g); DoubleDisplay X2=new DoubleDisplay(200,126,2,2); X2.C=new Color(255,100,0); if(M.V.state==1) { X2.toDisplay(C[bend].bot/10.0); } X2.render(g); DoubleDisplay X3=new DoubleDisplay(25,126,3,2); X3.C=Color.green; if(M.V.state==1) { X3.toDisplay(C[bend].a); } X3.render(g); /*memory buttons*/ for(int i=1;i<=24;++i) MEM[i].render(g); g.setColor(Color.white); g.drawString("recall",422,42); g.drawString("save",422,22); g.drawString("reset",336,22); g.drawString("undo",336,42); g.drawString("memory",400,111); g.drawString("in.",285,17); g.drawString("in.",285,145); g.drawString("degrees",135,143); g.drawString("select bend",44,47); /*the strip and its markers*/ int number2=0; if(number==1) number2=1; if(number==2) number2=4; int trans=30; g.translate(trans,0); g.setColor(Color.black); g.fillRect(-2,61,484,30); for(int i=0;i<=6;++i) { int[] X={(int)(C[i].top/2.0),(int)(C[i].bot/2.0),(int)(C[i+1].bot/2.0),(int)(C[i+1].top/2.0)}; int[] Y={64,88,88,64}; g.setColor(M.C.LL[number2][i+1].C); g.fillPolygon(X,Y,4); } /*the ruling lines*/ g.setColor(Color.green); for(int i=0;i<=8;++i) { g.drawLine(60*i,54,60*i,60); g.drawLine(60*i,91,60*i,97); } for(int i=0;i<=16;++i) { g.drawLine(30*i,56,30*i,60); g.drawLine(30*i,91,30*i,95); } for(int i=0;i<=96;++i) { g.drawLine(5*i,58,5*i,60); g.drawLine(5*i,91,5*i,93); } g.translate(-trans,0); /*draw control keys*/ for(int i=1;i<=4;++i) { for(int j=1;j<=4;++j) { T[i][j].render(g); }} for(int i=1;i<=2;++i) { for(int j=1;j<=4;++j) { S[i][j].render(g); }} for(int i=1;i<=6;++i) C[i].render(g); C[7].specialRender(g); /*documentation*/ g.translate(720,0); g.setColor(Color.black); g.fillRect(0,0,180,180); g.setColor(new Color(50,50,255)); g.drawRect(1,1,178,148); g.drawRect(2,2,176,146); g.setColor(Color.white); if(number==2) { g.setColor(Color.white); g.drawString("RICH: APPLET 44",10,20); g.drawString("Strip Manipulator",10,40); g.drawString("Click here to start.",10,60); g.drawString("text window on",65,142); g.drawString("text window off",65,122); TUT1.render(g); TUT2.render(g); } for(int i=0;i<=7;++i) { St[i]=""; } if(message==0) { St[0]="this window documents the"; St[1]="applet. To learn the function"; St[2]="of an object on the screen"; St[3]="move the mouse over that"; St[4]="object and read here"; St[5]="about what it does. "; St[6]="(Or click the mouse"; St[7]="and see what happens.)"; } if(message==1) { St[0]="memory console:"; St[1]="if the SAVE button is"; St[2]="yellow then a click"; St[3]="here saves the strip"; St[4]="configuration. If the"; St[5]="RECALL button is yellow"; St[6]="then a click here"; St[7]="retrieves the info."; } if(message==2) { St[0]="click/drag this scale"; St[1]="to change the # below."; St[2]="The # specifies the "; St[3]="distance from the base of"; St[4]="the strip to the point"; St[5]="of intersection between"; St[6]="the top edge of the"; St[7]="strip and the bend line."; } if(message==3) { St[0]="click/drag this scale"; St[1]="to change the # below."; St[2]="The # specifies the "; St[3]="bending angle of the"; St[4]="selected bend."; } if(message==4) { St[0]="click/drag this scale"; St[1]="to change the # below."; St[2]="The # specifies the "; St[3]="distance from the base of"; St[4]="the strip to the point"; St[5]="of intersection between"; St[6]="the bottom edge of the"; St[7]="strip and the bend line."; } if(message==6) { St[0]="click here to increment"; St[1]="the displayed number by"; St[2]="1 unit."; } if(message==8) { St[0]="number entry console:"; St[1]="click here to enter the #"; St[2]="at right, which specifies"; St[3]="the distance from the"; St[4]="base of the strip to the"; St[5]="point of intersection of"; St[6]="the selected bend line and"; St[7]="the top edge of the strip."; } if(message==9) { St[0]="number entry console:"; St[1]="click here to enter the #"; St[2]="at right, which specifies"; St[3]="the bending angle of the"; St[4]="selected bend"; } if(message==10) { St[0]="number entry console:"; St[1]="click here to enter the #"; St[2]="at right, which specifies"; St[3]="the distance from the"; St[4]="base of the strip to the"; St[5]="point of intersection of"; St[6]="the selected bend line and"; St[7]="the bottom edge of the strip."; } if(message==14) { St[0]="number display:"; St[1]="this # displays"; St[2]="the distance from the"; St[3]="base of the strip to the"; St[4]="point of intersection of"; St[5]="the selected bend line and"; St[6]="the top edge of the strip."; } if(message==15) { St[0]="number display:"; St[1]="this # displays"; St[2]="the bend angle of the"; St[3]="selected bend"; } if(message==16) { St[0]="number display:"; St[1]="this # displays"; St[2]="the distance from the"; St[3]="base of the strip to the"; St[4]="point of intersection of"; St[5]="the selected bend line and"; St[6]="the botton edge of the strip."; } if(message==17) { St[0]="arrow keys:"; St[1]="use these keys to modify"; St[2]="number adjacent to the"; St[3]="keys. The outer arrows"; St[4]="make big modifications"; St[5]="and the inner arrows make"; St[6]="small modifications"; } if(message==131) { St[0]="eye buttons:"; St[1]="changes the direction of"; St[2]="of the eye's gaze."; } if(message==220) { St[0]="eye control buttons:"; St[1]="moves the observer around"; St[2]="a latitude line on the"; St[3]="hemisphere and thereby"; St[4]="rotates the image around"; } if(message==226) { St[0]="use this scale to zoom"; } if(message==225) { St[0]="use this scale to zoom"; } if(message==227) { St[0]="eye control buttons:"; St[1]="moves the observer around"; St[2]="a latitude line on the"; St[3]="hemisphere and thereby"; St[4]="rotates the image around"; } if(message==131) { St[0]="eye control buttons:"; St[1]="changes the direction of"; St[2]="of the eye's gaze."; } if(message==228) { St[0]="eye control buttons:"; St[1]="changes increment size"; St[2]="used in the other"; St[3]="eye control buttons:"; St[4]="this button gives"; St[5]="large increments"; } if(message==229) { St[0]="eye control buttons:"; St[1]="changes increment size"; St[2]="used in the other"; St[3]="eye control buttons:"; St[4]="this button gives"; St[5]="medium increments"; } if(message==230) { St[0]="eye control buttons:"; St[1]="changes increment size"; St[2]="used in the other"; St[3]="eye control buttons:"; St[4]="this button gives"; St[5]="small increments"; } if(message==100) { St[0]="number entry console"; } if(message==200) { St[0]="strip manipulator console:"; St[1]="using the arrows or the"; St[2]="number entry console you"; St[3]="can specify the 6 bend lines"; St[4]="and bend angles for the strip"; } if(message==300) { St[0]="strip coloring console:"; St[1]="using the buttons here you"; St[2]="can recolor the strips, the"; St[3]="checkerboard, or the"; St[4]="viewer background"; } if(message==600) { St[0]="strip evolver:"; St[1]="the goal of this applet"; St[2]="is to move the strips so"; St[3]="that the tips meet with no"; St[4]="bending or twisting."; } if(message==601) { St[0]="bend annealing button:"; St[1]="clicking on this button"; St[2]="causes the computer to"; St[3]="search for improved"; St[4]="configurations by making"; St[5]="some small alterations"; St[6]="to the relevant individual"; St[7]="bend, i.e. annealing it."; } if(message==602) { St[0]="automatic annealing:"; St[1]="clicking on this button"; St[2]="causes the computer to"; St[3]="do the annealing to all"; St[4]="12 bends in sequence."; } if(message==603) { St[0]="semi-automatic annealing:"; St[1]="clicking on this button"; St[2]="causes the computer to"; St[3]="do the annealing to the 6"; St[4]="bends of one strip."; } if(message==604) { St[0]="semi-automatic annealing:"; St[1]="clicking on this button"; St[2]="causes the computer to"; St[3]="do the annealing to the 6"; St[4]="bends of one strip."; } if(message==605) { St[0]="annealing step selector:"; St[1]="click/drag on this scale"; St[2]="to choose the step size for"; St[3]="the perturbations in the"; St[4]="bending angles done during"; St[5]="the annealing process."; St[6]="the left buttons set small"; St[7]="and the right ones set large"; } if(message==606) { St[0]="annealing step selector:"; St[1]="click/drag on this scale"; St[2]="to choose the step size for"; St[3]="the perturbations in the"; St[4]="crease lines done during"; St[5]="the annealing process."; St[6]="the left buttons set small"; St[7]="and the right ones set large"; } if(message==607) { St[0]="twist toggle:"; St[1]="sets the goal so that the"; St[2]="two strips meet at the"; St[3]="tips with 0 degree twist"; } if(message==608) { St[0]="twist toggle:"; St[1]="sets the goal so that the"; St[2]="two strips meet at the"; St[3]="tips with 180 degree twist"; } if(message==609) { St[0]="objective function modifier:"; St[1]="The objective function is a"; St[2]="positive linear combo of the"; St[3]="distance between the strip"; St[4]="tops, the relative twisting "; St[5]="the strips, and the relative"; St[6]="bending of the strips. Click"; St[7]="in the triangle to set weights."; } if(message==610) { St[0]="strip mismatch scales:"; St[1]="the scale on the botton"; St[2]="measures the bending error"; St[3]="the scale in the middle"; St[4]="measures the twisting error"; St[5]="the scale on the top"; St[6]="measures the distance"; } if(message==500) { St[0]="3D viewer:"; St[1]="shows the strips in 3D."; St[2]="strip segments which "; St[3]="intersect the checkerboard"; St[4]="are only plotted in outline"; St[5]="So, bend upwards at first!"; } if(message==39) { St[0]="paintbrush:"; St[1]="this large rectangle"; St[2]="displays the selected"; St[3]="color."; } if(message==40) { St[0]="red-green-blue scales:"; St[1]="click/drag on these scales"; St[2]="to change the color of the"; St[3]="paintbrush."; } if(message==49) { St[0]="local strip color buttons:"; St[1]="click on one of these"; St[2]="buttons to color a segment "; St[3]="of the relevant strip."; } if(message==45) { St[0]="global strip color buttons:"; St[1]="click on this button"; St[2]="to recolor the whole strip."; } if(message==141) { St[0]="checkerboard coloring:"; St[1]="click here to recolor the"; St[2]="lines on the checkerboard"; } if(message==142) { St[0]="checkerboard coloring:"; St[1]="click here to recolor half"; St[2]="the squares on the"; St[3]="checkerboard."; } if(message==143) { St[0]="checkerboard coloring:"; St[1]="click here to recolor half"; St[2]="the squares on the"; St[3]="checkerboard."; } if(message==144) { St[0]="background coloring:"; St[1]="click here to recolor"; St[2]="the background on the"; St[3]="viewport."; } if(message==400) { St[0]="3D viewing console:"; St[1]="using the buttons here you"; St[2]="can change the perspective"; St[3]="of the 3D plot."; } if(message==30) { St[0]="The eye: Virtually speaking,"; St[1]="an observer hovers around"; St[2]="the strips on a hemisphere."; St[3]="By clicking on the eye you "; St[4]="change the location of the"; St[5]="observer on the hemisphere."; St[6]="If your computer is fast you.";; St[7]="can also drag the mouse."; } if(message==23) { St[0]="undo button:"; St[1]="undoes the previous strip"; St[2]="modification. This button"; St[3]="is not compatible with the"; St[4]="simulated annealing"; St[5]="console on the east panel"; } if(message==21) { St[0]="save button:"; St[1]="If this button is yellow"; St[2]="you can save a strip"; St[3]="configuration by clicking"; St[4]="on a magenta button in the"; St[5]="memory console. Clicking"; St[6]="on a yellow memory button"; St[7]="overwrites it."; } if(message==22) { St[0]="recall button:"; St[1]="If this button is yellow"; St[2]="you can recall a strip"; St[3]="configuration by clicking"; St[4]="on a yellow button in the"; St[5]="memory console."; } if(message==24) { St[0]="reset button:"; St[1]="resets all the angles to 180"; St[2]="and returns the bend lines"; St[3]="to their initial configuration"; } if(message==18) { St[0]="bend selector disks:"; St[1]="clicking here selects"; St[2]="a bend for you to modify"; St[3]="when the bend is selected"; St[4]="the button turns white"; St[5]="and the number display"; St[6]="show the data associated"; St[7]="to the bend."; } if(message==19) { St[0]="length selector disk:"; St[1]="clicking here selects"; St[2]="the option of modifying"; St[3]="the length of the strip"; St[4]="the disk is white when"; St[5]="the option is on."; } if((history==1)&&(number==1)) { for(int i=0;i<=7;++i) { g.drawString(St[i],10,15+18*i); }} } /*mouse events*/ public void mousePressed(MouseEvent e) { if(M.V.state==0) { M.V.s1=M.V.s1.adapt(M.S1.C,1,M.S1.length); M.V.s2=M.V.s2.adapt(M.S2.C,2,M.S2.length); M.REPAINT(); M.V.state=1; } } public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseDragged(MouseEvent e) { e.consume(); Point P=new Point(); P.x=e.getX(); P.y=e.getY(); /*dragging interface*/ if(NUM[1][1].inside(P)==1) { double tt=(P.x-NUM[1][1].x1)/NUM[1][1].x2; top1=(int)(105.0*tt-2); if(top1>95) top1=95; if(top1<0) top1=0; NUM[1][2].x1=NUM[1][1].x1+96*tt-2; if(NUM[1][2].x1>NUM[1][1].x1+93) NUM[1][2].x1=NUM[1][1].x1+93; } if(NUM[1][3].inside(P)==1) { double tt=(P.x-NUM[1][3].x1)/NUM[1][3].x2; top2=1.1*tt-.1; if(top2>.995) top2=.995; if(top2<0) top2=0; NUM[1][4].x1=NUM[1][3].x1+96*tt-2; if(NUM[1][4].x1>NUM[1][3].x1+93) NUM[1][4].x1=NUM[1][3].x1+93; } if(NUM[2][1].inside(P)==1) { double tt=(P.x-NUM[2][1].x1)/NUM[2][1].x2; a1=(int)(365.0*tt-3); if(a1>359) a1=359; if(a1<0) a1=0; NUM[2][2].x1=NUM[2][1].x1+96*tt-2; if(NUM[2][2].x1>NUM[2][1].x1+93) NUM[2][2].x1=NUM[2][1].x1+93; } if(NUM[2][3].inside(P)==1) { double tt=(P.x-NUM[2][3].x1)/NUM[2][3].x2; a2=1.1*tt-.1; if(a2>.995) a2=.995; if(a2<0) a2=0; NUM[2][4].x1=NUM[2][3].x1+96*tt-2; if(NUM[2][4].x1>NUM[2][3].x1+93) NUM[2][4].x1=NUM[2][3].x1+93; } if(NUM[3][1].inside(P)==1) { double tt=(P.x-NUM[3][1].x1)/NUM[3][1].x2; bot1=(int)(105.0*tt-2); if(bot1>95) bot1=95; if(bot1<0) bot1=0; NUM[3][2].x1=NUM[3][1].x1+96*tt-2; if(NUM[3][2].x1>NUM[3][1].x1+93) NUM[3][2].x1=NUM[3][1].x1+93; } if(NUM[3][3].inside(P)==1) { double tt=(P.x-NUM[3][3].x1)/NUM[3][3].x2; bot2=1.1*tt-.1; if(bot2>.995) bot2=.995; if(bot2<0) bot2=0; NUM[3][4].x1=NUM[3][3].x1+96*tt-2; if(NUM[3][4].x1>NUM[3][3].x1+93) NUM[3][4].x1=NUM[3][3].x1+93; } repaint(); } public void mouseMoved(MouseEvent e) { e.consume(); Point P=new Point(); P.x=e.getX(); P.y=e.getY(); if(P.x>720) M.S1.message=0; if((P.x>530)&&(P.x<720)) M.S1.message=100; if(P.x<530) M.S1.message=200; if(NUM[1][0].inside(P)==1) M.S1.message=8; if(NUM[2][0].inside(P)==1) M.S1.message=9; if(NUM[3][0].inside(P)==1) M.S1.message=10; if(NUM[1][1].inside(P)==1) M.S1.message=2; if(NUM[1][3].inside(P)==1) M.S1.message=2; if(NUM[2][1].inside(P)==1) M.S1.message=3; if(NUM[2][3].inside(P)==1) M.S1.message=3; if(NUM[3][1].inside(P)==1) M.S1.message=4; if(NUM[3][3].inside(P)==1) M.S1.message=4; for(int i=1;i<=3;++i) { for(int j=5;j<=8;++j) { if(NUM[i][j].inside(P)==1) M.S1.message=6; } } for(int i=1;i<=20;++i) { if(MEM[i].inside(P)==1) M.S1.message=1; } if(MEM[24].inside(P)==1) M.S1.message=24; if(MEM[21].inside(P)==1) M.S1.message=21; if(MEM[22].inside(P)==1) M.S1.message=22; if(MEM[23].inside(P)==1) M.S1.message=23; for(int i=1;i<=4;++i) { for(int j=1;j<=5;++j) { if(T[i][j].inside(P)==1) M.S1.message=17; }} for(int i=1;i<=2;++i) { for(int j=1;j<=5;++j) { if(S[i][j].inside(P)==1) M.S1.message=17; }} for(int i=1;i<=6;++i) { if(C[i].inside(P)==1) M.S1.message=18; } if(C[7].inside(P)==1) M.S1.message=19; M.S1.repaint(); } public void mouseClicked(MouseEvent e) { e.consume(); Point P=new Point(); P.x=e.getX(); P.y=e.getY(); int respond=0; /*numerical entry system*/ if(NUM[1][1].inside(P)==1) { double tt=(P.x-NUM[1][1].x1)/NUM[1][1].x2; top1=(int)(105.0*tt-2); if(top1>95) top1=95; if(top1<0) top1=0; NUM[1][2].x1=NUM[1][1].x1+96*tt-2; if(NUM[1][2].x1>NUM[1][1].x1+93) NUM[1][2].x1=NUM[1][1].x1+93; } if(NUM[1][3].inside(P)==1) { double tt=(P.x-NUM[1][3].x1)/NUM[1][3].x2; top2=1.1*tt-.1; if(top2>.995) top2=.995; if(top2<0) top2=0; NUM[1][4].x1=NUM[1][3].x1+96*tt-2; if(NUM[1][4].x1>NUM[1][3].x1+93) NUM[1][4].x1=NUM[1][3].x1+93; } if(NUM[2][1].inside(P)==1) { double tt=(P.x-NUM[2][1].x1)/NUM[2][1].x2; a1=(int)(365.0*tt-3); if(a1>359) a1=359; if(a1<0) a1=0; NUM[2][2].x1=NUM[2][1].x1+96*tt-2; if(NUM[2][2].x1>NUM[2][1].x1+93) NUM[2][2].x1=NUM[2][1].x1+93; } if(NUM[2][3].inside(P)==1) { double tt=(P.x-NUM[2][3].x1)/NUM[2][3].x2; a2=1.1*tt-.1; if(a2>.995) a2=.995; if(a2<0) a2=0; NUM[2][4].x1=NUM[2][3].x1+96*tt-2; if(NUM[2][4].x1>NUM[2][3].x1+93) NUM[2][4].x1=NUM[2][3].x1+93; } if(NUM[3][1].inside(P)==1) { double tt=(P.x-NUM[3][1].x1)/NUM[3][1].x2; bot1=(int)(105.0*tt-2); if(bot1>95) bot1=95; if(bot1<0) bot1=0; NUM[3][2].x1=NUM[3][1].x1+96*tt-2; if(NUM[3][2].x1>NUM[3][1].x1+93) NUM[3][2].x1=NUM[3][1].x1+93; } if(NUM[3][3].inside(P)==1) { double tt=(P.x-NUM[3][3].x1)/NUM[3][3].x2; bot2=1.1*tt-.1; if(bot2>.995) bot2=.995; if(bot2<0) bot2=0; NUM[3][4].x1=NUM[3][3].x1+96*tt-2; if(NUM[3][4].x1>NUM[3][3].x1+93) NUM[3][4].x1=NUM[3][3].x1+93; } if((top1<95)&&(NUM[1][5].inside(P)==1)) { top1=top1+1; NUM[1][2].x1=NUM[1][2].x1+.96; if(top1==95) NUM[1][2].x1=NUM[1][1].x1+93; } if((top1>0)&&(NUM[1][6].inside(P)==1)) { top1=top1-1; NUM[1][2].x1=NUM[1][2].x1-.96; } if((top2<.985)&&(NUM[1][7].inside(P)==1)) { top2=top2+.01; NUM[1][4].x1=NUM[1][4].x1+.96; } if((top2>.011)&&(NUM[1][8].inside(P)==1)) { top2=top2-.01; NUM[1][4].x1=NUM[1][4].x1-.96; if(top2<.01) NUM[1][4].x1=NUM[1][3].x1; } if((a1<358.5)&&(NUM[2][5].inside(P)==1)) { a1=a1+1; NUM[2][2].x1=NUM[2][2].x1+.24; if(a1==359) NUM[2][2].x1=NUM[2][1].x1+93; if(a1<.1) NUM[2][6].x1=NUM[2][5].x1; } if((a1>0.5)&&(NUM[2][6].inside(P)==1)) { a1=(int)(a1-1); NUM[2][2].x1=NUM[2][2].x1-.24; if(NUM[2][2].x1.011)&&(NUM[2][8].inside(P)==1)) { a2=a2-.01; NUM[2][4].x1=NUM[2][4].x1-.96; if(a2<.01) NUM[2][4].x1=NUM[2][3].x1; } if((bot1<95)&&(NUM[3][5].inside(P)==1)) { bot1=bot1+1; NUM[3][2].x1=NUM[3][2].x1+.96; if(bot1==95) NUM[3][2].x1=NUM[3][1].x1+93; } if((bot1>0)&&(NUM[3][6].inside(P)==1)) { bot1=bot1-1; NUM[3][2].x1=NUM[3][2].x1-.96; } if((bot2<.985)&&(NUM[3][7].inside(P)==1)) { bot2=bot2+.01; NUM[3][4].x1=NUM[3][4].x1+.96; } if((bot2>.011)&&(NUM[3][8].inside(P)==1)) { bot2=bot2-.01; NUM[3][4].x1=NUM[3][4].x1-.96; if(bot2<.01) NUM[3][4].x1=NUM[3][3].x1; } /*transferring*/ if(NUM[1][0].inside(P)==1) { double dd=5.0*(top1+top1); respond=1; C[bend].top=dd; if(bend==7) length=dd; } if(NUM[2][0].inside(P)==1) {respond=1;C[bend].a=a1+a2;} if(NUM[3][0].inside(P)==1) { double dd=5.0*(bot1+bot1); respond=1; C[bend].top=dd; if(bend==7) length=dd; } if(MEM[24].inside(P)==1) { for(int i=0;i<=5;++i) { C[i+1].a=180; C[i+1].top=length/4+60*i; C[i+1].bot=length/4+60*i; respond=1; } } int test=0; for(int i=1;i<=7;++i) { if(C[i].inside(P)==1) test=i; } if(test>0) { bend=test; for(int i=1;i<=7;++i) C[i].s=0; C[test].s=1; } int i2=0; int j2=0; for(int i=1;i<=4;++i) { for(int j=1;j<=5;++j) { if(T[i][j].inside(P)==1) {i2=i;j2=j;} } } if(bend<=6) { if(i2==1) { if(j2==1) C[bend].top=C[bend].top+.1; if(j2==2) C[bend].top=C[bend].top+1.0; if(j2==3) C[bend].top=C[bend].top+10.0; if(j2==4) C[bend].top=C[bend].top+100.0; } if(i2==2) { if(j2==1) C[bend].top=C[bend].top-.1; if(j2==2) C[bend].top=C[bend].top-1.0; if(j2==3) C[bend].top=C[bend].top-10.0; if(j2==4) C[bend].top=C[bend].top-100.0; } if(i2==3) { if(j2==1) C[bend].bot=C[bend].bot+.1; if(j2==2) C[bend].bot=C[bend].bot+1.0; if(j2==3) C[bend].bot=C[bend].bot+10.0; if(j2==4) C[bend].bot=C[bend].bot+100.0; } if(i2==4) { if(j2==1) C[bend].bot=C[bend].bot-.1; if(j2==2) C[bend].bot=C[bend].bot-1.0; if(j2==3) C[bend].bot=C[bend].bot-10.0; if(j2==4) C[bend].bot=C[bend].bot-100.0; }} if(bend==7) { if((i2==1)||(i2==3)) { if(j2==1) length=length+.10; if(j2==2) length=length+1.0; if(j2==3) length=length+10.0; if(j2==4) length=length+100.0; } if((i2==2)||(i2==4)) { if(j2==1) length=length-.1; if(j2==2) length=length-1.0; if(j2==3) length=length-10.0; if(j2==4) length=length-100.0; } } int i3=0; int j3=0; for(int i=1;i<=2;++i) { for(int j=1;j<=5;++j) { if(S[i][j].inside(P)==1) {i3=i;j3=j;} }} if(bend<=6) { if(i3==1) { if(j3==5) C[bend].a=C[bend].a+30; if(j3==4) C[bend].a=C[bend].a+10; if(j3==3) C[bend].a=C[bend].a+1; if(j3==2) C[bend].a=C[bend].a+.1; if(j3==1) C[bend].a=C[bend].a+.01; } if(i3==2) { if(j3==5) C[bend].a=C[bend].a-30; if(j3==4) C[bend].a=C[bend].a-10; if(j3==3) C[bend].a=C[bend].a-1; if(j3==2) C[bend].a=C[bend].a-.1; if(j3==1) C[bend].a=C[bend].a-.01; } } /*toggle test window*/ if(i2+j2+i3+j3>0) respond=1; Point PP=new Point(); PP.x=P.x-720; PP.y=P.y; if((number==2)&&(TUT1.inside(PP)==1)) { TUT1.C=Color.white; M.S1.history=1; TUT2.C=new Color(50,50,255); } if((number==2)&&(TUT2.inside(PP)==1)) { TUT2.C=Color.white; M.S1.history=2; TUT1.C=new Color(50,50,255); } /*memory*/ for(int j=1;j<=20;++j) { if((MEM[j].inside(P)==1)&&(mem==1)) { MEM[j].C=Color.yellow; for(int i=1;i<=7;++i) { CC[j][i].top=C[i].top; CC[j][i].bot=C[i].bot; CC[j][i].a=C[i].a; } } } for(int j=1;j<=20;++j) { if((MEM[j].inside(P)==1)&&(mem==2)) { for(int i=1;i<=7;++i) { C[i].top=CC[j][i].top; C[i].bot=CC[j][i].bot; C[i].a=CC[j][i].a; respond=1; } } } if(MEM[21].inside(P)==1) { mem=1; MEM[21].C=Color.yellow; MEM[22].C=new Color(50,50,255); respond=1; } if(MEM[22].inside(P)==1) { mem=2; MEM[22].C=Color.yellow; MEM[21].C=new Color(50,50,255); respond=1; } if(MEM[23].inside(P)==1) { if(undo>0) { respond=-1; int q=RECORD[undo].s; C[q].top=RECORD[undo].top; C[q].bot=RECORD[undo].bot; C[q].a=RECORD[undo].a; } } /*boundary conditions*/ if(length>960) length=960; if(lengthC[bend+1].top) C[bend].top=C[bend+1].top-.0001; if(C[bend].bot>C[bend+1].bot) C[bend].bot=C[bend+1].bot-.0001; if(C[bend].top0)&&(A2>0)&&(A3>0)) val=1; return(val); } void render(Graphics g) { g.setColor(Color.black); Polygon P=new Polygon(); int x[]={(int)(this.x1),(int)(this.x2),(int)(this.x3)}; int y[]={(int)(this.y1),(int)(this.y2),(int)(this.y3)}; P.xpoints=x; P.ypoints=y; P.npoints=3; g.fillPolygon(P); g.setColor(new Color(100,100,255)); g.drawPolygon(P); } } /*This is the class for the square buttons*/ class ListenSquare { double x1,x2; double y1,y2; Color C; int number; int hot; ListenSquare(double x1,double y1,double x2,double y2) { this.x1=x1; this.x2=x2; this.y1=y1; this.y2=y2; number=0; hot=0; } void translate(double x,double y) { x1=x1+x; y1=y1+y; } int inside(Point p) { int val; val=1; if(p.x<=this.x1) val=0; if(p.x>this.x1+this.x2) val=0; if(p.y<=this.y1) val=0; if(p.y>this.y1+this.y2) val=0; return(val); } void render(Graphics g) { int xx1,yy1,xx2,yy2; xx1=(int)(this.x1); yy1=(int)(this.y1); xx2=(int)(int)(this.x2); yy2=(int)(int)(this.y2); g.setColor(this.C); g.fillRect(xx1,yy1,xx2,yy2); g.setColor(Color.black); g.fillRect(xx1+3,yy1+3,xx2-5,yy2-5); g.drawRect(xx1,yy1,xx2,yy2); if(hot==1) { g.setColor(Color.white); if(number==0) g.drawString("0",6+xx1,15+yy1); if(number==1) g.drawString("1",6+xx1,15+yy1); if(number==2) g.drawString("2",6+xx1,15+yy1); if(number==3) g.drawString("3",6+xx1,15+yy1); if(number==4) g.drawString("4",6+xx1,15+yy1); if(number==5) g.drawString("5",6+xx1,15+yy1); if(number==6) g.drawString("6",6+xx1,15+yy1); if(number==7) g.drawString("7",6+xx1,15+yy1); if(number==8) g.drawString("8",6+xx1,15+yy1); if(number==9) g.drawString("9",6+xx1,15+yy1); } } void solidRender(Graphics g) { int xx1,yy1,xx2,yy2; xx1=(int)(this.x1); yy1=(int)(this.y1); xx2=(int)(int)(this.x2); yy2=(int)(int)(this.y2); g.setColor(this.C); g.fillRect(xx1,yy1,xx2,yy2); } } /*bending data class*/ class Bend { double x1,x2; double y1,y2; double a; double top,bot; Color C; int s; Bend() { this.x1=x1; this.x2=x2; this.y1=y1; this.y2=y2; this.top=top; this.bot=bot; this.a=a; this.s=s; } int inside(Point p) { int val; val=1; if(p.x<=this.x1) val=0; if(p.x>this.x1+this.x2) val=0; if(p.y<=this.y1) val=0; if(p.y>this.y1+this.y2) val=0; return(val); } void render(Graphics g) { int xx1,yy1,xx2,yy2; xx1=(int)(this.x1); yy1=(int)(this.y1); xx2=(int)(this.x2); yy2=(int)(this.y2); g.setColor(new Color(180,0,180)); if(s==1) g.setColor(Color.white); g.fillOval(xx1,yy1,xx2,yy2); g.setColor(Color.magenta); g.fillArc(xx1-1,yy1-1,xx2+2,yy2+2,0,(int)(a)); g.setColor(Color.black); g.drawOval(xx1-1,yy1-1,xx2+2,yy2+2); g.setColor(Color.black); g.translate(30,0); g.drawLine((int)(top/2.0),64,(int)(bot/2.0),87); g.translate(-30,0); if(s==1) { g.setColor(Color.black); g.translate(30,0); g.drawLine((int)(top/2.0-1),64,(int)(bot/2.0-1),87); g.drawLine((int)(top/2.0+1),64,(int)(bot/2.0+1),87); g.translate(-30,0); } } void specialRender(Graphics g) { int xx1,yy1,xx2,yy2; xx1=(int)(this.x1); yy1=(int)(this.y1); xx2=(int)(this.x2); yy2=(int)(this.y2); g.setColor(Color.magenta); if(s==1) g.setColor(Color.white); g.fillOval(xx1,yy1,xx2,yy2); g.setColor(Color.black); g.drawOval(xx1,yy1,xx2,yy2); } } class DoubleDisplay { ListenSquare[] NUM=new ListenSquare[16]; int i1,i2; double x,y; Color C; DoubleDisplay(double x,double y,int i1,int i2) { this.x=x; this.y=y; this.i1=i1; this.i2=i2; for(int i=1;i<=i1+i2;++i) { NUM[i]=new ListenSquare(0,0,0,0); NUM[i].x1=x+20*i-20; NUM[i].y1=y; NUM[i].x2=20; NUM[i].y2=20; NUM[i].C=Color.black; } } void toDisplay(double v) { double d1=0; double h=1; double dd=v; for(int k=1;k<=i1+i2;++k) { h=Math.pow(10.0,k-i1); d1=Math.floor(dd*h); dd=dd-d1/h; NUM[k].hot=1; NUM[k].number=(int)(d1); } } void render(Graphics g) { for(int i=1;i<=i1+i2;++i) NUM[i].render(g); g.setColor(C); g.drawRect((int)(x),(int)(y),(i1+i2)*20,20); g.drawRect((int)(x+1),(int)(y+1),(i1+i2)*20-2,20-2); g.setColor(Color.white); g.fillRect((int)(x+i1*20-2),(int)(y+14),3,3); } } /********************************* Now for the 3D stuff... **********************************/ class ViewCanvas extends DBCanvas implements MouseListener { Manager M; Eye E; Strip s1,s2; int[] B=new int[15]; int[][] AA=new int[15][15]; Face F[]=new Face[15]; int state; Checkerboard H; ViewCanvas addManager(Manager MM) { ViewCanvas X=this; X.M=MM; return(X); } ViewCanvas() { state=0; addMouseListener(this); /*initialize the eye*/ E=new Eye(); E.p=new Vector(-2.4000, -5.333, 8.1114459); E.v=new Vector(0.240, 0.53333, -0.8111445); E.w=new Vector(0.3328, 0.7397, 0.58484); E.dist=4.0; /*the strips*/ s1=new Strip(1); s2=new Strip(2); /*the checkerboard*/ Vector V2=new Vector(12,12,0); H=new Checkerboard(V2); H.C[0]=Color.black; H.C[1]=new Color(120,0,120); H.C[2]=new Color(80,0,80); H.C[3]=new Color(0,0,0); } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); /*draw the background*/ g.setColor(H.C[3]); g.fillRect(0,0,640,400); /*draw the checkerboard*/ Polyhedron Q=H.toPolyhedron(); E.render(g,Q,H.C[0],H.state); /*compute the facet hiding*/ int test=0; makeFaces(M.C.LL); tableau(); getList(); /*draw the strips*/ stripRender(g); /*draw the window frame*/ g.setColor(Color.black); g.drawRect(0,0,539,349); g.drawRect(1,1,537,347); } /******************************** facet hiding ********************************/ /*tests whether one face blocks another*/ int hidden(Face F1,Face F2,int m,int n) { int test=0; int doop=(m-n)*(m-n); if(doop>1) test=hidden1(F1,F2,m,n); if(n==m+1) test=hidden1(F1,F2,m,n); if(m==n+1) test=-hidden(F2,F1,n,m); if((m==1)&&(n==8)) test=0; if((m==8)&&(n==1)) test=0; if(m==n) test=0; return(test); } int hidden1(Face F1,Face F2,int m,int n) { int fin=0; Vector[] W=new Vector[10]; for(int i=1;i<=9;++i) W[i]=new Vector(); if(n==m+1) { W[1]=W[1].add(F1.V[3],F1.V[4]); W[2]=W[1].add(F1.V[1],F1.V[2]); W[3]=W[1].scale(.5); W[4]=W[2].scale(.5); double TOLERANCE=.000001; W[5]=W[1].add(W[3].scale(1-TOLERANCE),W[4].scale(TOLERANCE)); fin=-E.block(F2,W[5],m,n,0); if(fin==0) { W[1]=W[1].add(F2.V[1],F2.V[2]); W[2]=W[1].add(F2.V[3],F2.V[4]); W[3]=W[1].scale(.5); W[4]=W[2].scale(.5); W[5]=W[1].add(W[3].scale(1-TOLERANCE),W[4].scale(TOLERANCE)); fin=E.block(F1,W[5],m,n,0); } } if((m-n)*(m-n)>1) { if(E.intersect(F1,F2)==0) { fin=0; int test1=E.insideVertex(F1,F2); int test2=E.insideVertex(F2,F1); if((test1==0)&&(test2==0)) fin=0; if(test1!=0) fin=-E.block(F2,F1.V[test1],m,n,0); if(test2!=0) fin=E.block(F1,F2.V[test2],m,n,0); } if(E.intersect(F1,F2)==1) { int test1=E.insideVertex(F1,F2); if(test1>0) { fin=-E.block(F2,F1.V[test1],m,n,0); if(fin==0) fin=1; } if(test1==0) { int test2=E.insideVertex(F2,F1); if(test2>0) { fin=E.block(F1,F2.V[test2],m,n,0); if(fin==0) fin=-1; } if(test2==0) { Vector W1=E.viewIntersect(F1,F2,m,n); fin=-E.block(F2,W1,m,n,1); if(fin==0) fin=1; } } } } return(fin); } /*compute blocking for all pairs*/ void tableau() { for(int i=1;i<=14;++i) { for(int j=1+1;j<=14;++j) { AA[i][j]=hidden(F[i],F[j],i,j); AA[j][i]=-AA[i][j]; } } } /* extract a plotting order from the blocking pair data*/ int blocked(int i) { int fail=0; for(int j=1;j<=14;++j) { if((AA[i][j]==1)&&(F[j].state==0)) fail=1; } return(fail); } void nextRender(Manager M,int k) { int test=1; int fail; for(int i=1;i<=14;++i) { fail=blocked(i); if((fail==0)&&F[i].state==0) test=i; } F[test].state=1; B[k]=test; } void getList() { for(int i=1;i<=14;++i) { nextRender(M,i); } } /*convert the strips into the faces to be plotted*/ void makeFaces(ListenSquare[][] LL) { Polyhedron Q1=s1.toPolyhedron(); Polyhedron Q2=s2.toPolyhedron(); for(int i=1;i<=14;++i) { if((i<=7)&&(E.Front(Q1.F[i])==1)) F[i]=new Face(Q1.F[i].V,4,LL[1][i].C); if((i<=7)&&(E.Front(Q1.F[i])!=1)) F[i]=new Face(Q1.F[i].V,4,LL[2][i].C); if((i>=8)&&(E.Front(Q2.F[i-7])==1)) F[i]=new Face(Q2.F[i].V,4,LL[3][i-7].C); if((i>=8)&&(E.Front(Q2.F[i-7])!=1)) F[i]=new Face(Q2.F[i].V,4,LL[4][i-7].C); F[i].state=0; } } /* virtual version of the makeFaces routine*/ ViewCanvas makeFaces(Strip t1,Strip t2) { ViewCanvas V=new ViewCanvas(); Polyhedron Q1=t1.toPolyhedron(); Polyhedron Q2=t2.toPolyhedron(); for(int i=1;i<=14;++i) { if(i<=7) V.F[i]=new Face(Q1.F[i].V,4,Color.black); if(i>=8) V.F[i]=new Face(Q2.F[i-7].V,4,Color.black); } return(V); } /*rendering*/ void stripRender(Graphics g) { int i=0; for(int ii=1;ii<=14;++ii) { i=B[ii]; if(F[i].negative()==0) { E.render(g,F[i]); } E.borderRender(g,F[i],new Color(0,0,0)); } } /*compute objective functions*/ double tipDistance(Face[] G) { Vector W1=new Vector(); Vector W2=new Vector(); W1=W1.add(G[7].V[3].scale(.5),G[7].V[4].scale(.5)); W2=W2.add(G[14].V[3].scale(.5),G[14].V[4].scale(.5)); double d=W2.dist(W1,W2); return(d); } double tipTwist(Face[] G) { Vector W1=new Vector(); Vector W2=new Vector(); W1=W1.add(G[7].V[3],G[7].V[4].scale(-1)); W2=W2.add(G[14].V[3],G[14].V[4].scale(-1)); double d=W1.angle(W1,W2); d=180*d/Math.PI; if(d<0) d=-d; return(d); } double tipBend(Face[] G) { Vector W1=new Vector(); Vector W2=new Vector(); W1=W1.add(G[7].V[1],G[7].V[4].scale(-1)); W2=W2.add(G[14].V[1],G[14].V[4].scale(-1)); double d=W1.angle(W1,W2); d=180*d/Math.PI; if(d<0) d=-d; return(180-d); } Vector tipGoal(Face[] G) { double d1=tipDistance(G); double d2=tipTwist(G); double d3=tipBend(G); Vector X=new Vector(4.0*d1,d2,d3); return(X); } /*virtual version of objective function.*/ Vector tipGoal(Strip t1,Strip t2,int tog) { ViewCanvas V=makeFaces(t1,t2); Vector X=V.tipGoal(V.F); if(tog==2) X.y=-180.0-X.y; return(X); } /* mouse events*/ public void mousePressed(MouseEvent e) { if(state==0) { s1=s1.adapt(M.S1.C,1,M.S1.length); s2=s2.adapt(M.S2.C,2,M.S2.length); M.REPAINT(); state=1; } } public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) { M.S1.message=500; M.S1.repaint(); } public void mouseExited(MouseEvent e) {} public void mouseClicked(MouseEvent e) { } } class Eye { Vector p,v,w; double dist; Eye(Vector p,Vector v,Vector w) { this.p=p; //position in space this.v=v; //looking direction this.w=w; //head tilt direction this.dist=dist; //distance from object } Eye() { this.p=new Vector(); this.v=new Vector(); this.w=new Vector(); this.dist=8.0; } Eye orthogonal() { Eye F=new Eye(); F.p=p; F.v=p.scale(-1.0/p.norm()); Vector w1=new Vector(0,0,1); F.w=w1.ortho(F.v); F.dist=dist; return(F); } Eye gaze1(double t) { Eye F=new Eye(); F.p=p; Vector vv=new Vector(v.x,v.y,v.z); Vector ww=new Vector(w.x,w.y,w.z); Vector xx=vv.cross(vv,ww); double cc=Math.cos(t); double ss=Math.sin(t); F.v=vv.add(vv.scale(cc), ww.scale(ss)); F.w=ww.add(vv.scale(-ss),ww.scale(cc)); F.dist=dist; return(F); } Eye gaze2(double t) { Eye F=new Eye(); F.p=p; Vector vv=new Vector(v.x,v.y,v.z); Vector ww=new Vector(w.x,w.y,w.z); Vector xx=vv.cross(vv,ww); double cc=Math.cos(t); double ss=Math.sin(t); F.v=vv.add(vv.scale(cc), xx.scale(ss)); F.w=w; F.dist=dist; return(F); } /*decides if the front or back of the face is seen. This is a computation of the orientation of the projection.*/ int Front(Face F) { Vector W[]=new Vector[20]; for(int i=1;i<=19;++i) W[i]=new Vector(0,0,0); W[1]=see(F.V[1]); W[2]=see(F.V[2]); W[3]=see(F.V[3]); double d1=W[1].x-W[2].x; double d2=W[1].y-W[2].y; double d3=W[1].x-W[3].x; double d4=W[1].y-W[3].y; double d5=d1*d4-d2*d3; int test=0; if(d5<0) test=-1; if(d5>=0) test=1; return(test); } /*decides if a face blocks a point in space. Another orientation computation.*/ int block(Face F,Vector V,int m,int n,int s) { Vector W[]=new Vector[10]; for(int i=1;i<=9;++i) W[i]=new Vector(); W[1]=W[1].add(F.V[2],F.V[1].scale(-1)); W[2]=W[1].add(F.V[3],F.V[1].scale(-1)); W[3]=W[1].add(V,F.V[1].scale(-1)); W[4]=W[1].add(p.scale(dist),F.V[1].scale(-1)); double d1=W[1].dot(W[4],W[1].cross(W[2],W[1])); double d2=W[1].dot(W[3],W[1].cross(W[2],W[1])); double d3=d1*d2; int test=0; if((d3<0)&&(inside(V,F)==1)) test=1; if((d3<0)&&(s==1)) test=1; return(test); } int inside(Vector V,Face F) { int d1=orientation(V,F.V[1],F.V[2]); int d2=orientation(V,F.V[2],F.V[3]); int d3=orientation(V,F.V[3],F.V[4]); int d4=orientation(V,F.V[4],F.V[1]); int d5=d1+d2+d3+d4; int d6=d5*d5; int test=0; if(d6==16) test=1; return(test); } /*this is the main routine. It is projection onto the plane normal to the looking direction of the the*/ Vector see(Vector X) { double t; Vector A=new Vector(); Vector pp=p.scale(dist); t=1-p.dot(v,v)/(p.dot(v,X)-p.dot(pp,v)); if((t>0)&&(t<1)) { Vector Y=new Vector(); Y=p.add(pp.scale(t),X.scale(1-t)); Vector Z=p.add(Y,p.add(pp,v.scale(-1))); Vector ww=p.cross(v,w); double a=p.dot(Z,w); double b=p.dot(Z,ww); A.x=b; A.y=-a; A.z=1; } if((t>=1)||(t<=0)) {A=A.make(0,0,-1);} return(A); } int orientation(Vector V1,Vector V2,Vector V3) { Vector v1=see(V1); Vector v2=see(V2); Vector v3=see(V3); double x1=v1.x-v3.x; double y1=v1.y-v3.y; double x2=v2.x-v3.x; double y2=v2.y-v3.y; int test=1; if(x1*y2-x2*y1<0) test=-1; return(test); } /*Facet hiding routines*/ int insideVertex(Face F1,Face F2) { int test=0; for(int i=1;i<=4;++i) { if(inside(F1.V[i],F2)==1) test=i; } return(test); } Vector findIntersect(Vector V1,Vector V2,Vector W1,Vector W2) { Vector v1=see(V1); Vector v2=see(V2); Vector w1=see(W1); Vector w2=see(W2); Vector z2=new Vector(); double d1=w1.dist(v1,w1); double d2=w1.dist(v1,w2); double d3=w1.dist(v2,w1); double d4=w1.dist(v2,w2); double d5=w1.dist(v1,w1); double d6=w1.dist(v2,w2); double d7=.000001; if((d1=d7)&&(d2>=d7)&&(d3>=d7)&&(d4>=d7)&&(d5>=d7)&&(d6>=d7)) { Vector x1=w1.cross(v1,v2); Vector y1=w1.cross(w1,w2); Vector z1=w1.cross(x1,y1); z2=z1; if(z1.z*z1.z>.0000000001) z2=z1.normalize(); } return(z2); } Vector findIntersect(Face F1,Face F2,int i,int j) { int ii=i+1; if(ii>4) ii=1; int jj=j+1; if(jj>4) jj=1; Vector V1=F1.V[i]; Vector V2=F1.V[ii]; Vector W1=F2.V[j]; Vector W2=F2.V[jj]; Vector X=findIntersect(V1,V2,W1,W2); return(X); } int intersect(Face F1,Face F2,int i,int j) { int ii=i+1; if(ii>4) ii=1; int jj=j+1; if(jj>4) jj=1; int test; Vector V1=F1.V[i]; Vector V2=F1.V[ii]; Vector W1=F2.V[j]; Vector W2=F2.V[jj]; Vector v1=see(V1); Vector v2=see(V2); Vector w1=see(W1); Vector w2=see(W2); Vector X=findIntersect(V1,V2,W1,W2); test=1; double d1=V1.dist(v1,X); double d2=V1.dist(v2,X); double d3=V1.dist(v1,v2); double e1=V1.dist(w1,X); double e2=V1.dist(w2,X); double e3=V1.dist(w1,w2); double TOLERANCE=.000000001; if((d3=TOLERANCE)&&(d2>=TOLERANCE)) { W[1]=V1; W[2]=V2; W[3]=W[1].add(W[2],W[1].scale(-1)); W[4]=W[3].unit(); W[5]=W[1].add(A,W[1].scale(-1)); W[6]=W[4].cross(W[4],W[5]); W[6]=W[6].unit(); W[7]=W[6].cross(W[4],W[6]); double x4=W[4].dot(W[4],W[5]); double x6=W[6].dot(W[6],W[5]); double x7=W[7].dot(W[7],W[5]); double tt=Math.PI*t/180; W[8]=W[6].scale(Math.cos(tt)); W[9]=W[7].scale(Math.sin(tt)); W[10]=W[10].add(W[8],W[9]); W[11]=W[6].scale(-Math.sin(tt)); W[12]=W[7].scale( Math.cos(tt)); W[13]=W[10].add(W[11],W[12]); W[14]=W[4].scale(x4); W[15]=W[10].scale(x6); W[16]=W[13].scale(x7); W[17]=W[1].add(W[1].add(W[14],W[15]),W[16]); W[18]=W[1].add(W[1],W[17]); } return(W[18]); } } class ControlCanvas extends DBCanvas implements MouseListener, MouseMotionListener { Manager M; ListenSquare L[]=new ListenSquare[50]; ListenSquare LL[][]=new ListenSquare[10][10]; double step,gaze1,gaze2; int red,green,blue; ControlCanvas addManager(Manager MM) { ControlCanvas X=this; X.M=MM; return(X); } ControlCanvas() { addMouseListener(this); addMouseMotionListener(this); step=.04; gaze1=0; gaze2=0; /*strips*/ for(int i=0;i<=1;++i) { for(int j=0;j<=6;++j) { LL[4-i][j+1]=new ListenSquare(5+16*j,245+15*i,15,15); LL[1+i][j+1]=new ListenSquare(5+16*j,345+15*i,15,15); }} /*initialize strip coloring*/ for(int j=1;j<=7;++j) { LL[1][j].C=Color.yellow; LL[2][j].C=new Color(255,100,0); LL[3][j].C=new Color(0,200,255); LL[4][j].C=new Color(0,100,200); } /* view panel colorings*/ L[1]=new ListenSquare(145,245,15,30); L[1].C=Color.white; L[2]=new ListenSquare(160,245,15,15); L[2].C=Color.white; L[3]=new ListenSquare(160,260,15,15); L[3].C=Color.white; L[4]=new ListenSquare(145,345,30,30); L[4].C=Color.white; /*coloring homogenizers*/ L[5]=new ListenSquare(125,345,15,15); L[5].C=Color.white; L[6]=new ListenSquare(125,360,15,15); L[6].C=Color.white; L[8]=new ListenSquare(125,245,15,15); L[8].C=Color.white; L[7]=new ListenSquare(125,260,15,15); L[7].C=Color.white; /*colorwheel*/ LL[5][1]=new ListenSquare(4,250,150,20); LL[5][1].C=new Color(255,0,0); LL[5][2]=new ListenSquare(4,270,150,20); LL[5][2].C=new Color(0,255,0); LL[5][3]=new ListenSquare(4,290,150,20); LL[5][3].C=new Color(50,50,255); LL[6][1]=new ListenSquare(4,252,4,16); LL[6][1].C=Color.white; LL[6][2]=new ListenSquare(4,272,4,16); LL[6][2].C=Color.white; LL[6][3]=new ListenSquare(4,292,4,16); LL[6][3].C=Color.white; LL[0][0]=new ListenSquare(158,280,18,60); LL[0][0].C=Color.black; red=0; green=0; blue=0; /*eye controls*/ /*fine motion*/ L[20]=new ListenSquare(145,182,15,15); L[20].C=Color.magenta; L[26]=new ListenSquare(3,150,14,4); L[26].C=Color.white; L[25]=new ListenSquare(3,115,15,90); L[25].C=Color.magenta; L[27]=new ListenSquare(160,182,15,15); L[27].C=Color.magenta; L[28]=new ListenSquare(25,178,65,15); L[28].C=Color.magenta; L[29]=new ListenSquare(60,180,4,11); L[29].C=Color.white; L[30]=new ListenSquare(75,178,15,15); L[30].C=new Color(100,100,255); /*change the gaze*/ L[31]=new ListenSquare(124,184,10,10); L[31].C=Color.red; L[32]=new ListenSquare(104,184,10,10); L[32].C=Color.red; L[33]=new ListenSquare(114,174,10,10); L[33].C=Color.red; L[34]=new ListenSquare(114,194,10,10); L[34].C=Color.red; /*controls*/ LL[0][0].translate(0,-30); for(int i=1;i<=8;++i) L[i].translate(0,-30); for(int i=1;i<=4;++i) { for(int j=1;j<=7;++j) { LL[i][j].translate(0,-30); }} } public void paint(Graphics g) { g.setColor(Color.black); g.fillRect(2,0,176,350); g.setColor(new Color(50,50,255)); g.drawRect(1,210,179,219); /* the eye*/ g.setColor(Color.white); g.drawString("zoom",20,206); g.drawString("speed",52,172); g.drawString("rotate",143,175); g.drawString("gaze",105,168); g.translate(15,5); for(int i=0;i<=5;++i) { g.setColor(new Color(0,0,200)); g.fillArc(0,0,150,150,60*i,30); } for(int i=0;i<=5;++i) { g.setColor(new Color(0,0,255)); g.fillArc(0,0,150,150,30+60*i,30); } g.setColor(Color.red); g.fillOval((int)(72-5000.0*gaze2),(int)(71+1+5000.0*gaze1),6,6); g.setColor(Color.white); int x=(int)(7.5*(-M.V.E.p.x+10.0)); int y=(int)(7.5*(-M.V.E.p.y+10.0)); double xx=0; double yy=0; g.fillRect(y-2,x-7,4,4); for(int i=0;i<=11;++i) { double d=2*Math.PI*i/12; xx=75.0+74.0*Math.cos(d); yy=75.0+74.0*Math.sin(d); //g.drawLine(y,x,(int)(xx),(int)(yy)); } g.translate(-15,-5); /*controls*/ LL[0][0].solidRender(g); for(int i=8;i>=1;--i) L[i].render(g); L[20].render(g); for(int i=25;i<=29;++i) L[i].render(g); for(int i=31;i<=34;++i) L[i].render(g); for(int i=1;i<=4;++i) { for(int j=1;j<=7;++j) { LL[i][j].render(g); }} /*colorwheel*/ for(int i=5;i<=6;++i) { for(int j=1;j<=3;++j) { LL[i][j].render(g); }} g.setColor(Color.white); g.fillRect(165,235,6,6); } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseMoved(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); if(p.y>210) M.S1.message=300; if(p.y<=210) M.S1.message=400; double tt=(p.x-75)*(p.x-75)+(p.y-75)*(p.y-75); if((tt<75*75)&&(tt>1)) { M.S1.message=30; } if(LL[0][0].inside(p)==1) M.S1.message=39; for(int i=1;i<=3;++i) { if(LL[5][i].inside(p)==1) M.S1.message=40; } for(int i=5;i<=8;++i) { if(L[i].inside(p)==1) M.S1.message=45; } for(int i=1;i<=4;++i) { if(L[i].inside(p)==1) M.S1.message=140+i; } for(int i=1;i<=4;++i) { if(L[30+i].inside(p)==1) M.S1.message=131; } if(L[20].inside(p)==1) M.S1.message=220; for(int i=5;i<=10;++i) { if(L[20+i].inside(p)==1) M.S1.message=220+i; } for(int i=1;i<=4;++i) { for(int j=1;j<=7;++j) { if(LL[i][j].inside(p)==1) M.S1.message=49; }} M.S1.repaint(); } public void mousePressed(MouseEvent e) { if(M.V.state==0) { M.V.s1=M.V.s1.adapt(M.S1.C,1,M.S1.length); M.V.s2=M.V.s2.adapt(M.S2.C,2,M.S2.length); M.REPAINT(); M.V.state=1; } } public void mouseDragged(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); int x=p.x-15; int y=p.y-5; /*speed*/ if(L[28].inside(p)==1) { double ss=(p.x-L[28].x1)/L[28].x2; step=.5*ss; L[29].x1=L[28].x1+L[28].x2*ss-2; } /*zoom*/ if(L[25].inside(p)==1) { double dd=(p.y-L[25].y1)/L[25].y2; M.V.E.dist=12*dd+1; L[26].y1=L[25].y1+90*dd-2; M.V.repaint(); } /*hemisphere of eye motion*/ double tt=(x-75)*(x-75)+(y-75)*(y-75); if((tt<75*75)&&(tt>1)) { M.V.E.p.x=-y/7.5+10; M.V.E.p.y=-x/7.5+10; M.V.E.p.z=Math.sqrt(100-M.V.E.p.x*M.V.E.p.x-M.V.E.p.y*M.V.E.p.y); M.V.E=M.V.E.orthogonal(); gaze1=0; gaze2=0; M.V.repaint(); } //colorwheel if(LL[5][1].inside(p)==1) { int re=(int)(255.0*(p.x-LL[5][1].x1)/(LL[5][1].x2)); if(re<0) re=0; if(re>255) re=255; red=re; LL[6][1].x1=4+148.0*re/255.0; LL[0][0].C=new Color(red,green,blue); } if(LL[5][2].inside(p)==1) { int gre=(int)(255.0*(p.x-LL[5][1].x1)/(LL[5][1].x2)); if(gre<0) gre=0; if(gre>255) gre=255; green=gre; LL[6][2].x1=4+148.0*gre/255.0; LL[0][0].C=new Color(red,green,blue); } if(LL[5][3].inside(p)==1) { int blu=(int)(255.0*(p.x-LL[5][1].x1)/(LL[5][1].x2)); if(blu<0) blu=0; if(blu>255) blu=255; blue=blu; LL[6][3].x1=4+148.0*blu/255.0; LL[0][0].C=new Color(red,green,blue); } repaint(); } public void mouseClicked(MouseEvent e) { e.consume(); Point p=new Point(); p.x=e.getX(); p.y=e.getY(); int x=p.x-15; int y=p.y; /*hemisphere of eye motion*/ double tt=(x-75)*(x-75)+(y-75)*(y-75); if((tt<75*75)&&(tt>1)) { M.V.E.p.x=-y/7.5+10; M.V.E.p.y=-x/7.5+10; M.V.E.p.z=Math.sqrt(100-M.V.E.p.x*M.V.E.p.x-M.V.E.p.y*M.V.E.p.y); M.V.E=M.V.E.orthogonal(); gaze1=0; gaze2=0; } /*fine eye motion*/ if(L[32].inside(p)==1) {M.V.E=M.V.E.gaze2(.002*step); gaze2=gaze2+.002*step; } if(L[31].inside(p)==1) {M.V.E=M.V.E.gaze2(-.002*step); gaze2=gaze2-.002*step; } if(L[34].inside(p)==1) {M.V.E=M.V.E.gaze1(.002*step); gaze1=gaze1+.002*step; } if(L[33].inside(p)==1) {M.V.E=M.V.E.gaze1(-.002*step); gaze1=gaze1-.002*step; } /* circumnavigation */ if(L[20].inside(p)==1) { M.V.E.p=M.V.E.p.cylinderRotate(step/5.0); M.V.E.v=M.V.E.v.cylinderRotate(step/5.0); M.V.E.w=M.V.E.w.cylinderRotate(step/5.0); } if(L[27].inside(p)==1) { M.V.E.p=M.V.E.p.cylinderRotate(-step/5.0); M.V.E.v=M.V.E.v.cylinderRotate(-step/5.0); M.V.E.w=M.V.E.w.cylinderRotate(-step/5.0); } if(L[25].inside(p)==1) { double dd=(p.y-L[25].y1)/L[25].y2; M.V.E.dist=12*dd+1; L[26].y1=L[25].y1+95*dd-2; } /*speed*/ if(L[28].inside(p)==1) { double ss=(p.x-L[28].x1)/L[28].x2; step=.5*ss; L[29].x1=L[28].x1+L[28].x2*ss-2; } /*recolor viewer*/ if(L[1].inside(p)==1) { M.V.H.C[0]=LL[0][0].C; } if(L[2].inside(p)==1) { M.V.H.C[1]=LL[0][0].C; } if(L[3].inside(p)==1) { M.V.H.C[2]=LL[0][0].C; } if(L[4].inside(p)==1) { M.V.H.C[3]=LL[0][0].C; } if(L[5].inside(p)==1) { for(int j=1;j<=7;++j) { LL[1][j].C=LL[0][0].C; }} if(L[6].inside(p)==1) { for(int j=1;j<=7;++j) { LL[2][j].C=LL[0][0].C; }} if(L[7].inside(p)==1) { for(int j=1;j<=7;++j) { LL[3][j].C=LL[0][0].C; }} if(L[8].inside(p)==1) { for(int j=1;j<=7;++j) { LL[4][j].C=LL[0][0].C; }} for(int i=1;i<=4;++i) { for(int j=1;j<=7;++j) { if(LL[i][j].inside(p)==1) LL[i][j].C=LL[0][0].C; }} //colorwheel if(LL[5][1].inside(p)==1) { int re=(int)(255.0*(p.x-LL[5][1].x1)/(LL[5][1].x2)); if(re<0) re=0; if(re>255) re=255; red=re; LL[6][1].x1=4+148.0*re/255.0; LL[0][0].C=new Color(red,green,blue); } if(LL[5][2].inside(p)==1) { int gre=(int)(255.0*(p.x-LL[5][1].x1)/(LL[5][1].x2)); if(gre<0) gre=0; if(gre>255) gre=255; green=gre; LL[6][2].x1=4+148.0*gre/255.0; LL[0][0].C=new Color(red,green,blue); } if(LL[5][3].inside(p)==1) { int blu=(int)(255.0*(p.x-LL[5][1].x1)/(LL[5][1].x2)); if(blu<0) blu=0; if(blu>255) blu=255; blue=blu; LL[6][3].x1=4+148.0*blu/255.0; LL[0][0].C=new Color(red,green,blue); } /*boundary conditions*/ if(M.V.E.dist<1.0) M.V.E.dist=1.0; if(M.V.H.state==3) M.V.H.state=0; M.V.s1=M.V.s1.adapt(M.S1.C,1,M.S1.length); M.V.s2=M.V.s2.adapt(M.S2.C,2,M.S2.length); M.REPAINT(); repaint(); } } class Checkerboard { Vector v,w; int state; Color[] C=new Color[5]; Checkerboard(Vector v) { this.v=v; //center state=1; this.C=C; } Polyhedron toPolyhedron() { Vector[][][] V=new Vector[16][16][16]; double d1=1; double d2=1; double d3=1; double d4=1; Face F[]=new Face[100]; int test=0; for(int i=0;i<=7;++i) { for(int j=0;j<=7;++j) { d1=v.x*(i-4); d2=v.x*(j-4); d3=d1+v.x; d4=d2+v.y; V[i][j][1]=v.make(d1,d2,v.z); V[i][j][2]=v.make(d1,d4,v.z); V[i][j][3]=v.make(d3,d4,v.z); V[i][j][4]=v.make(d3,d2,v.z); Color CC=new Color(0,0,0); CC=C[1]; test=(i+j); test=test=test-2*(test/2); if(test==0) CC=C[2]; F[8*i+j+1]=new Face(V[i][j],4,CC); } } Polyhedron P=new Polyhedron(F,64); return(P); } }