         //    Programma   Lente
 import java.applet.*;
 import java.awt.*; 
public class Lente extends Applet implements Runnable{
  Thread anim;
  int index;
  int x0,y0,y01s,y01,y02,xi,yi,yis,yi1,y,ys;
  int xf1,yf,xf2,r,r0,r01;
  int xl,yl1,yl2;
  int xrif,yrif,yrif1;
  int Xm,Ym,i,j,k,j1;
  int xa,xb,xc,xd,ya,yb,yc,yd;
  int xctn,yctn,h,l;
  int yinc1,yinc2,yincj;
  int xfrc,xfrc1,yfrc,yfrc1,yfrc2,yfrc3;
  Button b,c,d,ca,tasto;
  boolean got,gv,toi,olm,ctn,co_im,ani;
  Image im,img,imgsc,img1;
  Graphics gr;
  Color cim,scher;
  String str,ist;
  Label lb,lb1,lb11,lb2,lb3;
  public void init(){
    im=createImage(size().width,size().height);
    System.out.println("im size = "+im.getWidth(this)+" "+im.getHeight(this));
    gr=im.getGraphics();
    xl=200;yl1=40;yl2=240;
    x0=100;y0=100;y01=140;y01s=180;
    y02=y0+10;yi1=y01;
    yf=140;xf1=140;xf2=260;r=4;r0=500;r01=150;
    xrif=600;
    xa=310;ya=50;xb=400;yb=20;xc=xb;yc=258;xd=xa;yd=228;
    Ym=y0;
    xctn=175;yctn=40;l=5;h=100;
    xfrc=160;xfrc1=290;
    got=false;toi=false;olm=false;gv=false;
    ctn=false;co_im=false;ani=false;
    imgsc=getImage(getCodeBase(),"lentesc.gif");
    img1=getImage(getCodeBase(),"lente.gif");
    cim=new Color(0,0,255);
    scher=new Color(230,220,220);
    index=0;
    str=getParameter("co_im");
    if ("TRUE".equals(str)) co_im = true;
    str=getParameter("got");
    if ("TRUE".equals(str)) got = true;
    setLayout(null);
    tasto=new Button("COSTRUZIONE IMMAGINE");
    add(tasto);
    d=new Button("AVVIO");
    add(d);
    if(!got)if(!co_im)d.reshape(10,10,50,20);
    ca=new Button("CARTONCINO");
    add(ca);
    c=new Button("INDIETRO");
    add(c);
    b=new Button("ASSENZA LENTE");
    add(b); 
    if(co_im)b.reshape(10,10,110,20);
    lb=new Label("Cliccando il tasto");
    add(lb);
    lb1=new Label("AVVIO si pone davanti all'oggetto un cartoncino");
    add(lb1);
    lb2=new Label("luminosa, perchč formata da un minor numero di raggi.");
    add(lb2);
    if(!got & !co_im){
      lb.setBackground(Color.white);    
      lb.reshape(10,240,150,20);
      lb1.setBackground(Color.white);   
      lb1.reshape(10,260,340,20);
    } 
    if(got){
      lb=new Label("Cliccando con il mouse un punto qualsiasi dell'oggetto, rappresentato dalla freccia in blu,");
      add(lb);
      lb1=new Label("viene disegnato il cono di raggi da esso emesso ed il corrispondente punto immagine.");
      add(lb1);
      lb2=new Label("Cliccando il tasto COSTRUZIONE IMMAGINE si puņ osservare la costruzione completa");
      add(lb2);
      lb3=new Label("dell'immagine fatta in sequenza.");
      add(lb3);
      lb.setBackground(Color.white);     
      lb.reshape(5,255,520,20);
      lb1.setBackground(Color.white);   
      lb1.reshape(5,275,520,20);
    }
    if(co_im){
      lb=new Label("Cliccando il tasto");
      add(lb);
      lb1=new Label("ASSENZA LENTE si elimina la lente");
      add(lb1);
      lb11=new Label("punto dell'oggetto, come si puņ osservare cliccando su di esso con il mouse.");
      add(lb11);
      lb.setBackground(Color.white);    
      lb.reshape(10,240,200,20);
      lb1.setBackground(Color.white);   
      lb1.reshape(10,260,360,20);
    }
   while(img1==null || imgsc==null)try{ 
    System.out.println("Loading images");
Thread.sleep(1000);
}
catch(InterruptedException e){}
img=img1;
  }
  public boolean action(Event e, Object arg){
    if("COSTRUZIONE IMMAGINE".equals(arg)){
      lb.setText("");
      lb1.setText("");
      ani=true;
      c.reshape(175,10,80,20);
      c.show();
      repaint();
    }
    if("AVVIO".equals(arg)){
       cim=new Color(80,145,255);     

      lb1.setText("CARTONCINO si osservano i raggi che formano l'immagine");
      lb1.show();
      lb1.setBackground(Color.white);   
      lb1.reshape(10,260,340,20);
      d.hide();
      img=imgsc;
      ca.show();
      c.show();
      ca.reshape(10,10,90,20);
      c.reshape(105,10,80,20);
      olm=true;
      repaint();
    }
    if("CARTONCINO".equals(arg)){
       lb.show();
       lb.setText("L'immagine che si forma");
       lb.setBackground(Color.white);   
       lb.reshape(10,240,150,20);
       lb1.setText("ha la stessa dimensione di quella iniziale, ma č meno");
       lb2.show();
       lb2.setBackground(Color.white);   
       lb2.reshape(10,280,340,20);
       //cim=new Color(80,145,255);     
       ctn=true;
       repaint();
    }
    if("ASSENZA LENTE".equals(arg)){
       x0=100;
       lb.reshape(10,240,250,20);
       lb.setText("In assenza della lente non si forma alcuna");
       lb1.reshape(10,260,470,20);
       lb1.setText("immagine perchč i raggi non convergono in nessun punto. Questo per ogni");
       lb11.setBackground(Color.white);   
       lb11.reshape(10,280,460,20);
       lb11.show();
       c.show(); 
       scher=new Color(230,225,225);     
       c.reshape(125,10,80,20);
       toi=true;
       repaint();
    }
    if("INDIETRO".equals(arg)){
     if(got){
       lb.setText("Cliccando con il mouse un punto qualsiasi dell'oggetto, rappresentato dalla freccia in blu,");
       lb1.setText("viene disegnato il cono di raggi da esso emesso ed il corrispondente punto immagine.");
       lb2.setText("");
       lb3.setText("");
       tasto.hide();
       gv=true;
       ani=false;
     }
     if(!got &!co_im){
       lb.setText("Cliccando il tasto");
       lb1.setText("AVVIO si pone davanti all'oggetto un cartoncino");
       lb.setBackground(Color.white);   
       lb.reshape(10,240,150,20);
       lb1.setBackground(Color.white);   
       lb1.reshape(10,260,340,20);
     }
     if(co_im){
     x0=100;y0=100;
     yi=((y01-y0)*(xl-xf1)/(xf1-x0))+y01;
     Ym=y0;
       lb1.reshape(10,260,200,20);
       lb.setText("Cliccando il tasto");
       lb1.setText("ASSENZA LENTE si elimina la lente");
       lb11.hide();
     }
     lb2.hide();
     d.show();
     img=img1;
     cim=new Color(0,0,255);
     scher=new Color(230,220,220);
     ctn=false;
     toi=false;
     olm=false;
     ca.hide();
     c.hide();
     repaint();
   }
   return true;
  }
  public void start(){
    anim=new Thread(this);
    anim.start();
  }
  public void stop(){
    anim.stop();
  }
  public void run(){
   while(true){
   try{ Thread.sleep(500);}
   catch(InterruptedException e){}
   repaint();
   }
  }
  public void paint(Graphics g){
    System.out.println(gr);
    gr.clearRect(0,0,size().width,size().height);
    setBackground(Color.white);
    gr.setColor(scher);
    int Xsc[]={xa,xb,xc,xd};
    int Ysc[]={ya,yb,yc,yd};
    int est=Xsc.length;
    Polygon polysc=new Polygon(Xsc,Ysc,est);
    gr.fillPolygon(polysc);
    if(toi){
      Xm=x0;
      double teta;
      for(i=0;i<=360;i=i+10){
         teta=i*(Math.PI/180.);
          double teta1=6.05;
          if(Ym>=129)teta1=5;
         if(teta>=0&teta<=0.48||teta>teta1){
           xi=xl+(xl-Xm)*(xl-xf1)/(xf1-Xm);
           ys=(int)((xi-Xm)*Math.tan(teta));
           gr.setColor(Color.gray);
           gr.drawLine(Xm,Ym,xi,Ym+ys);     
         }
         else{
         gr.setColor(Color.gray);
         gr.drawLine(Xm,Ym,Xm+(int)(r0*Math.cos(teta)),
                     Ym+(int)(r0*Math.sin(teta)));
         }
         int xr01=Xm+(int)(r01*Math.cos(teta));
         int yr01=Ym+(int)(r01*Math.sin(teta));
            int k=(int)(i*0.1);
         if(teta>=0&teta<=1.22){
            gr.drawLine(xr01-5+k,yr01-5-(k-1),xr01,yr01);
            gr.drawLine(xr01-5-(k-1),yr01+5-k,xr01,yr01);
         }
         if(teta>1.22&teta<=1.57){
            gr.drawLine(xr01-5+k,yr01-9,xr01,yr01);
            gr.drawLine(xr01-8,yr01-k,xr01,yr01);
         }
         if(teta>1.57&teta<3){
            gr.drawLine(xr01+5+(k-9),yr01-7,xr01,yr01);
            gr.drawLine(xr01-5,yr01-7-(k-10),xr01,yr01);
         }
         if(teta>5.55&teta<6.28){
            gr.drawLine(xr01-5,yr01+10-(k-32),xr01,yr01);
            gr.drawLine(xr01-8,yr01-(k-32),xr01,yr01);
         }
      }
    }
    gr.setColor(Color.blue);
    if(co_im)y01s=y01+10;
    if(got)y01s=y01+10;
    int X[]={x0-1,x0-1,x0-4,x0,x0+4,x0+1,x0+1};
    int Y[]={y01s-10,y02,y02,y0,y02,y02,y01s-10};
    int punti=X.length;
    Polygon poli=new Polygon(X,Y,punti);
    gr.fillPolygon(poli);
    gr.setColor(Color.black);
    drawDashedLine(gr,0,140,500,140,5.,4.);//asse perp.lente
    if(!toi){ 
       int iw=img.getWidth(this);
       int ih=img.getHeight(this);
       gr.drawImage(img,185,28,iw/4,ih,this);
       gr.setColor(Color.black);
       drawDashedLine(gr,xl,yl1,xl,yl2,5.,4.);//asse perp.lente
       xi=xl+(xl-x0)*(xl-xf1)/(xf1-x0);
       drawDashedLine(gr,0,140,500,140,5.,4.);//asse perp.lente
       if(!got){
         gr.setColor(Color.white);
         drawDashedLine(gr,xi,y01,xc,y01,5.,4.);//asse perp.lente
       }
       gr.setColor(Color.red);
       gr.fillOval(xf1,yf-2,r,r);
       Font f=new Font("TimeRoman",Font.PLAIN,14);
       gr.setFont(f);
       gr.drawString("F",xf1,yf+15);
       gr.fillOval(xf2,yf-2,r,r);
       gr.drawString("F",xf2,yf+15);
       if(co_im){
              xf1=140;xf2=260;
              yi=((y01-Ym)*(xl-xf1)/(xf1-x0))+y01;
              gr.setColor(cim);
              yis=(y01-(y01s-10-y01)*(xi-xf2)/(xf2-xl));
              int Xtt[]={xi-1,xi-1,xi-4,xi,xi+4,xi+1,xi+1};
              int Ytt[]={yis,yi-10,yi-10,yi,yi-10,yi-10,yis};
              int puntt=Xtt.length;
              Polygon politt=new Polygon(Xtt,Ytt,puntt);
              gr.fillPolygon(politt);
       }
       if(!ani){
          if(got)xf1=150;xf2=250;
          if(gv){
             if(!co_im){
              yi=((y01-Ym)*(xl-xf1)/(xf1-x0))+y01;
              yis=(y01-(y01s-10-y01)*(xi-xf2)/(xf2-xl));
              xi=xl+(xl-x0)*(xl-xf1)/(xf1-x0);
              if(Ym>=y02){
               gr.setColor(Color.blue);
               int Xi[]={xi-1,xi-1,xi+1,xi+1};
               int Yi[]={yi-3,yi+3,yi+3,yi-3};
               int pun=Xi.length;
               Polygon poli1=new Polygon(Xi,Yi,pun);
               gr.fillPolygon(poli1);
              }
              if(Ym>y02-5&Ym<y02){
               gr.setColor(Color.blue);
               int Xt[]={xi-4,xi-2,xi+2,xi+4,xi-1};
               int Yt[]={yi-7,yi-2,yi-2,yi-7,yi-7};
               int punt=Xt.length;
               Polygon polit=new Polygon(Xt,Yt,punt);
               gr.fillPolygon(polit);
              }
              if(Ym>=y02-10&Ym<=y02-5){
               gr.setColor(Color.blue);
               int Xtt[]={xi-2,xi,xi+2};
               int Ytt[]={yi-3,yi+2,yi-3};
               int puntt=Xtt.length;
               Polygon politt=new Polygon(Xtt,Ytt,puntt);
               gr.fillPolygon(politt);
              }
              if(Ym>y02-5&Ym<y02)yi=yi-5;
              for(j=40;j<=240;j+=10){
                   gr.setColor(Color.lightGray);
                   gr.drawLine(x0,Ym,xl,j);
                   gr.drawLine(xl,j,xi,yi);
              }
              gr.setColor(Color.orange);
              gr.drawLine(x0,Ym,xl,Ym);
              gr.drawLine(xl,Ym,xi,yi);
              gr.drawLine(x0,Ym,xi,yi);
              gr.drawLine(x0,Ym,xl,yi);
              gr.drawLine(xl,yi,xi,yi);
             }//fine (!co_im)
          }//fine gv
       }//fine ani
       if(got){
          xa=260;xb=350;xc=xb;xd=xa;
          gr.setColor(Color.white);
          drawDashedLine(gr,300,140,350,140,5.,4.);//asse perp.lente
         if(ani){
            xf1=150;xf2=250;
            if(index==0)start();
            x0=100;
            int y0p=140-index;
            xi=300;yi=140+index;
            index=index+1;
            if(y0p>y02){
               gr.setColor(cim);
               int Xi[]={xi-1,xi-1,xi+1,xi+1};
               int Yi[]={y01,yi,yi,y01};
               int pun=Xi.length;
               Polygon poli1=new Polygon(Xi,Yi,pun);
               gr.fillPolygon(poli1);
            }
            if(y0p>y02-5&y0p<y02){
               gr.setColor(cim);
               int Xt[]={xi-1,xi-1,xi-4,xi-2,xi+2,xi+4,xi+1,xi+1};
               int Yt[]={y01,y01+30,y01+30,yi,yi,y01+30,y01+30,y01};
               int punt=Xt.length;
               Polygon polit=new Polygon(Xt,Yt,punt);
               gr.fillPolygon(polit);
            }
            if(y0p>=y02-10&y0p<=y02){
               gr.setColor(cim);
               int Xtt[]={xi-1,xi-1,xi-4,xi,xi+4,xi+1,xi+1};
               int Ytt[]={y01,y01+30,y01+30,yi,y01+30,y01+30,y01};
               int puntt=Xtt.length;
               Polygon politt=new Polygon(Xtt,Ytt,puntt);
               gr.fillPolygon(politt);
            }
            for(j=40;j<=240;j+=10){
                   gr.setColor(Color.lightGray);
                   gr.drawLine(x0,y0p,xl,j);
                   gr.drawLine(xl,j,xi,yi);
            }
            gr.setColor(Color.orange);
            gr.drawLine(x0,y0p,xl,y0p);
            gr.drawLine(xl,y0p,xi,yi);
            gr.drawLine(x0,y0p,xi,yi);
            gr.drawLine(x0,y0p,xl,yi);
            gr.drawLine(xl,yi,xi,yi);
            if(index==40){
               stop();
               index=0;
            }
         }//fine ani
       }//fine got
       yi=((y01-y0)*(xl-xf1)/(xf1-x0))+y01;
       xi=xl+(xl-x0)*(xl-xf1)/(xf1-x0);
       if(!got){
         xf1=140;xf2=260;
         if(!olm){
           if(!co_im){
              gr.setColor(cim);
              yis=(y01-(y01s-10-y01)*(xi-xf2)/(xf2-xl));
              int Xtt[]={xi-1,xi-1,xi-4,xi,xi+4,xi+1,xi+1};
              int Ytt[]={yis,yi-10,yi-10,yi,yi-10,yi-10,yis};
              int puntt=Xtt.length;
              Polygon politt=new Polygon(Xtt,Ytt,puntt);
              gr.fillPolygon(politt);
           }
         }
         /*if(ctn){
              xf2=260;xf1=140;
              gr.setColor(cim);
              yis=(y01-(y01s-10-y01)*(xi-xf2)/(xf2-xl));
              int Xtt[]={xi-1,xi-1,xi-4,xi,xi+4,xi+1,xi+1};
              int Ytt[]={yis,yi-10,yi-10,yi,yi-10,yi-10,yis};
              int puntt=Xtt.length;
              Polygon politt=new Polygon(Xtt,Ytt,puntt);
              gr.fillPolygon(politt);
         }*/
        }         
     }//fine toi
     if(olm){
              xf2=260;xf1=140;
              gr.setColor(cim);
              yis=(y01-(y01s-10-y01)*(xi-xf2)/(xf2-xl));
              int Xtt[]={xi-1,xi-1,xi-4,xi,xi+4,xi+1,xi+1};
              int Ytt[]={yis,yi-10,yi-10,yi,yi-10,yi-10,yis};
              int puntt=Xtt.length;
              Polygon politt=new Polygon(Xtt,Ytt,puntt);
              gr.fillPolygon(politt);

      if(!co_im){
         gr.setColor(new Color(120,60,50));
         gr.fillRect(xctn,yctn,l,h);
         if(ctn){
            for(j=40;j<=240;j+=10){
                   gr.setColor(Color.lightGray);
         //punto inf.
                   if(j==y01-20)gr.drawLine(x0,y01s-10,xctn+5,y01);
                   if(j<y01-20){
                      int yinck=(int)(j+((y01-10)-yl1)*(xl-xctn)/(xl-x0));
                      gr.drawLine(x0,y01s-10,xctn,yinck);
                   }
                   if(j>y01){
                      gr.drawLine(x0,y01s-10,xl,j);
                      gr.drawLine(xl,j,xi,yis);
                   }
         //punto sup.
                   if(j>y01+10){
                      gr.setColor(Color.lightGray);
                      gr.drawLine(x0,y0,xl,j);
                      gr.drawLine(xl,j,xi,yi);  
                      gr.setColor(Color.orange);
                      gr.drawLine(xl,yi,xi,yi);
                      gr.drawLine(xfrc1-5,yi+3,xfrc1,yi);
                   }
                   if(j<=y01+10){
                      yincj=j+(xl-xctn)*(y0-j)/(xl-x0);
                      gr.setColor(Color.lightGray);
                      gr.drawLine(x0,y0,xctn,yincj);
                      gr.drawLine(xfrc1-5,yi-3,xfrc1,yi);
                   }
            }//fine for
            gr.setColor(Color.orange);
            gr.drawLine(x0,y01s-10,xi,yis);
            gr.drawLine(x0,y01s-10,xl,y01s-10);
            gr.drawLine(xl,y01s-10,xi,yis);
                gr.drawLine(x0,y0,xctn,y0);
                yinc1=y01-(y01-y0)*(xl-xctn)/(xl-x0);
                gr.drawLine(x0,y0,xctn,yinc1);
                yinc2=y01+(y01-y0)*(xctn-xf1)/(xf1-x0);
                gr.drawLine(x0,y0,xctn,yinc2);
                gr.drawLine(xfrc-5,y0-3,xfrc,y0);
                gr.drawLine(xfrc-5,y0+3,xfrc,y0);
                yfrc=(int)(y01-(xl-xfrc)*(y01-y0)/(xl-x0));
                gr.drawLine(xfrc-5,yfrc-5,xfrc,yfrc);
                gr.drawLine(xfrc-5,yfrc+1,xfrc,yfrc);
                yfrc1=(int)(y01+(xfrc-xf1)*(y01-y0)/(xf1-x0));
                gr.drawLine(xfrc-1,yfrc1-6,xfrc,yfrc1);
                gr.drawLine(xfrc-5,yfrc1,xfrc,yfrc1);
         }//fine ctn
      }//fine !co_im
    }//fine olm
   g.drawImage(im,0,0,this); 
  }
public void drawDashedLine(Graphics g,int x1,int y1,int x2,int y2,
                            double dashlength, double spacelength) {
   double linelength=Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
   double yincrement=(y2-y1)/(linelength/(dashlength+spacelength));
   double xincdashspace=(x2-x1)/(linelength/(dashlength+spacelength));
   double yincdashspace=(y2-y1)/(linelength/(dashlength+spacelength));
   double xincdash=(x2-x1)/(linelength/(dashlength));
   double yincdash=(y2-y1)/(linelength/(dashlength));
   int counter=0;
   for (double i=0;i<linelength-dashlength;i+=dashlength+spacelength){
       g.drawLine((int) (x1+xincdashspace*counter),
                  (int) (y1+yincdashspace*counter),
                  (int) (x1+xincdashspace*counter+xincdash),
                  (int) (y1+yincdashspace*counter+yincdash));
       counter++;
       }
   if ((dashlength+spacelength)*counter<=linelength)
      g.drawLine((int) (x1+xincdashspace*counter),
                 (int) (y1+yincdashspace*counter),
                 x2,y2);
   }
  public void update(Graphics g){
    paint(g);
  }
  public boolean mouseDown(Event e,int xm,int ym){
    if(got){
     if(ym>100&ym<y01){
      Xm=xm;
      Ym=ym;
      gv=true;
      tasto.show();     
      tasto.reshape(10,10,160,20);
      lb2.setBackground(Color.white);   
      lb2.reshape(5,295,450,20);
      lb2.setText("Cliccando il tasto COSTRUZIONE IMMAGINE si puņ osservare la costruzione completa");
      lb2.show();
      lb3.setBackground(Color.white);   
      lb3.reshape(5,315,450,20);
      lb3.setText("dell'immagine fatta in sequenza.");
      lb3.show();
      repaint();
     }
    }

    if(toi){
     xm=x0;
     if(ym>100&ym<y01){
       Xm=xm;
       Ym=ym;
     }
    }
    return true;
  }
}