import java.applet.*;
import java.awt.*;
import java.lang.Math;
import java.lang.Object;
public class Cube extends Applet {

     public class point implements Cloneable{
                 public int x;
                 public int y;


                  public Object clone(){ //begin clone
                    try{ //begin try
                        return super.clone();
                        } //end try
                         
                    catch(CloneNotSupportedException e){ // begin catch
                        return null;  //if there is a catch
                         } //end catch
                    } //end cloning structure for point
             
                 }  //end point def

     public class rpoint implements Cloneable{
                 public double x;
                 public double y;
                 public double z;

                  public Object clone(){ //begin clone
                    try{ //begin try
                        return super.clone();
                        } //end try
                         
                    catch(CloneNotSupportedException e){ // begin catch
                        return null;  //if there is a catch
                         } //end catch
                    } //end cloning structure for point
             
                 }  //end point def


    
public class RCube implements Cloneable{
                public rpoint front=new rpoint();
                public rpoint side=new rpoint();
                public rpoint top=new rpoint();
                public point up1=new point();
                public point up2=new point();
                public point up3=new point();
                public point up4=new point();
                public point down1=new point();
                public point down2=new point();
                public point down3=new point();
                public point down4=new point();
                public double esize=30.0;
                public rpoint raxis=new rpoint();
                public double theta=0.0;

                  public Object clone(){ //begin clone
                    try{ //begin try
                        RCube cu=(RCube)super.clone();
                        cu.front=(rpoint)front.clone();
                        cu.top=(rpoint)top.clone();
                        cu.side=(rpoint)side.clone();
                        cu.raxis=(rpoint)raxis.clone();
                        cu.up1=(point)up1.clone();
                        cu.up2=(point)up2.clone();
                        cu.up3=(point)up3.clone();
                        cu.up4=(point)up4.clone();
                        cu.down1=(point)down1.clone();
                        cu.down2=(point)down2.clone();
                        cu.down3=(point)down3.clone();
                        cu.down4=(point)down4.clone();               
                        return cu;
                        } //end try
                    catch(CloneNotSupportedException e){
                           return null;
                          }//end catch

                    } //end cloning structure for body
  
 
                } // end Cube  def

   private int i;
   private int last_x=0;
   private int last_y=0;

   private Color current_color=Color.black;
   private Button clear_button;
   private Button draw_button;
   private Choice ang_choices;

   public RCube er=new RCube();
   public RCube cu=new RCube();
   public RCube c=new RCube();

   private double xmult=0.5;
   private double mult=0.01;
   private double phi=0.0;
   private double psi=0.0;
   private int delX;
   private int delY;



//init applet
   public void init(){

//set backgd color
    this.setBackground(Color.white);

//create a button
    clear_button=new Button("Clear");
    clear_button.setForeground(Color.black);
    clear_button.setBackground(Color.lightGray);
    this.add(clear_button);

//create a button
    draw_button=new Button("Draw Cube");
    draw_button.setForeground(Color.black);
    draw_button.setBackground(Color.lightGray);
    this.add(draw_button);



   }
//end init applet




//called when mouse click
    public boolean mouseDown(Event e, int x, int y){
          last_x=x; last_y=y;
           return true;
       }


//called when mouse moves
    public boolean mouseDrag(Event e, int x, int y){
          Graphics g=this.getGraphics();
          er=(RCube)c.clone();


// figure phi and psi
 
       delX=x - last_x;
       delY=y - last_y;

       phi=phi+ mult*delX;
      psi=psi- mult*delY;
       
 
c.front.x=Math.cos(psi)*Math.cos(phi);
c.front.z=Math.sin(psi)*Math.cos(phi);
c.front.y= Math.sin(phi);

c.side.x= -Math.cos(psi)*Math.sin(phi);
c.side.z= -Math.sin(psi)*Math.sin(phi);
c.side.y= Math.cos(phi);


c.top.x =c.front.y*c.side.z - c.front.z*c.side.y;
c.top.y = c.front.z*c.side.x - c.front.x*c.side.z;
c.top.z = c.front.x*c.side.y - c.front.y*c.side.x;





//figure vertices

c.down1.y=(int)(80 + c.esize*(xmult*(c.front.x - c.top.x - c.side.x) 
                         +  c.top.z - c.front.z + c.side.z));
c.down1.x=(int)(60 + c.esize*(xmult*(-c.front.x + c.top.x + c.side.x) 
                         +  c.front.y + c.top.y - c.side.y));
c.down2.y=(int)(80 + c.esize*(xmult*(c.front.x - c.top.x + c.side.x) 
                         +  c.top.z - c.front.z + c.side.z));
c.down2.x=(int)(60 + c.esize*(xmult*(-c.front.x + c.top.x - c.side.x) 
                         +  c.front.y + c.top.y + c.side.y));
c.down4.y=(int)(80 + c.esize*(xmult*(-c.front.x - c.top.x + c.side.x) 
                         +  c.top.z + c.front.z + c.side.z));
c.down4.x=(int)(60 + c.esize*(xmult*(c.front.x + c.top.x - c.side.x) 
                         -  c.front.y + c.top.y + c.side.y));
c.down3.y=(int)(80 + c.esize*(xmult*(-c.front.x - c.top.x - c.side.x) 
                         +  c.top.z + c.front.z + c.side.z));
c.down3.x=(int)(60 + c.esize*(xmult*(c.front.x + c.top.x + c.side.x) 
                         -  c.front.y - c.top.y - c.side.y));

c.up1.y=(int)(80 + c.esize*(xmult*(c.front.x + c.top.x - c.side.x) 
                         -  c.top.z - c.front.z - c.side.z));
c.up1.x=(int)(60 + c.esize*(xmult*(-c.front.x - c.top.x + c.side.x) 
                         +  c.front.y - c.top.y - c.side.y));
c.up2.y=(int)(80 + c.esize*(xmult*(c.front.x + c.top.x + c.side.x) 
                         -  c.top.z - c.front.z - c.side.z));
c.up2.x=(int)(60 + c.esize*(xmult*(-c.front.x - c.top.x - c.side.x) 
                         +  c.front.y + c.top.y + c.side.y));
c.up4.y=(int)(80 + c.esize*(xmult*(-c.front.x + c.top.x + c.side.x) 
                         -  c.top.z + c.front.z - c.side.z));
c.up4.x=(int)(60 + c.esize*(xmult*(c.front.x - c.top.x - c.side.x) 
                         -  c.front.y + c.top.y + c.side.y));
c.up3.y=(int)(80 + c.esize*(xmult*(-c.front.x + c.top.x - c.side.x) 
                         -  c.top.z + c.front.z - c.side.z));
c.up3.x=(int)(60 + c.esize*(xmult*(c.front.x - c.top.x + c.side.x) 
                         -  c.front.y - c.top.y - c.side.y));
// erase 

         g.setColor(Color.white);

               g.drawLine(er.up3.x,er.up3.y,er.up4.x,er.up4.y);//up3 to up4
               g.drawLine(er.up3.x,er.up3.y,er.up1.x,er.up1.y);//up3 to up1
               g.drawLine(er.up4.x,er.up4.y,er.up2.x,er.up2.y);//up4 to up2
               g.drawLine(er.up1.x,er.up1.y,er.up2.x,er.up2.y);//up1 to up2
               g.drawLine(er.up3.x,er.up3.y,er.down3.x,er.down3.y);//up3 to down3
               g.drawLine(er.up4.x,er.up4.y,er.down4.x,er.down4.y);//up4 to down4
               g.drawLine(er.up1.x,er.up1.y,er.down1.x,er.down1.y);//up1 to down1
               g.drawLine(er.up2.x,er.up2.y,er.down2.x,er.down2.y);//up2 to down2
               g.drawLine(er.down3.x,er.down3.y,er.down1.x,er.down1.y);//down3 to down1
               g.drawLine(er.down2.x,er.down2.y,er.down4.x,er.down4.y);//down4 to down2
               g.drawLine(er.down4.x,er.down4.y,er.down3.x,er.down3.y);//down3 to down4
               g.drawLine(er.down1.x,er.down1.y,er.down2.x,er.down2.y);//down1 to down2

//draw
        
               g.setColor(Color.black);

               g.drawLine(c.up1.x,c.up1.y,c.up2.x,c.up2.y);//up1 to up2
               g.drawLine(c.up3.x,c.up3.y,c.up1.x,c.up1.y);//up3 to up1
               g.drawLine(c.up4.x,c.up4.y,c.up2.x,c.up2.y);//up4 to up2
               g.drawLine(c.up3.x,c.up3.y,c.up4.x,c.up4.y);//up3 to up4
               g.setColor(Color.red);
               g.drawLine(c.up3.x,c.up3.y,c.down3.x,c.down3.y);//up3 to down3
               g.drawLine(c.up4.x,c.up4.y,c.down4.x,c.down4.y);//up4 to down4
               g.drawLine(c.up1.x,c.up1.y,c.down1.x,c.down1.y);//up1 to down1
               g.drawLine(c.up2.x,c.up2.y,c.down2.x,c.down2.y);//up2 to down2
               g.drawLine(c.down4.x,c.down4.y,c.down3.x,c.down3.y);//down3 to down4
               g.drawLine(c.down1.x,c.down1.y,c.down2.x,c.down2.y);//down1 to down2
               g.drawLine(c.down3.x,c.down3.y,c.down1.x,c.down1.y);//down3 to down1
               g.drawLine(c.down2.x,c.down2.y,c.down4.x,c.down4.y);//down4 to down2



          last_x=x;
          last_y=y;
          return true;
      }

//user clicks button or chooses a color
     public boolean action(Event event, Object arg){
         if(event.target==clear_button){
               Graphics g=this.getGraphics();
               Rectangle r=this.bounds();
               g.setColor(this.getBackground());
               g.fillRect(r.x,r.y,r.width,r.height);
               return true;
              }
              //end clear

  
          // in case of click
         else if(event.target==draw_button){

// draw
c.front.x=1.0;
c.front.y=0.0;
c.front.z=0.0;
c.side.x=0.0;
c.side.y=1.0;
c.side.z=0.0;
c.top.x=0.0;
c.top.y=0.0;
c.top.z=1.0;
phi=0.0;
psi=0.0;

c.down1.y=(int)(80 + c.esize*(xmult*(c.front.x - c.top.x - c.side.x) 
                         +  c.top.z - c.front.z + c.side.z));
c.down1.x=(int)(60 + c.esize*(xmult*(-c.front.x + c.top.x + c.side.x) 
                         +  c.front.y + c.top.y - c.side.y));
c.down2.y=(int)(80 + c.esize*(xmult*(c.front.x - c.top.x + c.side.x) 
                         +  c.top.z - c.front.z + c.side.z));
c.down2.x=(int)(60 + c.esize*(xmult*(-c.front.x + c.top.x - c.side.x) 
                         +  c.front.y + c.top.y + c.side.y));
c.down4.y=(int)(80 + c.esize*(xmult*(-c.front.x - c.top.x + c.side.x) 
                         +  c.top.z + c.front.z + c.side.z));
c.down4.x=(int)(60 + c.esize*(xmult*(c.front.x + c.top.x - c.side.x) 
                         -  c.front.y + c.top.y + c.side.y));
c.down3.y=(int)(80 + c.esize*(xmult*(-c.front.x - c.top.x - c.side.x) 
                         +  c.top.z + c.front.z + c.side.z));
c.down3.x=(int)(60 + c.esize*(xmult*(c.front.x + c.top.x + c.side.x) 
                         -  c.front.y - c.top.y - c.side.y));

c.up1.y=(int)(80 + c.esize*(xmult*(c.front.x + c.top.x - c.side.x) 
                         -  c.top.z - c.front.z - c.side.z));
c.up1.x=(int)(60 + c.esize*(xmult*(-c.front.x - c.top.x + c.side.x) 
                         +  c.front.y - c.top.y - c.side.y));
c.up2.y=(int)(80 + c.esize*(xmult*(c.front.x + c.top.x + c.side.x) 
                         -  c.top.z - c.front.z - c.side.z));
c.up2.x=(int)(60 + c.esize*(xmult*(-c.front.x - c.top.x - c.side.x) 
                         +  c.front.y + c.top.y + c.side.y));
c.up4.y=(int)(80 + c.esize*(xmult*(-c.front.x + c.top.x + c.side.x) 
                         -  c.top.z + c.front.z - c.side.z));
c.up4.x=(int)(60 + c.esize*(xmult*(c.front.x - c.top.x - c.side.x) 
                         -  c.front.y + c.top.y + c.side.y));
c.up3.y=(int)(80 + c.esize*(xmult*(-c.front.x + c.top.x - c.side.x) 
                         -  c.top.z + c.front.z - c.side.z));
c.up3.x=(int)(60 + c.esize*(xmult*(c.front.x - c.top.x + c.side.x) 
                         -  c.front.y - c.top.y - c.side.y));

               Graphics g=this.getGraphics();
               g.setColor(Color.black);
             
   g.drawLine(c.up3.x,c.up3.y,c.up4.x,c.up4.y);//up3 to up4
   g.drawLine(c.up3.x,c.up3.y,c.down3.x,c.down3.y);//up3 to down3
   g.drawLine(c.down4.x,c.down4.y,c.down3.x,c.down3.y);//down3 to down4
   g.drawLine(c.up4.x,c.up4.y,c.down4.x,c.down4.y);//up4 to down4
   g.drawLine(c.up1.x,c.up1.y,c.up2.x,c.up2.y);//up1 to up2
   g.drawLine(c.up1.x,c.up1.y,c.down1.x,c.down1.y);//up1 to down1
   g.drawLine(c.up2.x,c.up2.y,c.down2.x,c.down2.y);//up2 to down2
   g.drawLine(c.down1.x,c.down1.y,c.down2.x,c.down2.y);//down1 to down2
   g.drawLine(c.up3.x,c.up3.y,c.up1.x,c.up1.y);//up3 to up1
   g.drawLine(c.up4.x,c.up4.y,c.up2.x,c.up2.y);//up4 to up2
   g.drawLine(c.down3.x,c.down3.y,c.down1.x,c.down1.y);//down3 to down1
   g.drawLine(c.down2.x,c.down2.y,c.down4.x,c.down4.y);//down4 to down2
                
            
           
          return true;
          } //end draw button event
           // other wise let superclass handle it
          else return super.action(event, arg);
     }
     // end action method
}
//end Applet

