// Modification history // May 31,1997 fixed bug when object located at focus point // May 22,1997 add paraxial ray option for mirror // Feb 21,1997 major modification, almost rewritten the whole code // try without frame => very slow for netscape // Nov. 3, 1996 impletemt double buffering //----------------------------------------------------- // written by Fu-Kwun Hwang // I hope that you enjoy this applet // Suggestions? E-mail to hwang@phy03.phy.ntnu.edu.tw //----------------------------------------------------- import java.awt.*; public class thinLens extends java.applet.Applet{ String buttonText="start"; String windowTitle="Thin Lens demonstration by Fu-Kwun Hwang(1996)"; int windowWidth = 600; int windowHeight = 350; LensWindow m; int windowCount=0; Color bgColor=new Color(0xC8,0xDF,0xD0); String rts,STR[]={"Reset","p","q","f","m","lens","mirror","Paraxial"}; public void init() { setBackground(bgColor); for(int i=0;ilxc || lh0;j++,i=lxc-(int)(j*scale)) g.drawLine(i,lyc-2,i,lyc+2); for(i=lxc,j=0;ixc){ ox=lxc-xc; side=1; }else{ ox=xc-lxc; side=-1; } oy=lyc-yc; if(ox==lf){// located at focus point normal=false; textQ.setText("Inf"); }else { normal=true; ix=1./(1./lf-1./ox); writeText(textQ,ix); } magnify=-ix/ox; // write P,Q,F writeText(textP,Math.abs(lxc-xc)); writeText(textF,Math.abs(lf)); textM.setText(d2String(magnify)); int x1,y1,x2,y2; // ray paths x1=lxc-side*ox; y1=lyc-oy; if(normal)iy=magnify*oy; else{// May 31,1997 double mag2=-100.*magnify/Math.abs(magnify); iy=-mag2*oy; ix=mag2*ox; } y2=lyc-(int)iy; //draw object g.setColor(Color.blue); drawit(g,x1,lyc,oy); if(lh>Math.abs(iy))inrange=true; else inrange=false; if(is_lens){// lens x2=lxc+side*(int)ix; g.drawLine(x1,y1,lxc,y1); //1-1 平行入射光 if(magnify<0){ g.drawLine(lxc,y1,x2,y2); //1-2 g.drawLine(x1,y1,x2,y2); //2 穿過透鏡中心 if(inrange){ g.drawLine(x1,y1,lxc,y2); //3-1 穿過焦點入射光 g.drawLine(lxc,y2,x2,y2); //3-2 平行主軸 } g.setColor(Color.blue); }else{ if(lf>0){ // converging lens g.drawLine(lxc,y1,lxc+2*side*(int)lf,lyc+oy); //1-2 g.drawLine(x1,y1,lxc-side*(int)ix,lyc+(int)iy); //2-1 if(inrange) { g.drawLine(x1,y1,lxc,lyc-(int)iy); //3-1 g.drawLine(lxc,y2,lxc+2*side*(int)lf,y2); //3-2 } g.setColor(Color.green); g.drawLine(x1,y1,x2,y2); //2-2 g.drawLine(lxc,y1,x2,y2); //1-3 if(inrange) g.drawLine(lxc,y2,x2,y2); //3-3 }else{ // diverging lens g.drawLine(lxc,y1,lxc-2*side*(int)lf,lyc-3*oy); //1-2 g.drawLine(x1,y1,lxc+side*ox,lyc+(int)oy); //2 if(inrange){ g.drawLine(x1,y1,lxc,y2); //3-1 g.drawLine(lxc,y2,lxc-2*side*(int)lf,y2); //3-2 } g.setColor(Color.green); g.drawLine(lxc,y1,lxc+side*(int)lf,lyc); //1-3 if(inrange) g.drawLine(lxc,y2,lxc+side*(int)ix,y2); //3-3 } } }else{// mirror double angle=Math.asin(oy/lr); double dw=0.,dw2; int xx,xx2,yy; x2=lxc-(int)ix; if(!thinMirror)dw=lr*(1.-Math.cos(angle)); xx=lxc-(int)dw; angle*=2.; if(lf>0){// concave mirror 凹面鏡 boolean within; g.drawLine(x1,y1,lxc,lyc); //2-1 物 通過 鏡面中心 yy=lyc-(int)(lr*oy/(lr-ox)); double mm=iy/(-ix+lr),xt=0.; if(!thinMirror) xt=lr*(1./Math.sqrt(1.+mm*mm)-1.); if( (within=(Math.abs(mm*(xt+lr))0)side=1;else side=-1; if(oy*iy>0){//虛像 if(!thinMirror)g.drawLine(x1,y1,lxc-(int)lr,lyc);//4-2 垂直入射 else g.drawLine(lxc-(int)(2.*lf),lyc,lxc,yy=lyc-(int)(iy*2.*lf/(2.*lf-ix))); g.drawLine(lxc,lyc,lxc-2*ox,lyc+2*oy);//2-2 鏡心反射 g.setColor(Color.green); g.drawLine(lxc,lyc,x2,y2);//2-3 g.drawLine(lxc+(int)xt,yy,x2,y2);//2-1 g.setColor(Color.blue); g.drawLine(x1,y1,xx,y1);//1-1 平行入射光 if(!thinMirror)g.drawLine(xx,y1,lxc-(int)lr,lyc-oy+(int)(Math.tan(angle)*(lr-dw)));//1-2 g.setColor(Color.green); if(!thinMirror){ g.drawLine(xx,y1,lxc-(int)ix,lyc-oy-(int)(Math.tan(angle)*(-ix+dw)));//1-3 g.setColor(Color.yellow); g.drawLine(lxc-(int)lf,lyc,x2,y2); }else{ g.drawLine(lxc,y1,x2,y2); g.drawLine(lxc,yy,x2,y2); g.setColor(Color.blue); g.drawLine(lxc,y1,lxc-(int)lf,lyc); } }else{//實像 g.drawLine(lxc,lyc,x2,y2);//2-2 鏡面中心--像 if(within&&!thinMirror)g.drawLine(x1,y1,x2,y2);//4-2 g.drawLine(x1,y1,xx,y1);//1-1 平行入射光 if(!thinMirror){ g.drawLine(xx,y1,lxc-(int)ix,lyc-oy+side*(int)(Math.abs(Math.tan(angle))*(ix-dw)));//1-2 g.setColor(Color.yellow); } g.drawLine(xx,y1,lxc,yy=lyc+(int)(lf*iy/(ix-lf))); g.drawLine(x2,y2,lxc,yy); if(inrange){ g.drawLine(x1,y1,lxc,yy=lyc+(int)(lf*oy/(ox-lf)));//3-1 g.drawLine(x2,y2,lxc,yy);//3-2 } } if(!thinMirror){ g.setColor(Color.white); g.drawLine(lxc-(int)lr,lyc,xx,y1); } }else{// convex mirror dw2=lr*(1.-Math.cos(Math.asin(oy/(lr+ox)))); yy=lyc+(int)((2*lf+dw2/2.)*oy/(ox-2.*lf)); g.drawLine(x1,y1,xx=lxc+(int)dw2,yy);//2垂直射向鏡面 g.drawLine(x1,y1,lxc,lyc);//3 通過鏡面中心 g.drawLine(lxc-2*ox,lyc+2*oy,lxc,lyc);//3-1 g.setColor(Color.green); if(!thinMirror)g.drawLine(lxc+(int)dw2,yy,lxc+(int)lr,lyc);//2-1 else g.drawLine(xx,yy,lxc-(int)(2*lf),lyc); g.drawLine(lxc,lyc,x2,y2);//3-2 g.setColor(Color.blue); g.drawLine(x1,y1,xx=lxc+(int)(dw),y1);//1-1 平行入射光 if(!thinMirror)g.drawLine(lxc+(int)(dw+lf),y1+(int)(lf*Math.tan(angle)),xx,y1); else g.drawLine(lxc,(int)y1,lxc+(int)(2*lf),y1-2*oy); if(!thinMirror){ g.setColor(Color.white); g.drawLine(lxc+(int)(2*dw-lr),2*y1-lyc,lxc-(int)(2*lf),lyc);//通過焦點 } g.setColor(Color.green); if(!thinMirror){ g.drawLine(xx,y1,lxc+(int)(dw-lf),y1-(int)(lf*Math.tan(angle))); g.setColor(Color.yellow); } g.drawLine(lxc,y1,lxc-(int)lf,lyc); } } if(oy*iy>0)g.setColor(Color.green); else g.setColor(Color.darkGray); drawit(g,x2,lyc,(int)iy); // draw image } String d2String(double d){ float d2=(float)((int)(100.*d)/100.); String str=String.valueOf(d2); if(str.indexOf(".")==-1)str+=".0"; return str; } private void drawit(Graphics g,int x,int y,int height){ // for object and image int x1,y1,width=2,sign=1; x1=x-width/2; if(height<0){ sign=-1; y1=y; }else y1=y-height; g.fillRect(x1,y1,width,sign*height); y1=y-height; width=2*width; sign*=2; // draw hats g.drawLine(x,y1,x+width,y1+sign*width); g.drawLine(x,y1,x-width,y1+sign*width); } int lxc,lyc,lh; // (xc,yc):center position, h:height of lens double lr,lf; // focusLength*2; int lwidth; // half/quater width of lens public void linit(int x, int y,int hi,double fi){ lxc=x; lyc=y; lr=Math.abs(2.*fi); lf=fi; if(hi<10)lh=10; // minimum height of lens else if(hi>lr) lh=(int)lr-10; else lh=hi; // if(!is_lens && lf<0)type.setLabel("-"); // else type.setLabel("+"); } boolean moving=false; boolean sizing=false; boolean lmouseDown(int x,int y){ if(Math.abs(x-lxc+ww)lxc && (x-lxc)0)if(sizing)g.drawOval(lxc-lwidth,lyc-lh,2*lwidth,2*lh); else g.fillOval(lxc-lwidth,lyc-lh,2*lwidth,2*lh); else{ double x0,y0; double c=Math.PI-angle,dc; int ncnt=100;//(int)(lr*c/15.)+1; int ncnt2=2*ncnt; x0=lxc+lwidth/2+lr; y0=lyc; if(ncnt>cnt){ X=new int[ncnt2]; Y=new int[ncnt2]; cnt=ncnt; } //g.drawString(String.valueOf(ncnt),100,100); ncnt2-=1; dc=2.*angle/(ncnt-1); if(is_lens){ for(int i=0;i0){// concave mirror ww=lwidth; x0=lxc-lr+1; for(int i=0;i0.)ww=lwidth;// draw ray path in lens approximately //else ww=-lwidth; ww=lwidth; g.drawLine(lxc-side*ww*3/4,lyc-oy,lxc+side*ww,lyc+(int)(oy*(ww-lf)/lf)); g.drawLine(lxc-side*ww,lyc-(int)(iy*(-ww+lf)/lf),lxc+side*ww*3/4,lyc-(int)(iy)); } ww=0;// for lens } } }