// Mark Huang <markman@mit.edu>
// MIT 6.837 Fall 1999
// Assignment 2

import display.*;

public class CohenSutherland {

    public static final int LEFT = 1;
    public static final int RIGHT = 2;
    public static final int TOP = 4;
    public static final int BOTTOM = 8;
    
    /*
      Inputs: the original line from (x1,y1) to (x2,y2), and a
      viewport The viewport object has four public instance variables,
      which can be accessed by: 
      var1 = viewport.top; 
      var2 = viewport.bottom; 
      var3 = viewport.left; 
      var4 = viewport.right;

      Output: a LineSegment object 
            You can create a LineSegment object by making the call
			      LineSegment ls = new LineSegment()

            Having created it, you must set five values: 
	    x1, y1, x2, y2    the coordinates of each of the
                              endpoints of the clipped line You set
                              these values by including the line
                              ls.setEndPoints(x1, y1, x2, y2); 
			      or alternatively, by setting each of
                              the endpoints individually: 
			      ls.x1 = x1;
                              ls.y1 = y1; 
			      etc.

	    clipType          The clip type can be set to three
	                      values:

			      "internal" if the input line segment
			      falls entirely within the clip region,
			      otherwise:

                              "clipped" if it was determined that
                              some part of the input line segment does
                              fall within the boundaries defined by the
                              clip region, otherwise:

			      "external" if NO part of the input
			      line segment falls within the clip region
			      (i.e. the entire line was clipped.)
                              
			      You can set these values by including
			      the java statements:
                                    ls.setClipType("internal");
			      OR
                                    ls.setClipType("clipped");
                              OR
                                    ls.setClipType("external");
    
	NOTE: If you want to have any auxiliary methods (helpers), you
	must make sure to declare them "static" as well.
    */

    public static LineSegment ClipSegment(double x1, double y1, 
				       double x2, double y2, 
				       Viewport vp) {

	// ******* YOUR CODE HERE *********

	LineSegment ls = new LineSegment();
	int o1, o2, i = 0;

	ls.x1 = x1;
	ls.y1 = y1;
	ls.x2 = x2;
	ls.y2 = y2;
	ls.setClipType("internal"); // Internal by default

	// Recalculate outcodes
	while (((o1 = outcode(ls.x1,ls.y1,vp.top,vp.bottom,vp.left,vp.right)) |
		(o2 = outcode(ls.x2,ls.y2,vp.top,vp.bottom,vp.left,vp.right)))
	       != 0) {
	    // Reject if both endpoints are outside the same side
	    if ((o1 & o2) != 0) {
		ls.setClipType("external");
		return ls;
	    }		
	    // Alternate between checking L/R and T/B
	    if (i++%2 == 0) {
		if ((o1 & LEFT)   != 0) ls.x1 = vp.left; 
		if ((o2 & LEFT)   != 0) ls.x2 = vp.left;
		if ((o1 & RIGHT)  != 0) ls.x1 = vp.right;  
		if ((o2 & RIGHT)  != 0) ls.x2 = vp.right;
		ls.y1 = (ls.x1-x1)*(y2-y1)/(x2-x1)+y1; // Recalculate y1
		ls.y2 = (ls.x2-x2)*(y2-y1)/(x2-x1)+y2; // Recalculate y2
	    } else {
		if ((o1 & TOP)    != 0) ls.y1 = vp.top;   
		if ((o2 & TOP)    != 0) ls.y2 = vp.top;
		if ((o1 & BOTTOM) != 0) ls.y1 = vp.bottom; 
		if ((o2 & BOTTOM) != 0) ls.y2 = vp.bottom;
		ls.x1 = (ls.y1-y1)*(x2-x1)/(y2-y1)+x1; // Recalculate x1
		ls.x2 = (ls.y2-y2)*(x2-x1)/(y2-y1)+x2; // Recalculate x2
	    }
	    ls.setClipType("clipped");
	}

	return ls;
    }

    /*
      This method, given a point (x,y) and some clip region
      boundaries, should produce the binary clip codes for the
      Cohen-Sutherland algorithm.  
    */
    public static int outcode(double x, double y,
			      double top, double bottom, 
			      double left, double right) {

	return ((x < left) ? LEFT : 0) |
	       ((x > right) ? RIGHT : 0) |
	       ((y > top) ? TOP : 0) |
	       ((y < bottom) ? BOTTOM : 0);
    }	

    /*
    public static void main(String[] args) {
	try {
	    LineSegment ls = 
		ClipSegment(Integer.parseInt(args[0]), 
			    Integer.parseInt(args[1]), 
			    Integer.parseInt(args[2]), 
			    Integer.parseInt(args[3]),
			    new Viewport(Integer.parseInt(args[4]), 
					 Integer.parseInt(args[5]), 
					 Integer.parseInt(args[6]), 
					 Integer.parseInt(args[7])));
	} catch (ArrayIndexOutOfBoundsException e) {
	    System.err.println("Usage: java CohenSutherland [x1] [y1] [x2] [y2][top] [bottom] [left] [right]");
	}

	System.exit(0);
    }
    */
}




