/****************************************************************
*File:Polydraw.java
*Author: David Allard
*Description:  This applet contains an example of a reconfiguration  
*              and the means to dynamically reconfigure between two
*              polygons specified by the user.  The user clicks the 
*              points of the initial polygon onto the canvas, and 
*              specifies the final polygon by modifying the points
*              once they have been entered. Some deprecated libraries
*              for mouse input are used, and could be updated.
******************************************************************/



import java.applet.*;
import java.awt.*;
import java.util.*;
import java.lang.*;


public class PolyDraw extends Applet{
	
	public Poly_v l = new Poly_v();//extended vector for our polygon
	public canvasgraph graph = new canvasgraph(l);
	public int[][] poly1= {{170,100,1},{240,115,1},{320,170,1},{327, 190,1},
	{300,345,1},{270,370,1},{240,365,1},{180, 300,1}, {120,184,1}};
	
	Checkbox c_in_pointer;//pointer to input Checkbox, used for setting
	Checkbox c_out_pointer;//pointer to output Checkbox
	CheckboxGroup io;
	
	
	public void init(){
		
		//create the containers and buttons
		setLayout(new BorderLayout());
		setBackground(Color.lightGray);
		Button preset1 = new Button("Example");
		Button clear= new Button("Clear");
		Button close= new Button("Close");

		CheckboxGroup box=new CheckboxGroup();
		
		//options for type of processing
		Checkbox stepButton=new Checkbox("Stepwise",box,true);
		Checkbox compButton=new Checkbox("Complete",box,false);
		Checkbox textButton=new Checkbox("Explain",true);
			
		CheckboxGroup inout=new CheckboxGroup();//initial and final configurations
		Checkbox input=new Checkbox("Initial",inout,true);
		Checkbox output=new Checkbox("Final",inout,false);
		
		io=inout;//pointer to CheckBoxGroup
		c_in_pointer=input;
		c_out_pointer=output;
		
		Button reconfigure= new Button("Reconfigure");
		Panel p=new Panel();
		p.setLayout(new FlowLayout(FlowLayout.RIGHT));
	
		p.add(preset1);
		p.add(clear);
		p.add(close);
		p.add(textButton, "West");
		
		Panel p2=new Panel();
		p2.setLayout(new BorderLayout());
		p2.add(stepButton, "North");
		p2.add(compButton, "South");
		
		Panel p3=new Panel();
		p3.setLayout(new BorderLayout());
		p3.add(input, "North");
		p3.add(output, "South");
		
		Panel p4=new Panel();
		p4.setLayout(new BorderLayout());
		Button inc_angle= new Button("+");
		Button dec_angle= new Button("-");
		Button big_inc_angle= new Button("++");
		Button big_dec_angle= new Button("--");
		p4.add(inc_angle,"North");
		p4.add(dec_angle,"South");
		Panel p5=new Panel();
		p5.setLayout(new BorderLayout());
		p5.add(big_inc_angle,"North");
		p5.add(big_dec_angle,"South");
		
		p.add(p2);
		p.add(p4);
		p.add(p5);
		p.add(p3);
		p.add(reconfigure);
		
		add("North",p);
		add("Center",graph);
		l.step=true;
		l.textoff=false;
		l.reconfigure=false;
		l.end=false;
		l.start_complete=false;
		l.drawn=false;
		l.closed=false;
		l.input_poly=true;
		l.example = false;
		io.setSelectedCheckbox(input);
		l.moves = new Vector();//will hold reconfigurations
		
	}//method init
	
	
	
	
	
	//initializes a default polygon
	public void addPoly(int num,Poly_v po){

		String lab;
		Vertex v0,v1,v2,v3,v4,v5,v6,v7,v8;
		int dif;
		int[] temp = new int[3];
		int[][] temp2 = new int[9][3];
		Vertex[] v = new Vertex[9];
		
	
		if(num==1){//add more ifs here for more predefined polygons
			
			System.out.println("num==1");
			for(int j=0; j < poly1.length;j++){
			temp2[j][0]=poly1[j][0];
			temp2[j][1]=poly1[j][1];
			temp2[j][2]=poly1[j][2];
			}
			
			v0 = new Vertex(temp2[0],"+",0);
			v1 = new Vertex(temp2[1],"+",0);		
			v2 = new Vertex(temp2[2],"--",0);
			v3 = new Vertex(temp2[3],"--",0);
			v4 = new Vertex(temp2[4],"+",0);
			v5 = new Vertex(temp2[5],"+",0);
			v6 = new Vertex(temp2[6],"0",0);
			v7 = new Vertex(temp2[7],"--",0);
			v8 = new Vertex(temp2[8],"--",0);
			
			l.addElement(v0);
			l.addElement(v1);
			l.addElement(v2);
			l.addElement(v3);
			l.addElement(v4);
			l.addElement(v5);
			l.addElement(v6);
			l.addElement(v7);
			l.addElement(v8);
		}//num==1
		repaint();
		
	}//method addPoly
	
	
	
	
	
	
	
	//all button events handled here
	public boolean action (Event e,Object o) {
		
		Vertex tempv;
		boolean move_success=true;
		int move_index=-1;
		
		
		if (e.target instanceof Checkbox) {
			if ( ((Checkbox) e.target).getLabel()=="Stepwise")  {
				l.step=true;   //stepwise reconfiguration
				l.start_complete=false;
				}
			if ( ((Checkbox) e.target).getLabel()=="Complete") {
				l.step=false;  //complete reconfiguration
			}
			if ( ((Checkbox) e.target).getLabel()=="Explain steps")  {
				l.textoff=!l.textoff;   //stepwise reconfiguration
				}	
			if ( ((Checkbox) e.target).getLabel()=="Initial")  {
				l.input_poly=true;//set initial polygon
				}
			if ( ((Checkbox) e.target).getLabel()=="Final") {
				l.input_poly=false;//set final polygon
			}
			return true;	
		}

		if (e.target instanceof Button) {
			if ("Close".equals((String) o)) {//indicates initial polygon is completed
				if (l.size()>2){//must have at least 3 points for a polygon
					
					l.closed=true;
					l.drawn = true;
					io.setSelectedCheckbox(c_out_pointer);
					l.input_poly=false;
					l.initial_poly = new int[l.size()][2];
					for(int i=0;i<l.size();i++){
						l.initial_poly[i][0] = ((Vertex)l.elementAt(i)).pt[0];
						l.initial_poly[i][1] = ((Vertex)l.elementAt(i)).pt[1];
					}//copy initial polygon
					l.poly_diff = new int[l.size()];
					for(int i=0; i<l.size();i++){
						l.poly_diff[i]=0;
					}//initialize labels on each vertex
					l.final_poly = new int[l.size()][2];//final polygon has same number of vertices as initial
				}
			}
			if(l.size()==0 && "Example".equals((String) o) ) {
				addPoly(1,l);
				l.drawn=true;//object on the canvas
				l.example=true;
				l.final_poly = new int[1][2];
				l.final_poly[0][0] = 0;//example initializer
				l.final_poly[0][1] = 0;
				}//draw polygon button
				
			if ("Clear".equals((String) o) ) {
				l.removeAllElements();
				l.reconfigure=false;
				l.end=false;
				l.closed=false;
				l.drawn=false;
				l.flex_num=0;
				l.example=false;
				l.selected[0]=-1;
				l.selected[1]=-1;
				l.selected[2]=-1;
				l.selected[3]=-1;
				io.setSelectedCheckbox(c_in_pointer);
				l.input_poly=true;
				l.dist_modifier=0;
				for(int i=0;i<9;i++){
					l.flex_check[i] = false;
				}
				l.initial_poly=null;
				l.final_poly=null;
				l.moves=null;
				l.poly_diff=null;
			}//clear button
				
			if ("+".equals((String) o)){
				boolean move_point_result=false;
				
				if(l.drawn && !l.example && allselected() && !l.input_poly){
					int[] backup = new int[l.size()*2];//keep backup points
					
					for(int k=0;k<l.size();k++){
						tempv=(Vertex)l.elementAt(k);
						backup[2*k]=tempv.pt[0];
						backup[2*k+1]=tempv.pt[1];
					}//store points before move
					
					move_point_result = move_point(-5);//move
					
					for(int i=0;i<l.size();i++){					
						tempv = (Vertex)l.elementAt(i);
						if(!move_point_result || tempv.pt[0]<1 || tempv.pt[0]>550 || tempv.pt[1]<1 || tempv.pt[1]>494){
							for(int j=0; j<l.size();j++){
								
								tempv=(Vertex)l.elementAt(j);
								tempv.pt[0]=backup[2*j];
								tempv.pt[1]=backup[2*j+1];
							}//reset points
							move_success = false;//set failure flag;
							if(move_point_result) l.dist_modifier+=5;
							break;
						}//check boundaries and reset points if they are violated
					}//for every vertex in the polygon
					if(move_success){//we have made a valid move and update vertices
						l.poly_diff[l.selected[1]]-=5;
						//check if similar move has been made
						move_index = check_moves(l.selected[0],l.selected[1],l.selected[2],l.selected[3]);
						System.out.println("Checked");
						if(move_index!=-1){//if a similar one exists, update it
							System.out.println("Updated"+ move_index);
							((int[])l.moves.elementAt(move_index))[4]-=5;
						}
						else{//or add the new move
							System.out.println("else");
							int[] m = {l.selected[0],l.selected[1],l.selected[2],l.selected[3], -5};
							l.moves.addElement(m);	
						}
					}
				}
				
			}
			if ("++".equals((String) o)){
				
				boolean move_point_result=false;
				
				if(l.drawn && !l.example && allselected() && !l.input_poly){
					int[] backup = new int[l.size()*2];//keep backup points
					
					for(int k=0;k<l.size();k++){
						tempv=(Vertex)l.elementAt(k);
						backup[2*k]=tempv.pt[0];
						backup[2*k+1]=tempv.pt[1];
					}//store points before move

					move_point_result=move_point(-35);
					for(int i=0;i<l.size();i++){					
						tempv = (Vertex)l.elementAt(i);
						if(!move_point_result || tempv.pt[0]<1 || tempv.pt[0]>550 || tempv.pt[1]<1 || tempv.pt[1]>494){
							for(int j=0; j<l.size();j++){
								
								tempv=(Vertex)l.elementAt(j);
								tempv.pt[0]=backup[2*j];
								tempv.pt[1]=backup[2*j+1];
							}//reset points
							move_success=false;//set failure flag
							if(move_point_result) l.dist_modifier+=35;
							break;
						}//check boundaries and reset points if they are violated
					}//for every vertex in the polygon
					if(move_success){//we have made a valid move and update vertices
						l.poly_diff[l.selected[1]]-=35;
						System.out.println("IN");
						move_index = check_moves(l.selected[0],l.selected[1],l.selected[2],l.selected[3]);
						if(move_index!=-1){//if a similar one exists, update it
							((int[])l.moves.elementAt(move_index))[4]-=35;
							System.out.println("Updated"+ move_index);
						}
						else{//or add the new move
							int[] m = {l.selected[0],l.selected[1],l.selected[2],l.selected[3], -5};
							l.moves.addElement(m);	
						}

					}

				}
			}//larger increments

			
			if ("-".equals((String) o)){
				
				if(l.drawn && !l.example && allselected() && !l.input_poly){
					boolean move_point_result=false;
					int[] backup = new int[l.size()*2];//keep backup points
					
					for(int k=0;k<l.size();k++){
						tempv=(Vertex)l.elementAt(k);
						backup[2*k]=tempv.pt[0];
						backup[2*k+1]=tempv.pt[1];
					}//store points before move

					move_point_result=move_point(5);
					for(int i=0;i<l.size();i++){					
						tempv = (Vertex)l.elementAt(i);
						if(!move_point_result ||tempv.pt[0]<1 || tempv.pt[0]>550 || tempv.pt[1]<1 || tempv.pt[1]>494){
							for(int j=0; j<l.size();j++){
								
								tempv=(Vertex)l.elementAt(j);
								tempv.pt[0]=backup[2*j];
								tempv.pt[1]=backup[2*j+1];
							}//reset points
							move_success=false;//set failure flag
							if(move_point_result)l.dist_modifier-=5;
							break;
						}//check boundaries and reset points if they are violated
					}//for every vertex in the polygon
					if(move_success){//we have made a valid move and update vertices
						l.poly_diff[l.selected[1]]+=5;
						move_index = check_moves(l.selected[0],l.selected[1],l.selected[2],l.selected[3]);
						if(move_index!=-1){//if a similar one exists, update it
							((int[])l.moves.elementAt(move_index))[4]+=5;
							System.out.println("Updated"+ move_index);
						}
						else{//or add the new move
							int[] m = {l.selected[0],l.selected[1],l.selected[2],l.selected[3], -5};
							l.moves.addElement(m);	
						}

					}
				}
			}
			if ("--".equals((String) o)){
				boolean move_point_result=false;
				if(l.drawn && !l.example && allselected() && !l.input_poly){
					
					int[] backup = new int[l.size()*2];//keep backup points
					
					for(int k=0;k<l.size();k++){
						tempv=(Vertex)l.elementAt(k);
						backup[2*k]=tempv.pt[0];
						backup[2*k+1]=tempv.pt[1];
					}//store points before move

					move_point_result=move_point(35);
					for(int i=0;i<l.size();i++){					
						tempv = (Vertex)l.elementAt(i);
						if(!move_point_result || tempv.pt[0]<1 || tempv.pt[0]>550 || tempv.pt[1]<1 || tempv.pt[1]>494){
							for(int j=0; j<l.size();j++){
								
								tempv=(Vertex)l.elementAt(j);
								tempv.pt[0]=backup[2*j];
								tempv.pt[1]=backup[2*j+1];

							}//reset points
							move_success=false;//set failure flag
							if(move_point_result)l.dist_modifier-=35;
							break;
						}//check boundaries and reset points if they are violated
					}//for every vertex in the polygon
					if(move_success){//otherwise we have made a valid move and update vertices
						l.poly_diff[l.selected[1]]+=35;
						move_index = check_moves(l.selected[0],l.selected[1],l.selected[2],l.selected[3]);
						if(move_index!=-1){//if a similar one exists, update it
							((int[])l.moves.elementAt(move_index))[4]+=35;
							System.out.println("Updated"+ move_index);
						}
						else{//or add the new move
							int[] m = {l.selected[0],l.selected[1],l.selected[2],l.selected[3], -5};
							l.moves.addElement(m);								
						}

					}
				}
			}
			if ("Reconfigure".equals((String) o)){
				
				if(!l.end && l.drawn && l.example){//object on canvas and not done reconfiguring
				       
					if(!l.example){//set the final polygon before reconfiguring user input
						l.final_poly= new int[l.size()][2];
						for(int i=0; i<l.size();i++){
							l.final_poly[i][0] = ((Vertex)l.elementAt(i)).pt[0];
							l.final_poly[i][1] = ((Vertex)l.elementAt(i)).pt[1];
						}//set final polygon coordinates
					}
					
					if(l.step){//stewise reconfiguration
						if(l.reconfigure){
							l.flex_num++;
						}
						else{//initial click
							l.reconfigure=true;
							
						}
					}
					else if(!l.start_complete && l.drawn){//complete reconfiguration
						l.start_complete=true; //only initial click sets flags
						l.reconfigure=true;
					}
				}	
			}//reconfigure button
	
		graph.repaint();
		return true;
		}
		return false;
	}//method action

	
	public int check_moves(int a, int b, int c, int d){
		int[] mov = new int[5];
		if(l.moves==null)return -1;
		if(l.moves.size()==0) return -1;//empty case
		else{
			
			for(int i=0; i<l.moves.size();i++){
				mov =((int[])l.moves.elementAt(i));
				System.out.println("i2: "+i);
				if(mov[0]==a && mov[1]==b && mov[2]==c && mov[3]==d)return i;
				
			}//check moves for identical ones
			return -1;
		}
		
		
	}//method check_moves
	
	
	//takes in the selected
	public boolean allselected(){
	
			if(l.selected[0]!=-1 && l.selected[1]!=-1 && l.selected[2]!=-1 && l.selected[3]!=-1)
				return true;
			else return false;
	}//method allselected
	
	
	
	
	
 /* move_point moves the second explicit vertex, and all others follow		     *
	* The Law of Cosines is used in this function to determine the position          *
	*	of implicit points after the move of the second explicit point.  The polygonal *
	*	subchains follow as rotations after the implicit point's position is found     *
	*					c*c = a*a + b*b -2*a*b*cos(C),                                         *
	*																 where C is the angle opposite side c.           */
	public boolean move_point(int dist){
		
		int x_new, y_new;//setting explicit point
		double a, b, c, d, e, diff_x, diff_y;//sides in Law of Cosines
		double B, BOriginal, C, COriginal, E, EOriginal, D, DOriginal;//angles
		double magnitude;
		Vertex changer, fixed_vert, moving_vert, imp_vert;
		double[] unit_vector= {-1.0,-1.0};
		int[] rot_coords;
		int[] old_moving_vert = new int[2];
		l.dist_modifier+=dist;
		//use magnitude in creating normal vector
		magnitude = Math.sqrt(l.initial_slope_xy[0]*l.initial_slope_xy[0] + l.initial_slope_xy[1]*l.initial_slope_xy[1]);
		
		//calculate unit vector
		unit_vector[0] = ((double)l.initial_slope_xy[0])/magnitude;
		unit_vector[1] = ((double)l.initial_slope_xy[1])/magnitude;

		//the new coordinates will be a vector added to the fixed point
		x_new = (int)((double)l.dist_modifier*unit_vector[0]) + l.initial_slope_xy[0];
		y_new = (int)((double)l.dist_modifier*unit_vector[1]) + l.initial_slope_xy[1];
			
		//calculate the lengths of all sides but a before explicit point is moved 
		fixed_vert = (Vertex)l.elementAt(l.selected[0]);
		moving_vert = (Vertex)l.elementAt(l.selected[1]);
		old_moving_vert[0] = moving_vert.pt[0];
		old_moving_vert[1] = moving_vert.pt[1];
		imp_vert = (Vertex)l.elementAt(l.selected[2]);
		
		//compute side lengths before point is moved because we want to preserve the lengths of c and e
		
		diff_x = moving_vert.pt[0] - fixed_vert.pt[0];
		diff_y = moving_vert.pt[1] - fixed_vert.pt[1];
		a = Math.sqrt(diff_x*diff_x + diff_y*diff_y);//initial length of side a
		
		diff_x = imp_vert.pt[0] - fixed_vert.pt[0];
		diff_y = imp_vert.pt[1] - fixed_vert.pt[1];
		b = Math.sqrt(diff_x*diff_x + diff_y*diff_y);//edge from fixed point to left implicit
		
		diff_x = moving_vert.pt[0] - imp_vert.pt[0];
		diff_y = moving_vert.pt[1] - imp_vert.pt[1];
		c = Math.sqrt(diff_x*diff_x + diff_y*diff_y);//edge from left implicit to moving
		
		
		//calculate original angles of B and C
		BOriginal = Math.acos((b*b - a*a - c*c)/( -2.0*a*c));//used for second left subchain
		COriginal= Math.acos((c*c - a*a - b*b)/( -2.0*a*b));//used for first left subchain
		
		//now calculate the edges for "right" implicit point
		imp_vert = (Vertex)l.elementAt(l.selected[3]);
	
		diff_x = imp_vert.pt[0] - fixed_vert.pt[0];
		diff_y = imp_vert.pt[1] - fixed_vert.pt[1];
		d = Math.sqrt(diff_x*diff_x + diff_y*diff_y);//edge from fixed point to right implicit
		
		diff_x = moving_vert.pt[0] - imp_vert.pt[0];
		diff_y = moving_vert.pt[1] - imp_vert.pt[1];
		e = Math.sqrt(diff_x*diff_x + diff_y*diff_y);//edge from right implicit to moving
		
		//calculate original angles of D and E
		DOriginal = Math.acos((d*d - a*a - e*e)/( -2.0*a*e));
		EOriginal= Math.acos((e*e - a*a - d*d)/( -2.0*a*d));

		//now set the new explicit point's coordinates
		changer = (Vertex)l.elementAt(l.selected[1]);
		changer.pt[0] = x_new + ((Vertex)l.elementAt(l.selected[0])).pt[0];
		changer.pt[1] = y_new + ((Vertex)l.elementAt(l.selected[0])).pt[1];
    
		//calculate the coordinates of the implicit point on the "left" (l.sel[2]) using Law of Cosines 
		diff_x = moving_vert.pt[0] - fixed_vert.pt[0];
		diff_y = moving_vert.pt[1] - fixed_vert.pt[1];
		a = Math.sqrt(diff_x*diff_x + diff_y*diff_y);
		
		//now use law of cosines to determine angle C using: c*c = a*a + b*b -2*a*b*cos(C)
		B = Math.acos((b*b - a*a - c*c)/( -2.0*a*c));
		C = Math.acos((c*c - a*a - b*b)/( -2.0*a*b));
		
		
		//compute the point along a that is distance b from the fixed point
		x_new = (int)(b*unit_vector[0]) + fixed_vert.pt[0];
		y_new = (int)(b*unit_vector[1]) + fixed_vert.pt[1];

		
		
		if(C==C && B==B){//check that rotation angle is a number
			
			//rotate the point according to our angle to find the new implicit point
			rot_coords = rotatePoint(x_new - fixed_vert.pt[0], y_new - fixed_vert.pt[1],-C);
			((Vertex)l.elementAt(l.selected[2])).pt[0]=rot_coords[0] + fixed_vert.pt[0];
			((Vertex)l.elementAt(l.selected[2])).pt[1]=rot_coords[1] + fixed_vert.pt[1];
			
			//rotate the first left subchain
			for(int i=(l.selected[0]+1)%l.size(); i!=l.selected[2];i=(i+1)%l.size()){
			
				//compute distance d from fixed point to point
				diff_x=((Vertex)l.elementAt(i)).pt[0]- fixed_vert.pt[0];
				diff_y=((Vertex)l.elementAt(i)).pt[1]- fixed_vert.pt[1];
			
				//rotate the point according to our angle to find the new implicit point
				rot_coords = rotatePoint((int)diff_x, (int)diff_y, COriginal - C);
				((Vertex)l.elementAt(i)).pt[0]=rot_coords[0] + fixed_vert.pt[0];
				((Vertex)l.elementAt(i)).pt[1]=rot_coords[1] + fixed_vert.pt[1];
	
			}//rotate subchain by COriginal-C
			
			for(int i=(l.selected[2]+1)%l.size(); i!=l.selected[1];i=(i+1)%l.size()){
				//compute distance d from point to moving point
				diff_x=((Vertex)l.elementAt(i)).pt[0] - old_moving_vert[0];
				diff_y=((Vertex)l.elementAt(i)).pt[1] - old_moving_vert[1] ;
				
				//rotate the point according to our angle to find the new implicit point
				rot_coords = rotatePoint((int)diff_x, (int)diff_y, B - BOriginal);
				((Vertex)l.elementAt(i)).pt[0]=rot_coords[0] + moving_vert.pt[0];
				((Vertex)l.elementAt(i)).pt[1]=rot_coords[1] + moving_vert.pt[1];
				
			}//rotate subchain by B - BOriginal
			
		}//only if C is a number
		else{
			l.dist_modifier-=dist;
			return false;
		}//if rotation angle is NaN
		
		
		//likewise for E
		D = Math.acos((d*d - a*a - e*e)/( -2.0*a*e));
		E = Math.acos((e*e - a*a - d*d)/( -2.0*a*d));
		
		//compute the point along a that is distance d from the fixed point
		x_new = (int)(d*unit_vector[0]) + fixed_vert.pt[0];
		y_new = (int)(d*unit_vector[1]) + fixed_vert.pt[1];		
		
		if(E==E && D==D){	
			//rotate the point according to our angle to find the new implicit point
			rot_coords = rotatePoint(x_new - fixed_vert.pt[0], y_new - fixed_vert.pt[1],E);
			((Vertex)l.elementAt(l.selected[3])).pt[0]=rot_coords[0] + fixed_vert.pt[0];
			((Vertex)l.elementAt(l.selected[3])).pt[1]=rot_coords[1] + fixed_vert.pt[1];

			
			//rotate points along the right subchain
			for(int i=(l.selected[3]+1)%l.size(); i!=l.selected[0];i=(i+1)%l.size()){
				
				
				//compute distance d from fixed point to point
				diff_x=((Vertex)l.elementAt(i)).pt[0]- fixed_vert.pt[0];
				diff_y=((Vertex)l.elementAt(i)).pt[1]- fixed_vert.pt[1];
			
				//rotate the point according to our angle to find the new implicit point
				rot_coords = rotatePoint((int)diff_x, (int)diff_y,E-EOriginal);
				((Vertex)l.elementAt(i)).pt[0]=rot_coords[0] + fixed_vert.pt[0];
				((Vertex)l.elementAt(i)).pt[1]=rot_coords[1] + fixed_vert.pt[1];
	
			}//rotate subchain by E - EOriginal
			
			
			//rotate second right subchain
			for(int i=(l.selected[1]+1)%l.size(); i!=l.selected[3];i=(i+1)%l.size()){

				//compute distance d from point to moving point
				diff_x=((Vertex)l.elementAt(i)).pt[0] - old_moving_vert[0];
				diff_y=((Vertex)l.elementAt(i)).pt[1] - old_moving_vert[1];
			
				//rotate the point according to our angle to find the new implicit point
				rot_coords = rotatePoint((int)diff_x, (int)diff_y, DOriginal -D);
				((Vertex)l.elementAt(i)).pt[0]=rot_coords[0] + moving_vert.pt[0];
				((Vertex)l.elementAt(i)).pt[1]=rot_coords[1] + moving_vert.pt[1];
	
			}//rotate subchain by DOriginal-D
			
		}//if E is a number
		else{
			l.dist_modifier-=dist;
			return false;
		}//if rotation angle is NaN
		
		return true;
		
	}//method move_point
	
	
	
	
	//takes coordinates and an angle and rotates them
	public static int[] rotatePoint(int xn, int yn, double angle)
   {
      int[] new_position = {0,0};
      
      /* Set up the rotation matrix */
      double[][] rotMatrix = 
         {
            { java.lang.Math.cos(angle), -(java.lang.Math.sin(angle)) },
            { java.lang.Math.sin(angle), java.lang.Math.cos(angle) }
         };
      
      // Do the matrix multiplication of the matrix with the coordinates and round it
    
      new_position[0] = (int)java.lang.Math.round((rotMatrix[0][0]*((double)(xn))) + 
                                           (rotMatrix[0][1]*((double)(yn))));
      new_position[1] = (int)java.lang.Math.round((rotMatrix[1][0]*((double)(xn))) +
                                           (rotMatrix[1][1]*((double)(yn))));
      
      System.out.println("NEW LOC " + new_position[0] + ":" + new_position[1]);
      return new_position;   
   }
	
	
   
   
	//display coordinates of the mouse	
	public boolean mouseMove(Event e, int x, int y) {
		
		super.showStatus((String) "<"+x+","+y+">");
		repaint();
		return true;		
	}//method mouseMove
	
}//class PolyDraw






class canvasgraph extends Canvas {
		
		Poly_v l;
		/* pointers are redundant in this simple case, but they will all be included 
		 for the sake of completeness */
		Vertex firstI, firstJ, firstK, firstL; //first pointers for the quadrangle
		Vertex curI, curJ, curK, curL;         //current pointers
		Vertex lastI, lastJ, lastK, lastL;     //last pointers
		
		private long last_click = 0; //used for identifying double clicks 
		
		//defaults for colors
		final int black=0;    //background
		final int green=1;    //edges
		final int yellow=2;   //highlighted vertex
		final int red=3;      //quadrangle
	
		
		
		//canvas constructor
	public canvasgraph(Poly_v liste) {
			resize(550,550);
			l=liste;
			
		}//canvasgraph

		
		
		
	public void paint(Graphics g) {	
		
		boolean drawing = true;
		Vertex v1,v2, I, J, K, L, changeverts;
		int xmov, ymov;
		int int_lab;           //interval between labels
		int pt1[]=new int[2];
		int pt2[]=new int[3];
		int smalldif;//will be the smallest difference in angles to change

		g.setColor(Color.black);  //canvas
		g.fillRect(0,0,550,550);
		g.setColor(Color.blue);		//outline	
		g.drawRect(0,0,550,550);
		
		g.setColor(Color.green);  //default
	
		
		if(!l.example){
			
			if(!l.reconfigure){
				if(l.size()==1){ //draw the point
					pt1=((Vertex)l.firstElement()).pt;
					g.fillOval(pt1[0]-2,pt1[1]-2,4,4);
				}
				else if(l.size()>1){//or draw points and the lines
					pt1=((Vertex)l.firstElement()).pt;
					g.fillOval(pt1[0]-2,pt1[1]-2,4,4);
					for(int i=1; i<l.size();i++){
						draw(g,((Vertex)l.elementAt(i-1)).pt, ((Vertex)l.elementAt(i)).pt, green);
					}
				if(l.closed)
					draw(g,((Vertex)l.elementAt(l.size()-1)).pt, ((Vertex)l.elementAt(0)).pt, green); 
				}
				if(l.selected[0] != -1){
					System.out.println(l.selected.length);
					if(l.selected[1]==-1){
					
						g.setColor(Color.white);
						g.fillOval(((Vertex)l.elementAt(l.selected[0])).pt[0]-4,((Vertex)l.elementAt(l.selected[0])).pt[1]-4,8,8);
					}
					else{
					
						g.setColor(Color.white);
						g.fillOval(((Vertex)l.elementAt(l.selected[0])).pt[0]-4,((Vertex)l.elementAt(l.selected[0])).pt[1]-4,8,8);
						g.setColor(Color.yellow);
						g.fillOval(((Vertex)l.elementAt(l.selected[1])).pt[0]-4,((Vertex)l.elementAt(l.selected[1])).pt[1]-4,8,8);
						g.setColor(Color.orange);
						if(l.selected[2]!=-1){
							g.fillOval(((Vertex)l.elementAt(l.selected[2])).pt[0]-3,((Vertex)l.elementAt(l.selected[2])).pt[1]-3,6,6);
						}
						if(l.selected[3]!=-1){
							g.fillOval(((Vertex)l.elementAt(l.selected[3])).pt[0]-3,((Vertex)l.elementAt(l.selected[3])).pt[1]-3,6,6);
						}

					}
				}//if
			}//!reconfigure represents the initial entering of the polygon
			
			else{//we start to reconfigure given the input
				
				while(!l.end){//keep reconfiguring until we are done
				
				//draw the initial polygon
				for(int i=0; i<(l.size()-1);i++){
					draw(g, l.initial_poly[i], l.initial_poly[i+1], green);
				}
				draw(g, l.initial_poly[l.size()-1], l.initial_poly[0], green);
					
				
					
					
					
					
					
					
				}
				
				
				
				
				
				
				
				
			}
		}
		
		//example reconfiguration
		if(l.drawn && l.example){ 
			
			if(l.reconfigure && l.flex_num >= 0){
				
				switch(l.flex_num){
						
					case 0:
						
						//set each of the sets' first element
						
						I = (Vertex)l.elementAt(0);
						J = (Vertex)l.elementAt(2);
						K = (Vertex)l.elementAt(4);
						L = (Vertex)l.elementAt(7);

						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("Initial Quadrangle", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);
							
						}
						
						if(l.start_complete){
							l.flex_num++;
						}	
											
						break;
					case 1:
							// flex
						
						I = (Vertex)l.elementAt(0);
						J = (Vertex)l.elementAt(2);
						K = (Vertex)l.elementAt(4);
						L = (Vertex)l.elementAt(7);
					
						if(!l.flex_check[l.flex_num]){
							changeverts  = (Vertex)l.elementAt(1);
							changeverts.pt[0]+=8;
							changeverts.pt[1]+=7;
							
							changeverts  = (Vertex)l.elementAt(3);
							changeverts.pt[0]+=8;
							changeverts.pt[1]-=4;
						
							changeverts  = (Vertex)l.elementAt(5);
							changeverts.pt[0]-=0;
							changeverts.pt[1]+=2;
	
							changeverts  = (Vertex)l.elementAt(6);
							changeverts.pt[0]-=1;
							changeverts.pt[1]+=3;

							changeverts  = (Vertex)l.elementAt(8);
							changeverts.pt[0]+=5;
							changeverts.pt[1]+=7;	
						
							I.pt[0]+=13;
							I.pt[1]+=15;
							I.label="0";
						
							J.pt[0]+=7;
							J.pt[1]-=6;
						
							L.pt[0]-=7;
							L.pt[1]+=6;
						
							l.flex_check[l.flex_num] = true;
							
						}
						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("Flexing the quadrangle yields a zero label on the first vertex of I", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);

						}
						
						if(l.start_complete){
							l.flex_num++;
						}

					//	l.just_reconned=false;
						break;
					case 2:
						//show new quadrangle
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(2);
						K = (Vertex)l.elementAt(4);
						L = (Vertex)l.elementAt(7);
						
						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("New quadrangle is formed as the I-pointer advances", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);
							
						}
						
						if(l.start_complete){
							l.flex_num++;
						}

						break;
						
					case 3:
						//flex
						
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(2);
						K = (Vertex)l.elementAt(4);
						L = (Vertex)l.elementAt(7);
						if(!l.flex_check[l.flex_num]){
							changeverts  = (Vertex)l.elementAt(0);
							changeverts.pt[0]+=9;
							changeverts.pt[1]+=4;
						
							changeverts  = (Vertex)l.elementAt(3);
							changeverts.pt[0]+=5;
							changeverts.pt[1]-=5;
					
							changeverts  = (Vertex)l.elementAt(5);
							changeverts.pt[0]-=0;
							changeverts.pt[1]+=1;

							changeverts  = (Vertex)l.elementAt(6);
							changeverts.pt[0]-=1;
							changeverts.pt[1]+=3;

							changeverts  = (Vertex)l.elementAt(8);
							changeverts.pt[0]+=7;
							changeverts.pt[1]+=3;	
							
							I.pt[0]+=8;
							I.pt[1]+=4;
							
							J.pt[0]+=6;
							J.pt[1]-=6;
						
							L.pt[0]-=6;
							L.pt[1]+=6;
							l.flex_check[l.flex_num] = true;
						}
						
						J.label="0";
						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("Flexing the quadrangle yields a zero label on the J-vertex", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);	
						}
					
						if(l.start_complete){
							l.flex_num++;
						}
						
						break;
						
					case 4:
						//new quadrangle
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(3);
						K = (Vertex)l.elementAt(4);
						L = (Vertex)l.elementAt(7);
						System.out.println("4");

						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("A new quadrangle is formed with the new vertex at the head of J ", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);
						}	
							
						if(l.start_complete){
							l.flex_num++;
						}
	
						break;

					case 5:
						//flex
						
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(3);
						K = (Vertex)l.elementAt(4);
						L = (Vertex)l.elementAt(7);
						if(!l.flex_check[l.flex_num]){

							changeverts  = (Vertex)l.elementAt(0);
							changeverts.pt[0]+=9;
							changeverts.pt[1]+=4;
						
							changeverts  = (Vertex)l.elementAt(2);
							changeverts.pt[0]+=6;
							changeverts.pt[1]-=5;
					
							changeverts  = (Vertex)l.elementAt(5);
							changeverts.pt[0]-=0;
							changeverts.pt[1]+=1;

							changeverts  = (Vertex)l.elementAt(6);
							changeverts.pt[0]-=1;
							changeverts.pt[1]+=3;

							changeverts  = (Vertex)l.elementAt(8);
							changeverts.pt[0]+=7;
							changeverts.pt[1]+=3;	
						
							I.pt[0]+=8;
							I.pt[1]+=4;
						
							J.pt[0]+=7;
							J.pt[1]-=6;
						
							L.pt[0]-=7;
							L.pt[1]+=6;
							
							l.flex_check[l.flex_num] = true;
						}
						
						K.label="0";

						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("Flexing the quadrangle yields a zero label on the K-vertex", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);

						}
						if(l.start_complete){
							l.flex_num++;
						}
						
						break;
						
					case 6:
						//display new quad
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(3);
						K = (Vertex)l.elementAt(5);
						L = (Vertex)l.elementAt(7);

						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("A new quadrangle is formed with the new vertex at the head of K", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);
							
						}
						
						if(l.start_complete){
							l.flex_num++;
						}
						
						break;
						
					case 7:
						//flex
						
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(3);
						K = (Vertex)l.elementAt(5);
						L = (Vertex)l.elementAt(7);
						if(!l.flex_check[l.flex_num]){
	
							changeverts  = (Vertex)l.elementAt(0);
							changeverts.pt[0]+=2;
							changeverts.pt[1]+=1;
						
							changeverts  = (Vertex)l.elementAt(2);
							changeverts.pt[0]+=3;
							changeverts.pt[1]-=2;
					
							changeverts  = (Vertex)l.elementAt(4);
							changeverts.pt[0]-=0;
							changeverts.pt[1]+=1;

							changeverts  = (Vertex)l.elementAt(6);
							changeverts.pt[0]-=0;
							changeverts.pt[1]+=1;

							changeverts  = (Vertex)l.elementAt(8);
							changeverts.pt[0]+=2;
							changeverts.pt[1]+=1;	
				
							I.pt[0]+=0;
							I.pt[1]+=3;
						
							J.pt[0]+=3;
							J.pt[1]-=2;
						
							L.pt[0]-=3;
							L.pt[1]+=2;		
							l.flex_check[l.flex_num] = true;

						}

						L.label = "0";

						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("Flexing the quadrangle leads to a zero label on the L-vertex", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);

						}
						if(l.start_complete){
							l.flex_num++;
						}
						
						break;
						
					case 8:
						//display new quad
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(3);
						K = (Vertex)l.elementAt(5);
						L = (Vertex)l.elementAt(8);
						
						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("A quadrangle which contains the last 4 vertices to be modified is formed", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);
						}
						
						if(l.start_complete){
							l.flex_num++;
						}

						break;
						
					case 9:
						//final flex
												
						I = (Vertex)l.elementAt(1);
						J = (Vertex)l.elementAt(3);
						K = (Vertex)l.elementAt(5);
						L = (Vertex)l.elementAt(8);

						I.label = "0";
						J.label = "0";
						K.label = "0";
						L.label = "0";
						
						if(!l.end){
							l.end = true;
						}
						if(!l.textoff){
							g.setColor(Color.white);
							g.drawString("The final flex always sets 4 labels to 0", 110,450);
							g.drawString("I", I.pt[0]-10,I.pt[1]-10);
							g.drawString("J", J.pt[0]-10,J.pt[1]-10);
							g.drawString("K", K.pt[0]-10,K.pt[1]-10);
							g.drawString("L", L.pt[0]-10,L.pt[1]-10);

						}

						if(l.start_complete){
							l.start_complete=false;
						}
						
						break;
					default:
						I = (Vertex)l.elementAt(0);
						J = (Vertex)l.elementAt(2);
						K = (Vertex)l.elementAt(4);
						L = (Vertex)l.elementAt(7);
				}//switch
				
				//print out ending statement
				if(l.end){
					g.setColor(Color.orange);
					g.drawString("Final Configuration Attained", 200,50);
				}
				
				draw(g,I.pt, J.pt, red);      //draw quadrangle in red
				draw(g,J.pt, K.pt, red);
				draw(g,K.pt, L.pt, red);
				draw(g,L.pt, I.pt, red);
			}//if we are reconfiguring
			
			//draw the polygon
			v1 = (Vertex)l.elementAt(0);
			for(int i=1; i<l.size();i++){
				v2 = (Vertex)l.elementAt(i);	
				draw(g,v1.pt,v2.pt,green);//draw an edge
				v1 = v2;
			}
			v2 = (Vertex)l.elementAt(0);
			draw(g,v1.pt, v2.pt, green);
			
			drawLabels(l,g);
			if(l.start_complete){
				try{
					Thread.currentThread().sleep(1000);
					repaint();
				}
				catch(InterruptedException e){
					System.out.println("Uh-oh! EXCEPTION: " + e);
				}
			}//pause after each step
					
		}//if drawn
		
	}//method paint
	

//mouseDown lets the user add a new point on canvas if it maintains polygon's convexity
//also deals with specifying the final polygon configuration through edit points
	public boolean mouseDown(Event evt, int x, int y)
	{
		
		double mind=551.0;//minimum distance of the click to a vertex
		double tempd;
		int index = -1;//index of closest vertex to point
		Vertex dcheck, add;
		int[] temp_pt = new int[2];
		long last_click_delay;
      
    last_click_delay = Math.abs(evt.when - last_click);//time between clicks
    last_click=evt.when;

		if (x<550 && x>1 && y<550 && y>1 && !l.closed && l.input_poly && !l.example){
			
			temp_pt[0]=x;
			temp_pt[1]=y;
			add = new Vertex(temp_pt, "0", 0);
			l.addElement(add);

			if(!convex(l)){
				l.removeElement(add);//remove the point if it violates convexity
			}
		}
		else if(x<550 && x>1 && y<550 && y>1 && l.closed && !l.input_poly && !l.example){
			
			for(int i=0;i<l.size(); i++){
				
				dcheck = (Vertex)l.elementAt(i);
				
				tempd = Math.sqrt((dcheck.pt[0]-x)*(dcheck.pt[0]-x) + (dcheck.pt[1]-y)*(dcheck.pt[1]-y));
				if(tempd <= mind){
					mind = tempd;
					index = i;
				}//keep track of closest index
				
			}//get the closest Vertex to the click
			
			//now we select the vertex if it is close enough
			if(mind < 10){
					
				if(l.selected[1]== -1){//must have less than 2 selected
					
					if(l.selected[0]==-1){//add index if none are selected
						l.selected[0]=index;
					}
					else{
						if(index!=((l.selected[0]+1)%(l.size())) && index!=((l.selected[0]+l.size()-1)%(l.size()))){
							if(index != l.selected[0]){
								l.selected[1]=index;
								l.selected[2]=(index + l.size() - 1)%(l.size());
								l.selected[3]=(index+1)%(l.size());
								
								l.initial_slope_xy[0] = ((Vertex)l.elementAt(l.selected[1])).pt[0] - ((Vertex)l.elementAt(l.selected[0])).pt[0];
								l.initial_slope_xy[1] = ((Vertex)l.elementAt(l.selected[1])).pt[1] - ((Vertex)l.elementAt(l.selected[0])).pt[1];
							}
							else{
								//deselect the point when clicked on a second time
								l.selected[0]=-1;
							}
						}//disallow points next to each other, as edge lengths are static
					}//else
				}//selected not full
				
				else{//adding implicit points and deselecting when 2 points have been selected
					if(index == l.selected[0]){
						l.selected[0]=l.selected[1];//shift points
						l.selected[1]=-1;
						l.selected[2]=-1;
						l.selected[3]=-1;
						l.initial_slope_xy[0] = 0;
						l.initial_slope_xy[1] = 0;//reset slope
						l.dist_modifier=0;
					}
					//explicit point and implicit ones deselected when explicit one is double-clicked
					else if(index == l.selected[1]){
						if(last_click_delay < 250){
							l.selected[1]=-1;
							l.selected[2]=-1;
							l.selected[3]=-1;
							l.initial_slope_xy[0] = 0;
							l.initial_slope_xy[1] = 0;//reset slope
							l.dist_modifier=0;
						}
					}
					else if(index == l.selected[2]){
						l.selected[2] = -1; //deselect implicit point
					}
					else if(index == l.selected[3]){
						l.selected[3] = -1; //deselect implicit point
					}
					else if(l.selected[2]==-1 && in(index,(l.selected[0]+1)%l.size(), (l.selected[1]-1)%l.size())){
						//left side
						l.selected[2]=index;	
					}
					else if(l.selected[3]==-1 && in(index,(l.selected[1]+1)%l.size(), (l.selected[0]-1)%l.size())){
						//right side
						l.selected[3]=index;
					}
				}//else
			}
			
			//next we deal with dragging a selected vertex within convexity...time permitting
			
		}//get final configuration
		
		repaint();	
		return true;
	}//method mouseDown
	
	
	
	//checks whether an index is along a polygonal subchain
	public boolean in(int ind, int start, int end){
		
		int counter=start;//initialize the counter we will use to step along the chain
		
		while(counter!=end+1){
			if(counter==ind){
				return true;
			}
			counter++;
			counter%=l.size();
		}
		return false;
	}//method in
	
	
	
	
	
	//test for convexity in user input if this feature is implemented
	public boolean convex(Poly_v pol){
		//right now this allows all points
		boolean con = true;
		return con;
	}//method convex

	
	
	
	
	
//draws a label on each vertex of the polygon
	public void drawLabels(Poly_v p, Graphics g){
	
		Vertex vert;
		
		for(int i=0; i<l.size(); i++){
			
			vert = (Vertex)l.elementAt(i);
			if(vert.label == "0"){
				g.setColor(Color.yellow);
			}
			else g.setColor(Color.white);
			g.drawString(vert.label,vert.pt[0] + 5, vert.pt[1]);
			
		}	
	}//method drawLabels
	
	

	
	
	
 //pt2 is the point we are adding to the polygon
	public void draw(Graphics g, int[] pt,int[] pt2, int col) {
		
		g.fillOval(pt2[0]-2,pt2[1]-2,4,4); //draw the vertex
		if(col==red)
			g.setColor(Color.red);
		else
			g.setColor(Color.green);
		g.drawLine(pt[0],pt[1],pt2[0],pt2[1]);//draw the edge
		g.setColor(Color.green);
	}//method draw	
		
}//class canvasgraph
	




class Poly_v extends Vector {
	static boolean step;
	static boolean reconfigure;
	static int flex_num=0; //counter for flexing steps
	static boolean textoff;
	static boolean start_complete;
	static boolean end;
	static boolean[] flex_check={false,false,false,false,false,false,false,false,false};//bug check
	static boolean drawn; //keep track of having something on the canvas
	static boolean closed;
	static boolean input_poly;
	static boolean example;
	static int dist_modifier;//used to move from a point
	static int[] selected = {-1,-1,-1,-1};//4 selected points
  static int[][] initial_poly;//holds coordinates of initial points
  static int[][] final_poly=null;//holds coordinates of final points
  static int[] poly_diff;//difference between initial and final
  static Vector moves;//reconfigurations in int[6]
	
	/*holds the initial (x and y)slope of explicit points
	 so no cumulative error from casting when moving*/
	static int[] initial_slope_xy = {0,0};
	
}//class Poly
	
		
	
class Vertex{
	public Vertex next;				 //next pointer
	public int[] pt;         // actual point
	public String label;     // + or -
	public int difference;   // difference in angles
	
	public Vertex(int[] p, String l, int diff){
		this.pt=p;
		this.label=l;
		this.difference=diff;
	}//Vertex constructor
	
}//class Vertex
