/* Clipping de Cohen-Sutherland                 */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2012                                */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include "Position2D.h"
#include "Direction2D.h"
#include "Segment2D.h"
#include "Rectangle2D.h"

/* Variables et constantes globales             */

static const float blanc[]   = { 1.0F,1.0F,1.0F,1.0F };
static const float jaune[]   = { 1.0F,1.0F,0.0F,1.0F };
static const float magenta[] = { 1.0F,0.0F,1.0F,1.0F };
static const float rouge[]   = { 1.0F,0.0F,0.0F,1.0F };
static const float vert[]    = { 0.0F,0.7F,0.0F,1.0F };
static const float bleu[]    = { 0.0F,0.0F,1.0F,1.0F };

static Position2D *r1 = NULL;
static Position2D *r2 = NULL;
static Position2D *s3 = NULL;
static Position2D *s4 = NULL;

static void clean(void) {
  if ( r1 ) {
    delete(r1);
    r1 = NULL; }
  if ( r2 ) {
    delete(r2);
    r2 = NULL; }
  if ( s3 ) {
    delete(s3);
    s3 = NULL; }
  if ( s4 ) {
    delete(s4);
    s4 = NULL; }
}

/* Scene dessinee                               */

static void fond(void) {
  glColor3fv(bleu);
  int tx = (glutGet(GLUT_WINDOW_WIDTH)+10)/11;
  int ty = (glutGet(GLUT_WINDOW_HEIGHT)+10)/11;
  for ( int x = 0 ; x <= tx ; x++ )
    for ( int y = 0 ; y <= ty ; y++ ) {
      glBegin(GL_LINE_LOOP);
      glVertex2i(x*11,y*11);
      glVertex2i(x*11+10,y*11);
      glVertex2i(x*11+10,y*11+10);
      glVertex2i(x*11,y*11+10);
      glEnd(); }
}

static void scene(void) {
  s3->print();
  printf(" - ");
  s4->print();
  printf("\n");
  glColor4fv(jaune);
  Rectangle2D *r = new Rectangle2D(r1,r2);
  r->draw();
  Segment2D *s = new Segment2D(s3,s4);
  glColor4fv(rouge);
  s->draw();
  if ( s->clip(r) ) {
    glColor4fv(vert);
    s->draw(); }
  delete(s);
  delete(r);
}

/* Fonction executee lors d'un rafraichissement */
/* de la fenetre de dessin                      */

static void display(void) {
  glClearColor(0.8F,0.8F,0.8F,1.0F);
  glClear(GL_COLOR_BUFFER_BIT);
  glPushMatrix();
  fond();
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

/* Fonction executee lors d'un changement       */
/* de la taille de la fenetre OpenGL            */
/* -> Ajustement de la camera de visualisation  */

static void reshape(int x,int y) {
  glViewport(0,0,x,y); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0,x,0.0,y,-1000.0,1000.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

/* Fonction executee lors de la frappe          */
/* d'une touche du clavier                      */

static void keyboard(unsigned char key,int x,int y) {
  switch ( key ) {
    case 0x20 :
      s3->c[0] = 2+rand()%40;
      s3->c[1] = 2+rand()%24;
      s4->c[0] = 2+rand()%40;
      s4->c[1] = 2+rand()%24;
      glutPostRedisplay(); 
      break;
    case 0x1B :
      clean();
      exit(0); 
      break; }
}

/* Fonction principale                          */

int main(int argc,char **argv) {
  atexit(clean);
  r1 = new Position2D(32.0, 9.0);
  r2 = new Position2D(11.0,22.0);
  s3 = new Position2D( 9.0, 3.0);
  s4 = new Position2D(29.0,26.0);
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);
  glutInitWindowSize(480,320); 
  glutInitWindowPosition(50,50); 
  glutCreateWindow("Clipping de Cohen-Sutherland"); 
  glutKeyboardFunc(keyboard);
  glutReshapeFunc(reshape);
  glutDisplayFunc(display);
  glutMainLoop();
  return(0);
}
