
/* Auteur: Nicolas JANEY         */
    /* nicolas.janey@univ-fcomte.fr  */
    /* Avril 2002                    */
    /* Clipping 2D                   */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include <GL/glut.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    
    #include "ModuleCouleurs.h"
    #include "ModuleMenus.h"
    #include "ModuleReshape.h"
    
    struct point {
      int x ;
      int y ; } ;
    
    struct segment {
      point pi ;
      point pf ; } ;
    
    struct rectangle {
      point sg ;
      point id ; } ;
    
    static int aff = 0 ;
    static segment s1 = { 2,10,27,19 } ;
    static segment s2 = { 5,9,28,4 } ;
    static int disc = 1 ;
    
    void pixel(int x,int y,float *c) {
      glColor4fv(c) ;
      glBegin(GL_QUADS) ;
      glVertex2f(x-1.0F,y-1.0F) ;
      glVertex2f(x-1.0F,y) ;
      glVertex2f(x,y) ;
      glVertex2f(x,y-1.0F) ;
      glEnd() ;
    }
    
    void pixelClip(rectangle *r,int x,int y,float *c) {
      if ( ( x >= r->sg.x ) && ( y >= r->sg.y ) && ( x <= r->id.x ) && ( y <= r->id.y ) )
        pixel(x,y,c) ;
    }
    
    void line(int xi,int yi,int xf,int yf,float *c) {
      int dx,dy,i,xinc,yinc,cumul,x,y ;
      x = xi ;
      y = yi ;
      dx = xf - xi ;
      dy = yf - yi ;
      xinc = ( dx > 0 ) ? 1 : -1 ;
      yinc = ( dy > 0 ) ? 1 : -1 ;
      dx = abs(dx) ;
      dy = abs(dy) ;
      pixel(x,y,c) ;
      if ( dx > dy ) {
        cumul = dx / 2 ;
        for ( i = 1 ; i <= dx ; i++ ) {
          x += xinc ;
          cumul += dy ;
          if (cumul >= dx) {
            cumul -= dx ;
            y += yinc ; }
          pixel(x,y,c) ; } }
        else {
        cumul = dy / 2 ;
        for ( i = 1 ; i <= dy ; i++ ) {
          y += yinc ;
          cumul += dx ;
          if ( cumul >= dy ) {
            cumul -= dy ;
            x += xinc ; }
          pixel(x,y,c) ; } }
    }
    
    void traceRectangle(rectangle *r,float *c) {
      line(r->id.x,r->id.y-1,r->id.x,r->sg.y+1,c) ;
      line(r->id.x,r->sg.y,r->sg.x,r->sg.y,c) ;
      line(r->id.x,r->id.y,r->sg.x,r->id.y,c) ;
      line(r->sg.x,r->id.y-1,r->sg.x,r->sg.y+1,c) ;
    }
    
    void clipperSegment(rectangle *r,int xi,int yi,int xf,int yf,float *c) {
      int dx,dy,i,xinc,yinc,cumul,x,y ;
      x = xi ;
      y = yi ;
      dx = xf - xi ;
      dy = yf - yi ;
      xinc = ( dx > 0 ) ? 1 : -1 ;
      yinc = ( dy > 0 ) ? 1 : -1 ;
      dx = abs(dx) ;
      dy = abs(dy) ;
      pixelClip(r,x,y,c) ;
      if ( dx > dy ) {
        cumul = dx / 2 ;
        for ( i = 1 ; i <= dx ; i++ ) {
          x += xinc ;
          cumul += dy ;
          if (cumul >= dx) {
            cumul -= dx ;
            y += yinc ; }
          pixelClip(r,x,y,c) ; } }
        else {
        cumul = dy / 2 ;
        for ( i = 1 ; i <= dy ; i++ ) {
          y += yinc ;
          cumul += dx ;
          if ( cumul >= dy ) {
            cumul -= dy ;
            x += xinc ; }
          pixelClip(r,x,y,c) ; } }
    }
    
    void dessineQuadrillage(void) {
      float i;
      glColor4fv(couleurGrisMoyen()) ;
      glBegin(GL_LINES);
      for ( i = 0 ; i <= 30 ; i++ ) {
        glVertex3d(i,0,-10.0);
        glVertex3d(i,20,-10.0); }
      for ( i = 0 ; i <= 20 ; i++ ) {
        glVertex3d(0,i,-10.0);
        glVertex3d(30,i,-10.0); }
      glEnd() ;
    }
    
    void display() {
      rectangle r = { 6,5,26,15 } ;
      glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
      glPushMatrix();
      dessineQuadrillage();
      traceRectangle(&r,couleurRouge(0.6F));
      switch ( aff) {
        case 1 : line(s1.pi.x,s1.pi.y,s1.pf.x,s1.pf.y,couleurBleu(0.5));
                 line(s2.pi.x,s2.pi.y,s2.pf.x,s2.pf.y,couleurVertFonce(0.5));
                 break ;
        case 2 : line(s1.pi.x,s1.pi.y,s1.pf.x,s1.pf.y,couleurBleu(0.3));
                 line(s2.pi.x,s2.pi.y,s2.pf.x,s2.pf.y,couleurVertFonce(0.3));
                 clipperSegment(&r,s1.pi.x,s1.pi.y,s1.pf.x,s1.pf.y,couleurBleu(0.8));
                 clipperSegment(&r,s2.pi.x,s2.pi.y,s2.pf.x,s2.pf.y,couleurVertFonce(0.8));
                 break ; }
      glPopMatrix();
      glFlush();
      glutSwapBuffers() ;
    }
    
    void key(unsigned char key,int x,int y) {
      switch ( key ) {
        case 0x0D : aff = (aff+1)%3 ;
                    glutPostRedisplay();
                    break;
        case 0x1B : exit(0);
                    break; }
    }
    
    void myinit() {
      glEnable(GL_ALPHA_TEST);
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
      glClearColor(0.8F,0.8F,0.8F,1.0F);
    }
    
    int main(int argc,char **argv) {
      glutInit(&argc,argv);
      glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
      glutInitWindowSize(375,252); 
      glutInitWindowPosition(50,50); 
      glutCreateWindow("Clipping 2D"); 
      myinit(); 
      creationMenuBasique();
      setParametresOrthoBasique(-0.5,20.5,-0.5,20.5,-50.0,50.0);
      glutReshapeFunc(reshapeOrthoBasique);
      glutKeyboardFunc(key);
      glutDisplayFunc(display);
      glutMainLoop();
      return(0);
    }