import java.awt.*;
import java.lang.*;
import java.applet.*;


public class CG_hw_02 extends BufferedApplet {
	
	double matrixD[][] = new double[3][3];
	double tempMatrix[][] = new double[3][3];
	
	int X[] = new int[2];
   	int Y[] = new int[2];
   	
   	double xy[][]={{10,10,1},{20,10,1},{0,0,0}};
   	

   	
   	
	
		
		public void identity(double matrix[][])
		{
			for(int i=0;i<3;i++)
			{
				for(int j=0;j<3;j++)
				{
					if(i==j)
						matrix[i][j]=1;
					else
						matrix[i][j]=0;
				}
			}

		}
		
   		public void translationMatrix(double matrix[][], double a, double b) 
   		{
      		identity(matrix);
   			matrix[2][0] = a;
      		matrix[2][1] = b;
      		
			
   		}
   		
   		public void rotationMatrix(double matrix[][], double angle)
   		{
   			identity(matrix);
   			matrix[0][0]=Math.cos(angle);
   			matrix[0][1]=Math.sin(angle);
   			matrix[1][0]=-Math.sin(angle);
   			matrix[1][1]=Math.cos(angle);
   		}


   		public void scaleMatrix(double matrix[][], double a,double b)
   		{
   			identity(matrix);
   			matrix[0][0]=a;
   			matrix[1][1]=b;
   		}		
		
		
	
	
		public void multiplyMatrix(double A[][], double B[][])
		{
			double temp[][] = new double[3][3];
			for(int j=0;j<3;j++)
			{
				for(int k=0;k<3;k++)
				{
					temp[j][k]=A[j][k];
				}
			}
			
			for (int i = 0 ; i < 3 ; i++)
			{
   				for (int j = 0 ; j < 3 ; j++)
   				{
    	  			A[i][j] = temp[i][0]*B[0][j] + temp[i][1]*B[1][j] + temp[i][2]*B[2][j];
    	  		
    	  		}

    	  	}
	
		
		}
	
   		


   		public void translate(double matrix[][], double a, double b) 
   		{
   			identity(tempMatrix);
   		   	translationMatrix(tempMatrix,a,b); // CREATES A TRANSLATION MATRIX
   		   	multiplyMatrix( matrix,tempMatrix);
   	   		for (int i = 0 ; i < 2 ; i++) 
   			{
    		  X[i] = viewportX(xy[i][0]);
   			  Y[i] = viewportY(xy[i][1]);
   			 
   			}      // MODIFIES THE FIRST ARGUMENT IN PLACE
   		}

   		public void rotation(double matrix[][], double a) 
   		{
   			identity(tempMatrix);   	
   		   	rotationMatrix(tempMatrix,a); // CREATES A TRANSLATION MATRIX
   		   	multiplyMatrix(matrix,tempMatrix);   
   	   		for (int i = 0 ; i < 2 ; i++) 
   			{
    		  X[i] = viewportX(xy[i][0]);
   			  Y[i] = viewportY(xy[i][1]);
   			 
   			}   // MODIFIES THE FIRST ARGUMENT IN PLACE
   		}
   	
   		public void scale(double matrix[][], double a, double b) 
   		{
   			identity(tempMatrix);
   		   	scaleMatrix(tempMatrix,a,b); // CREATES A TRANSLATION MATRIX
   	   		multiplyMatrix( matrix,tempMatrix); 
   	   		for (int i = 0 ; i < 2 ; i++) 
   			{
    		  X[i] = viewportX(xy[i][0]);
   			  Y[i] = viewportY(xy[i][1]);
   			 
   			}      // MODIFIES THE FIRST ARGUMENT IN PLACE
   		}   	

	
	
	
	public int viewportX(double a)
	{
		return ((int)a+150);

	}
	
	public int viewportY(double a)
	{
		return (-(int)a+100);

	}
	
	public void init() {
		

	
	
	}
	
	
	public void render(Graphics g) {
		
		if(damage){
		
		

		Matrix2D a = new Matrix2D();
		


  
  		scale(xy,1,1);
  		
		
  		
   		rotation(xy,Math.PI/1.5);
   		g.drawPolygon(X,Y,2);
   		rotation(xy,1.95*Math.PI);
   		translate(xy,2,-10);
   		g.drawPolygon(X,Y,2);
   		
 
   		rotation(xy,1.93*Math.PI);
   		translate(xy,3,-13);
   		g.drawPolygon(X,Y,2);   		
   		
   		
    	rotation(xy,1.98*Math.PI);
   		translate(xy,2,-11);
   		g.drawPolygon(X,Y,2);  		
   		
   		
    	rotation(xy,1.99*Math.PI);
   		translate(xy,1,-11);
   		g.drawPolygon(X,Y,2);   		
   		
   		
    	rotation(xy,1.99*Math.PI);
   		translate(xy,1,-11);
   		g.drawPolygon(X,Y,2);  		
   		
   		scale(xy,1,2);
      	rotation(xy,Math.PI);
   		translate(xy,-15,-140);
   		g.drawPolygon(X,Y,2);			
  
   		
     	rotation(xy,0.93*Math.PI);
   		translate(xy,-29,-128);
   		g.drawPolygon(X,Y,2);  		
   		
     	rotation(xy,0.93*Math.PI);
   		translate(xy,-41,-165);
   		g.drawPolygon(X,Y,2);   		
   		
     	rotation(xy,0.93*Math.PI);
   		translate(xy,-61,-200);
   		g.drawPolygon(X,Y,2);  		
   		
   		
     	rotation(xy,Math.PI);
   		translate(xy,-62,-237);
   		g.drawPolygon(X,Y,2);   		  		
   		
   		
     	rotation(xy,0.45*Math.PI);
   		translate(xy,-154,-84);
   		g.drawPolygon(X,Y,2);	   		
		
     	rotation(xy,0.49*Math.PI);
   		translate(xy,-161,-102);
   		g.drawPolygon(X,Y,2);
   		
     	rotation(xy,1.05*Math.PI);
   		translate(xy,-9,-272);
   		g.drawPolygon(X,Y,2);  
   		
     	rotation(xy,1.06*Math.PI);
   		translate(xy,16,-240);
   		g.drawPolygon(X,Y,2);   		 		

     	rotation(xy,1.07*Math.PI);
   		translate(xy,35,-202);
   		g.drawPolygon(X,Y,2); 
   		
     	rotation(xy,0.2*Math.PI);
   		translate(xy,-45,-23);
   		g.drawPolygon(X,Y,2); 
   		
     	rotation(xy,1.1*Math.PI);
   		translate(xy,73,-193);
   		g.drawPolygon(X,Y,2); 
   		
     	rotation(xy,1.05*Math.PI);
   		translate(xy,88,-230);
   		g.drawPolygon(X,Y,2); 

     	rotation(xy,1.05*Math.PI);
   		translate(xy,122,-255);
   		g.drawPolygon(X,Y,2);
   		
     	rotation(xy,1.05*Math.PI);
   		translate(xy,159,-275);
   		g.drawPolygon(X,Y,2);
   		
     	rotation(xy,1.05*Math.PI);
   		translate(xy,198,-289);
   		g.drawPolygon(X,Y,2);
   		
   		
   		rotation(xy,0.35*Math.PI);
   		translate(xy,-68,-169);
   		g.drawPolygon(X,Y,2);
   		
     	rotation(xy,0.5*Math.PI);
   		translate(xy,-38,-252);
   		g.drawPolygon(X,Y,2);
   		
   		
     	rotation(xy,0.96*Math.PI);
   		translate(xy,199,-277);
   		g.drawPolygon(X,Y,2);
   		
		rotation(xy,0.90*Math.PI);
   		translate(xy,153,-262);
   		g.drawPolygon(X,Y,2);  
   		
   		
		rotation(xy,0.9*Math.PI);
   		translate(xy,145,-225);
   		g.drawPolygon(X,Y,2); 		
   		
		rotation(xy,0.95*Math.PI);
   		translate(xy,164,-179);
   		g.drawPolygon(X,Y,2);
   		
   		
   		
		rotation(xy,0.95*Math.PI);
   		translate(xy,168,-155);
   		g.drawPolygon(X,Y,2);   		
   		
   		
		rotation(xy,0.95*Math.PI);
   		translate(xy,178,-127);
   		g.drawPolygon(X,Y,2);  		
   		
   		
		rotation(xy,0.95*Math.PI);
   		translate(xy,197,-92);
   		g.drawPolygon(X,Y,2);   		
   		
   		
		rotation(xy,0.95*Math.PI);
   		translate(xy,220,-60);
   		g.drawPolygon(X,Y,2);   		
   		   		
  
		rotation(xy,0.95*Math.PI);
   		translate(xy,248,-31);
   		g.drawPolygon(X,Y,2);  
  
		rotation(xy,0.55*Math.PI);
   		translate(xy,155,-118);
   		g.drawPolygon(X,Y,2);  
  
		rotation(xy,0.45*Math.PI);
   		translate(xy,108,-122);
   		g.drawPolygon(X,Y,2);  
  
 
		rotation(xy,1.05*Math.PI);
   		translate(xy,214,27);
   		g.drawPolygon(X,Y,2); 
 
 
		rotation(xy,1.05*Math.PI);
   		translate(xy,192,-2);
   		g.drawPolygon(X,Y,2); 
 
 
 		rotation(xy,1.05*Math.PI);
   		translate(xy,175,-34);
   		g.drawPolygon(X,Y,2);
 
 
  		rotation(xy,1.05*Math.PI);
   		translate(xy,161,-72);
   		g.drawPolygon(X,Y,2);
 
 
   		rotation(xy,1.05*Math.PI);
   		translate(xy,152,-111);
   		g.drawPolygon(X,Y,2);
   		
   		rotation(xy,0.20*Math.PI);
   		translate(xy,-123,38);
   		g.drawPolygon(X,Y,2);
 
    	rotation(xy,0.45*Math.PI);
   		translate(xy,5,55);
   		g.drawPolygon(X,Y,2); 
   		
     	rotation(xy,0.58*Math.PI);
   		translate(xy,25,58);
   		g.drawPolygon(X,Y,2);  		
   		
   		  		
      	rotation(xy,.97*Math.PI);
   		translate(xy,5,46);
   		g.drawPolygon(X,Y,2);  		
   		
   		
   		
       	rotation(xy,.97*Math.PI);
   		translate(xy,20,16);
   		g.drawPolygon(X,Y,2); 		
   		
   		
       	rotation(xy,.97*Math.PI);
   		translate(xy,34,-19);
   		g.drawPolygon(X,Y,2);   		
   		
   		
        rotation(xy,1.05*Math.PI);
   		translate(xy,53,-52);
   		g.drawPolygon(X,Y,2); 		
   		
   		
        rotation(xy,1.05*Math.PI);
   		translate(xy,76,-86);
   		g.drawPolygon(X,Y,2);  		
   		
 
 
        rotation(xy,1.05*Math.PI);
   		translate(xy,103,-116);
   		g.drawPolygon(X,Y,2); 
   		
   		
        rotation(xy,1.02*Math.PI);
   		translate(xy,120,-142);
   		g.drawPolygon(X,Y,2);
   		
   		 		 		
        rotation(xy,1.22*Math.PI);
   		translate(xy,150,-180);
   		g.drawPolygon(X,Y,2); 
  		
        rotation(xy,0.5*Math.PI);
   		translate(xy,-97,-203);
   		g.drawPolygon(X,Y,2); 
   		

   		scale(xy,1,5);
   		translate(xy,0,650);
   		g.drawPolygon(X,Y,2);
   		
 		
   		
   		translate(xy,-20,-11);
   		g.drawPolygon(X,Y,2);
   		
   		scale(xy,1,.2);
   		
   		translate(xy,0,-35);
   		g.drawPolygon(X,Y,2);
   		
    	translate(xy,0,20);
   		g.drawPolygon(X,Y,2);  
   		
   		
   		translate(xy,20,-1);
   		g.drawPolygon(X,Y,2);
   		
   		scale(xy,1,2);
   		
        rotation(xy,0.8*Math.PI);
   		translate(xy,82,-110);
   		g.drawPolygon(X,Y,2); 
   		
   		scale(xy,1,1.5);
   		rotation(xy,1.05*Math.PI);
   		translate(xy,171,23);
   		g.drawPolygon(X,Y,2); 	
   		
 
    	translate(xy,-15,15);
   		g.drawPolygon(X,Y,2);
   		
   		scale(xy,1,0.25);
   		rotation(xy,1.07*Math.PI);
   		translate(xy,139,37);
   		g.drawPolygon(X,Y,2);
   		
   		rotation(xy,0.45*Math.PI);
   		translate(xy,50,-56);
   		g.drawPolygon(X,Y,2);
   		
   		scale(xy,1,4);
   		rotation(xy,1.07*Math.PI);
   		translate(xy,71,90);
   		g.drawPolygon(X,Y,2);
   		
   		translate(xy,-15,-15);
   		g.drawPolygon(X,Y,2);
   		  		
   		scale(xy,1,.4);
   		rotation(xy,.88*Math.PI);
   		translate(xy,53,-5);
   		g.drawPolygon(X,Y,2);
   		
 
 
    	scale(xy,1,.4);
   		rotation(xy,.45*Math.PI);
   		translate(xy,-2,31);
   		g.drawPolygon(X,Y,2); 
   		

   		rotation(xy,.5*Math.PI);
   		translate(xy,160,53);
   		g.drawPolygon(X,Y,2);
   		
   		  		 		
				

   				
}

}


}

class BufferedApplet extends java.applet.Applet implements Runnable
{
/*
   THIS CLASS HANDLES DOUBLE BUFFERING FOR YOU, SO THAT THE IMAGE
   DOESN'T FLICKER WHILE YOU'RE RENDERING IT.  YOU DON'T REALLY
   NEED TO WORRY ABOUT THIS TOO MUCH, AND YOU'LL PROBABLY NEVER NEED
   TO CHANGE IT.  IT'S REALLY JUST USEFUL LOW LEVEL PLUMBING.
*/

   public void render(Graphics g) { }   // *you* define how to render
   public boolean damage = true;        // you can force a render

   private Image image = null;
   private Graphics buffer = null;
   private Thread t;
   private Rectangle r = new Rectangle(0, 0, 0, 0);

   // A BACKGROUND THREAD CHECKS FOR CHANGES ABOUT 30 TIMES PER SECOND

   public void start() { if (t == null) { t = new Thread(this); t.start(); } }
   public void stop()  { if (t != null) { t.stop(); t = null; } }
   public void run()   { try { while (true) { repaint(); t.sleep(30); } }
                             catch(InterruptedException e){}; }
/*
   UPDATE GETS CALLED BY THE SYSTEM.
   IT CALLS YOUR RENDER METHOD, WHICH DRAWS INTO AN OFF-SCREEN IMAGE.
   THEN UPDATE COPIES THE IMAGE YOU'VE RENDERED ONTO THE APPLET WINDOW.
*/

   public void update(Graphics g) {
      if (r.width != bounds().width || r.height != bounds().height) {
         image = createImage(bounds().width, bounds().height);
         buffer = image.getGraphics();
         r = bounds();
         damage = true;
      }
      render(buffer);
      damage = false;
      if (image != null)
         g.drawImage(image,0,0,this);
   }
}