/****************************************************

Problem Statement:Cohen Sutherland line Clipping

*****************************************************/


#include<GL/glut.h>
#include<math.h>
#include<stdio.h>
#include<iostream>
using namespace std;

void display();
float Xmin, Ymin, Xmax, Ymax, xd1, yd1, xd2, yd2;

// Initialize the Window Screen
void Init()
{
        glClearColor(1,1,1,0);
        glMatrixMode(GL_PROJECTION);
        gluOrtho2D(-400,400,-300,300);
}

// To check whether the given Co-ordinate is inside the Window Box or not
int code(float x,float y)
{
        int c=0;
        if(y>Ymax)
        {       
                c=c|8;
        }
        else if(y<Ymin)
        {
                c=c|4;
        }
        if(x>Xmax)
        {
                c=c|2;
        }
        else if(x<Xmin)
           {
                c=c|1;
           }               
        return c;
}

// Cohen Sutherland Line Clipping Algo
void cohenLine(float x1,float y1,float x2,float y2)
{
     int c, c1, c2;
     float x, y, xi, yi, m;
     c1=code(x1,y1);            // check whether the Co-ordinate is inside or not
     c2=code(x2,y2);            // check whether the Co-ordinate is inside or not
     m=(y2-y1)/(x2-x1);         // Calculate the slope of line    
     while((c1|c2)>0)
    {
    if(c1 & c2)
        {
                break;
        }
        xi=x1;
        yi=y1;       
        c=c1;               
        if(c==0)
        {
           c=c2;
            xi=x2;
            yi=y2;
        }               
        if(c & 8)
        {
           y=Ymax;
            x=xi+1.0*(Ymax-yi)/m;
        }
        else if(c & 4)
        {
           y=Ymin;
            x=xi+1.0*(Ymin-yi)/m;
        }
        else if(c & 2)
        {
           x=Xmax;
            y=yi+m*(Xmax-xi);
        }
        else if(c & 1)
        {
           x=Xmin;
            y=yi+m*(Xmin-xi);
        }
        if(c==c1)
        {
           xd1=x;
            yd1=y;
            c1=code(xd1,yd1);
        }
        if(c==c2)
        {
           xd2=x;
            yd2=y;
            c2=code(xd2,yd2);
        }
        cout<<"Line accepted: ("<<xd1<<","<<yd1<<"), ("<<xd2<<","<<yd2<<")\n";
     }
    display();
}

// Clip the line when user press "c"
void clip(unsigned char key, int x, int y)
{
     if(key=='c' || key=='C')
    {
        cohenLine(xd1,yd1,xd2,yd2);
        glFlush();
    }
}

// display the final output
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.0,0.0,0.0);          // Black colour window box
   
    glBegin(GL_LINE_LOOP);      // drawing Window Box
    glVertex2i(Xmin,Ymin);
    glVertex2i(Xmin,Ymax);
    glVertex2i(Xmax,Ymax);
    glVertex2i(Xmax,Ymin);
    glEnd();  
       
    glColor3f(1.0,0.0,0.0);          //Red colour for line
    glBegin(GL_LINES);               // drawing the line
    glVertex2i(xd1,yd1);
    glVertex2i(xd2,yd2);
    glEnd();
    glFlush();
}

// Main function definintion
int main(int argc,char **argv)
{
    cout<<"\n\tENTER 'c' TO CLIP LINE";   
    cout<<"\n-----------------------------------------\n";
    cout<<"\nEnter the Window Co-ordinates";
    cout<<"\nBottom left point";
    cout<<"\n\tEnter the X Co-ordinate: ";
    cin>>Xmin;
    cout<<"\tEnter the Y Co-ordinate: ";
    cin>>Ymin;
    cout<<"\nTop right point";
    cout<<"\n\tEnter the X Co-ordinate: ";
    cin>>Xmax;
    cout<<"\tEnter the Y Co-ordinate: ";
    cin>>Ymax;
    cout<<"\nCreated a Window of dimension: "<<"("<<Xmin<<","<<Ymax<<"), ("<<Xmax<<","<<Ymax<<")";
    cout<<"\n\t\t\t\t"<<"("<<Xmin<<","<<Ymin<<"), ("<<Xmax<<","<<Ymin<<")";
    cout<<"\nEnter line coordinates";
    cout<<"\nFirst point";
    cout<<"\n\tEnter the X Co-ordinate: ";
    cin>>xd1;
    cout<<"\tEnter the Y Co-ordinate: ";
    cin>>yd1;
    cout<<"\nSecond point";
    cout<<"\n\tEnter the X Co-ordinate: ";
    cin>>xd2;
    cout<<"\tEnter the Y Co-ordinate: ";
    cin>>yd2;          
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(800,600);
    glutInitWindowPosition(0,0);       
    glutCreateWindow("Cohen-Sutherland Line Clipping Algo");   
    glutDisplayFunc(display);
    glutKeyboardFunc(clip);
    Init();
    glutMainLoop();   
    return 0;
}