import java.applet.*;
import java.awt.*;
import java.util.*;

public class areaCompute extends Applet{
	public Poly l = new Poly();
	public canvasgraph graphiq = new canvasgraph(l);
 
	public void init() {

		setLayout(new BorderLayout());
		setBackground(Color.lightGray);
		Button efface= new Button("Clear");
		Button ferme= new Button("Close Poly");
		Button barea= new Button("Area");
		Button bchord= new Button("Chord");
		Button bcentre= new Button("Centre");
		Panel p=new Panel();
		p.setLayout(new FlowLayout(FlowLayout.LEFT));
		CheckboxGroup box=new CheckboxGroup();
		Checkbox onFly=new Checkbox("On-the-fly testing",box,true);
		Checkbox aftDraw=new Checkbox("Testing after drawing",box,false);

		efface.setBounds(0,480,65,25);
    efface.setFont(new Font("Clear",Font.BOLD,12));
    efface.setBackground(Color.lightGray);
    add(efface);

    ferme.setBounds(90,480,65,25);
    ferme.setFont(new Font("Close Poly",Font.BOLD,12));
    ferme.setBackground(Color.lightGray);
    add(ferme);

    bchord.setBounds(190,480,65,25);
    bchord.setFont(new Font("Chord",Font.BOLD,12));
    bchord.setBackground(Color.lightGray);
    add(bchord);

    bcentre.setBounds(290,480,65,25);
    bcentre.setFont(new Font("Centre",Font.BOLD,12));
    bcentre.setBackground(Color.lightGray);
    add(bcentre);

    barea.setBounds(385,480,65,25);
    barea.setFont(new Font("Area",Font.BOLD,12));
    barea.setBackground(Color.lightGray);
    add(barea);

		Panel p2=new Panel();
		p2.setLayout(new BorderLayout());
		p.add(p2);
		add("North",p);
		add("Center",graphiq);

/******/
		
		l.simple=false;
		l.drawlines=false;
		l.allarea=true;
		l.erasegreen=false;
	}

	public boolean action (Event e,Object o) {

		if (e.target instanceof Button) {
			if ("Clear".equals((String) o) ) {
				l.removeAllElements();
				l.closeP=false;	
				l.propoint=false;
				l.drawlines=false;
				l.drawchordline=false;
				l.chord=false;
				l.simple=false;			
				l.area=false;
				l.allarea=true;
				System.out.println("chordP10 " + graphiq.chordP1[0] ); 
				System.out.println("chordP11 " + graphiq.chordP1[1] ); 


				}
			if ("Close Poly".equals((String) o)) {
				if (l.size()>2)
				l.closeP=true;			
				l.simple=true;
			
			}
			if ("Chord".equals((String) o)) {
		    l.chord=true;
		    l.drawchordline=false;
		    l.firstchord=true;
		    l.erasegreen=true;
		  }
		  if ("Centre".equals((String) o)) {
		    l.propoint=true;
				
		  }
			if ("Area".equals((String) o)) {
				l.area=true;
			}

/******/
	  graphiq.repaint();
		System.out.println("button pressed");
		return true;
		}
		return false;
	}
	
	public boolean mouseMove(Event e, int x, int y) {
		super.showStatus((String) "("+x+","+y+")");
		return true;		
		}
		
}

class canvasgraph extends Canvas {
	Poly l;
		
		final int black=0;
		final int green=1;
		final int yellow=2;
		final int red=3;
	
		static int X,Y;
		static int xmouse;
		static int ymouse;
		static int areas;
		static double area0,lineK,lineB,areaChord;
		static int chordPoint1[]=new int[3];
		static int chordPoint2[]=new int[3];
		static int[] chordP1=new int[3];
	  static int[] chordP2=new int[3];
	  static int[] kj=new int[3];
		final int areaSumKedges[]=new int[99];

		
		canvasgraph(Poly liste) {
		resize(400,300);
		l=liste;
	  }
		
	 public void paint(Graphics g) {
		int pt[]=new int[3];
		int pt2[]=new int[3];
			g.setColor(Color.white);
			g.fillRect(0,0,450,450);
			g.setColor(Color.black);
			g.drawRect(0,0,450,450);


			
			
/* connect all points to make a plygon*/		
			
			 
			 for ( int i=0; i<l.size();i++) {
					pt = (int[]) l.elementAt(i);
					g.setColor(Color.red);
				  g.fillOval(pt[0]-2,pt[1]-2,8,8);
					g.setColor(Color.black);
					if (i!=0) 	
						draw(g,pt,pt2);	
					pt2[0]=pt[0];
					pt2[1]=pt[1];
					pt2[2]=pt[2];
     	if (i== (l.size()-1) && l.closeP ) 	
						draw(g,(int[])l.lastElement(),(int[]) l.elementAt(0));
		   } 	
			
			
			
/* Show the number of vertices chosen on the panel*/
			
			g.drawString("Nb of points : "+Integer.toString(l.size()),355,465);
			

			
			
/* Test the simple characrster of the polygon*/
			
			if (l.simple && (!l.chord)&&(!l.area)&&(!l.drawlines)) {
				if (checkcross0()){
					g.setColor(Color.red);
					g.drawString("None Simple Polygon,Click CLEAR!",0,465);			
					l.simple=false;
					g.setColor(Color.black);
				}
				
			}
			
			
/* Chose the two point of Chord*/			
	
			if (l.chord && l.simple && !l.area && !l.firstchord ){
				
       //System.out.println("D "+l.chord +l.simple +l.area);
			 g.setColor(Color.green);
  		 g.fillOval(chordPoint1[0]-2,chordPoint1[1]-2,8,8);
			 g.setColor(Color.blue);					
			}
			else if (!l.chord && l.drawchordline) {
			 //System.out.println("C");
	  	 g.setColor(Color.green);
  		 g.fillOval(chordPoint1[0]-2,chordPoint1[1]-2,8,8);
  		 g.fillOval(chordPoint2[0]-2,chordPoint2[1]-2,8,8);
			 g.setColor(Color.blue);					
		   g.drawLine(chordPoint1[0],chordPoint1[1],chordPoint2[0],chordPoint2[1]);
			 g.setColor(Color.black);
			 l.chord=false;
		}	
		
		
		
		
		
/* Draw lines from the prejection point to the subpolygon including the first point*/		
	
		if (l.drawlines && l.simple && !l.erasegreen){
			g.setColor(Color.blue);
			g.fillOval(X-2,Y-2,8,8);
		  boolean crossCh;
      crossCh=chordCrossEdge();
		  if(!crossCh){
		  	l.drawlines=false;
		  	g.setColor(Color.red);
		  	g.drawString("It is not a chord, Click Chord!",0,465);
		  	g.setColor(Color.black);
		  }
      if(crossCh && !l.erasegreen){
			 
      		//System.out.println("kj0 " + kj[0]+"kj1 "+ kj[1]);
         //System.out.println("cp10 " + chordP1[0]);
				 //System.out.println("cp11 " + chordP1[1]);
         //System.out.println("cp20 " + chordP2[0]);
				// System.out.println("cp21 " + chordP2[1]);

      	for (int i=0;i<l.size();i++) {
				 g.setColor(Color.green);				   
				 if ((i>kj[0])&&(i<=kj[1])) continue;
			   else
			   { //System.out.println("i= " + i);
			   	 pt = (int[]) l.elementAt(i);
			     //System.out.println("i0=" + i + pt[0]);
				   //System.out.println("i1=" + i + pt[1]);
       
           g.drawLine(pt[0],pt[1],X,Y);
			   }
			   g.drawLine(chordP1[0],chordP1[1],X,Y);
         g.drawLine(chordP2[0],chordP2[1],X,Y);

			
				}
				 g.setColor(Color.black);
      }
		}
		
		
		
		
		
/* Get the total area of polygon and that of subpolygon */
		
		if (l.area && l.simple && !l.propoint && l.closeP && l.drawlines){
					
     /*****	only the button "clear" pressed, l.allarea become "true" *******/
     /*****	it will take O(n) time for preprocessing the polygon       *******/
			
				  if(l.allarea)
				   {area0();
				    l.allarea=false;
				    System.out.println(" area0");
				   }
				  g.drawString("Total Area: "+Double.toString(area0),200,465);

    /*****	for every query,it take only constant time to get the area of subpolygon *******/
				   
				  
				  chordArea();
          System.out.println("areac");
        	g.drawString("Sub-Area: "+Double.toString(areaChord),50,465);
				  areas=0;
				  areaChord=0;
				  l.area=false;
				
			}      
		
		
	}
 
	
	public boolean checkcross0(){
		int i,j,k;
		int[] a=new int[3];
		int[] b=new int[3];
		int[] c=new int[3];
		int[] d=new int[3];

		for (i=0;i<(l.size()-3);i++)
			for (j=i+2;j<(l.size()-1);j++){
				
				 	 a=(int[])l.elementAt(i);b=(int[])l.elementAt(i+1);
				 	 c=(int[])l.elementAt(j);d=(int[])l.elementAt(j+1);
				 	
				 if(intersectprop(a,b,c,d)) return true;
			 	}
		for (i=1;i<(l.size()-2);i++){

				   a=(int[])l.elementAt(i);b=(int[])l.elementAt(i+1);
				 	 c=(int[])l.lastElement();d=(int[])l.firstElement();
			               
			if(intersectprop(a,b,c,d)) return true;
		}
     
	 return false;	
		
	}

	public void area0(){
		int Sum=0;
		int i;
	  int[] a=new int[3];
		int[] b=new int[3];
		
	
		for (i=0;i<(l.size()-1);i++){
			 a=(int[])l.elementAt(i);b=(int[])l.elementAt(i+1);
			 Sum=Sum+a[0]*b[1]-a[1]*b[0];
			 areaSumKedges[i]=Sum;
			 /*System.out.println("areask2= "+Sum*1.0/20);
       System.out.println("areask20= "+Sum/2.0);
       System.out.println("areask= "+areaSumKedges[i]);
       System.out.println("areask101= "+areaSumKedges[i]/101);
*/
		}
		a=(int[])l.lastElement();b=(int[])l.firstElement();
		Sum=Sum+a[0]*b[1]-a[1]*b[0];
		areaSumKedges[l.size()-1]=Sum;
		
		area0=Sum/2.0;
	//	System.out.println("areas= "+areas);
		return;
	}
	
	/* function for getting the area of subpolygon*/
public void chordArea(){
   int AChord=0;
   int[] a=new int[3];
	 int[] b=new int[3];
  //System.out.println("kj[0]= "+ kj[0]  );
  //System.out.println("kj[1]= "+ kj[1] );

   a=(int[])l.elementAt(kj[0]);
   if (kj[1]==l.size()-1)
   	 b=(int[])l.elementAt(0);
   else b=(int[])l.elementAt(kj[1]+1);
   //System.out.println("a= "+ a + b  );
	 AChord=a[0]*chordP1[1]-a[1]*chordP1[0]
	        +chordP1[0]*chordP2[1]-chordP1[1]*chordP2[0]
	        +chordP2[0]*b[1]-chordP2[1]*b[0];
	 System.out.println("A= "+ AChord );
	 //System.out.println("l.size= "+l.size() );
	 if (kj[0]==0){
	   areaChord=(areaSumKedges[l.size()-1]
	 	         -areaSumKedges[kj[1]]	 	         
	 	         +AChord)/2.0; 
	 	         System.out.println("kj[0]=0 ");
	 }
	 else {areaChord=(areaSumKedges[l.size()-1]
	 	         -areaSumKedges[kj[1]]
	 	         +areaSumKedges[kj[0]-1]
	 	         +AChord)/2.0;
	 	       

	 }
	 //System.out.println("c= "+ areaSumKedges[l.size()-1]+areaSumKedges[kj[1]]+areaSumKedges[kj[0]-1]);
   System.out.println("Ac= "+ areaChord  );
	 return;
  } 	 	         

	
	/* function for computing the two points of chord and the edge with which the chord intersects */
	public boolean chordCrossEdge(){
		int i,numCross=0,k;
		int[] a=new int[3];
		int[] b=new int[3];
		double k1,b1,k2,b2,temp;

    
		for (i=0;i<l.size();i++)
			{  if(i<(l.size()-1)){
				  a=(int[])l.elementAt(i);b=(int[])l.elementAt(i+1);
			   }
			   else{
		       //System.out.println("last" + i);
			     a=(int[])l.lastElement();b=(int[])l.firstElement();
			   }
				 if(intersectprop(a,b,chordPoint1,chordPoint2)){
				  kj[numCross]=i;
				 	numCross++;
      	  if(numCross>2) return false;
				 	k1=(a[1]-b[1])*1.0/(a[0]-b[0]);
				 	b1=a[1]*1.0-k1*a[0];
				 	k2=(chordPoint1[1]-chordPoint2[1])*1.0/(chordPoint1[0]-chordPoint2[0]);
				 	b2=chordPoint1[1]*1.0-k2*chordPoint1[0];
				 	 /*
				 	 System.out.println("i=" + i+"a[0] " + a[0] +" a[1] " +a[1]); 
				 	 System.out.println("b[0] " + b[0] +" b[1] " +b[1]);
				 	 System.out.println("b1 " + b1 +" k1 " + k1);           
				 	 System.out.println("CP10 " + chordPoint1[0] +" cp11 " +chordPoint1[1]);
           System.out.println("CP20 " + chordPoint2[0] +" cp21 " +chordPoint2[1]);
           System.out.println("b2 " + b2 +" k2 " + k2);  
				   */
				   if (numCross==1)
        	  { temp=((b1-b2)*1.0/(k2-k1));
        		  chordP1[0]=(int)(temp);
        		  chordP1[1]=(int)(k1*temp+b1);
        		  //System.out.println("cp10 " + chordP1[0]); 
              //System.out.println("cp11 " + chordP1[1]); 
  

         	  }
            if (numCross==2)
        	  { temp=((b1-b2)*1.0/(k2-k1));
        		 chordP2[0]=(int)(temp);
        	   chordP2[1]=(int)(k1*temp+b1);
        	   //System.out.println("cp20 " + chordP2[0]); 
             //System.out.println("cp21 " + chordP2[1]); 

        	  }    

				 			 	
				 }	
			}
	 if (numCross<2) return false;	     
	 return true;	
		
	}
	
 
 public boolean intersectprop(int[] a, int[] b, int[] c,int[] d){
		if(collinear(a,b,c) && ((a[0]-c[0])*(c[0]-b[0])>=0))
			return true;
		if(collinear(a,b,d) && ((a[0]-d[0])*(d[0]-b[0])>=0))
			return true;
		if(collinear(c,d,a) && ((c[0]-a[0])*(a[0]-d[0])>=0))
			return true;
		if(collinear(c,d,b) && ((c[0]-b[0])*(b[0]-d[0])>=0))
			return true;
		return
		  (Left(a,b,c)^Left(a,b,d)) && (Left(c,d,a)^Left(c,d,b));

	}
	public boolean Left(int[] a, int[] b, int[] c){
    if((a[0]*b[1]-a[1]*b[0]+
       a[1]*c[0]-a[0]*c[1]+
       b[0]*c[1]-b[1]*c[0])>0) 
       return	true;
    else return false;
	}
	public boolean collinear(int[] a, int[] b, int[] c){
    if((a[0]*b[1]-a[1]*b[0]+
       a[1]*c[0]-a[0]*c[1]+
       b[0]*c[1]-b[1]*c[0])==0) 
       return	true;
    else return false;
	}
		
	public void draw(Graphics g, int[] pt,int[] pt2) {

					g.setColor(Color.black);
					g.drawLine(pt[0],pt[1],pt2[0],pt2[1]);
					g.setColor(Color.black);
	} 				
	
	public boolean mouseMove(int x, int y) {
		xmouse=x;
		ymouse=y;
		return true;
	}

	public boolean mouseDown(Event evt, int x, int y)
	{	
		int Point[] = new int[3];
		
		if (x<450 && x>1 && y<450 && y>1 && (!l.closeP )) {
	
			Point[0]=x;
			Point[1]=y;
			//System.out.println("x,y" + x +" "+y);  
			Point[2]=black;
			l.addElement((int[]) Point);
		}	
	
		 if (x<450 && x>1 && y<450 && y>1 && l.chord ){ 
		 	if (l.firstchord){
			   System.out.println("first point");
				 Point[0]=x;
				 Point[1]=y;
			   
			   Point[2]=black;
			   chordPoint1[0]=x;
				 chordPoint1[1]=y; 
			   l.firstchord=false;
			 }
			 else {
				 Point[0]=x;
			   Point[1]=y;
			   Point[2]=black;

			 	chordPoint2[0]=x;
				chordPoint2[1]=y;			
				l.drawchordline=true;
				l.chord=false;
				System.out.println("second point");
			}
		
		}

		if (x<450 && x>1 && y<450 && y>1 && l.propoint ) {
			Point[0]=x;
			X=x;
			Point[1]=y;
			Y=y;
			Point[2]=black;	

			l.propoint=false;
			l.drawlines=true;
			l.erasegreen=false;
		}
		repaint(); /***************************/
		return true;
	}
}	

class Poly extends Vector {
	static boolean closeP;		
	static boolean propoint;
	static boolean drawlines;
	static boolean simple;
	static boolean area;
	static boolean chord;
  static boolean drawchordline;
  static boolean firstchord;
  static boolean allarea;
  static boolean erasegreen;
	}
