En blanc, le rectangle de clipping, en bleu le segment complet, en rouge le segment clippé.
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Avril 2001 */
/* Une fonction de clipping recursive */
#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"
typedef struct Point2D {
int x;
int y; } Point2D ;
typedef struct Segment {
Point2D pi;
Point2D pf; } Segment ;
typedef struct MyRectangle {
int xmin;
int ymin;
int xmax;
int ymax; } MyRectangle ;
static int height ;
static int mouvement = 0 ;
static int button = 0 ;
static int ext = 0 ;
static Segment s = { {10,50},{270,180} };
int code(Point2D *p,MyRectangle *r) {
int res = 0x0000;
if ( p->x < r->xmin ) res |= 0x0001;
if ( p->x > r->xmax ) res |= 0x0010;
if ( p->y < r->ymin ) res |= 0x0100;
if ( p->y > r->ymax ) res |= 0x1000;
return(res);
}
int adjacents(Point2D *p1,Point2D *p2) {
if ( ( abs(p1->x-p2->x) <=1 ) && ( abs(p1->y-p2->y) <=1 ) )
return(1);
return(0);
}
void traceRectangle(MyRectangle *r) {
glBegin(GL_LINE_LOOP);
glVertex2i(r->xmin,r->ymin);
glVertex2i(r->xmax,r->ymin);
glVertex2i(r->xmax,r->ymax);
glVertex2i(r->xmin,r->ymax);
glEnd();
}
void traceSegment(Segment *s) {
glBegin(GL_LINES);
glVertex2i(s->pi.x,s->pi.y);
glVertex2i(s->pf.x,s->pf.y);
glEnd();
}
void clippingRecursif(Segment *s,MyRectangle *r) {
int cpi = code(&s->pi,r);
int cpf = code(&s->pf,r);
//printf("%04x %04x\n",cpi,cpf);
if ( ( cpi == 0 ) && ( cpf == 0 ) ) {
traceSegment(s);
//printf("Trace entre (%d,%d) et (%d,%d)\n",s->pi.x,s->pi.y,s->pf.x,s->pf.y);
return; }
if ( (cpi&cpf) != 0 ) {
//printf("Ne trace pas\n");
return; }
//printf("Decompose entre (%d,%d) et (%d,%d)\n",s->pi.x,s->pi.y,s->pf.x,s->pf.y);
if ( adjacents(&s->pi,&s->pf) ) {
Segment s1 = { { s->pi.x,s->pi.y } , { s->pi.x,s->pi.y } };
Segment s2 = { { s->pf.x,s->pf.y } , { s->pf.x,s->pf.y } };
clippingRecursif(&s2,r);
clippingRecursif(&s1,r);}
else {
int x = (s->pi.x+s->pf.x)/2;
int y = (s->pi.y+s->pf.y)/2;
Segment s1 = { { s->pi.x,s->pi.y } , { x,y } };
Segment s2 = { { x,y } , { s->pf.x,s->pf.y } };
clippingRecursif(&s2,r);
clippingRecursif(&s1,r);}
}
void display() {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
MyRectangle r = { 80,60,240,200 };
glColor4fv(couleurBlanc());
traceRectangle(&r);
glColor4fv(couleurBleu());
traceSegment(&s);
glColor4fv(couleurRouge());
clippingRecursif(&s,&r);
glPopMatrix();
glFlush();
glutSwapBuffers() ;
}
void souris(int bouton,int etat,int x,int y) {
button = bouton;
if ( bouton == GLUT_LEFT_BUTTON ) {
s.pi.x = x ;
s.pi.y = height-y ;
if ( etat == GLUT_DOWN ) {
mouvement = 1 ;}
if ( etat == GLUT_UP ) {
mouvement = 0 ; }
glutPostRedisplay(); }
if ( bouton == GLUT_RIGHT_BUTTON ) {
s.pf.x = x ;
s.pf.y = height-y ;
if ( etat == GLUT_DOWN ) {
mouvement = 1 ;}
if ( etat == GLUT_UP ) {
mouvement = 0 ; }
glutPostRedisplay(); }
}
void motion(int x,int y) {
switch ( button ) {
case GLUT_LEFT_BUTTON : if ( mouvement == 1 ) {
s.pi.x = x ;
s.pi.y = height-y ;
glutPostRedisplay(); }
break;
case GLUT_RIGHT_BUTTON : if ( mouvement == 1 ) {
s.pf.x = x ;
s.pf.y = height-y ;
glutPostRedisplay(); } }
}
void reshape(int w,int h) {
glViewport(0,0,w,h);
height = h ;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,w,0,h,-40.0,40.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void init() {
glShadeModel(GL_SMOOTH);
glClearColor(0.8F,0.8F,0.8F,1.0F);
}
void key(unsigned char key,int x,int y) {
switch ( key ) {
case 0x0D : ext = 1-ext ;
glutPostRedisplay();
break;
case '\033' : exit(0);
break ; }
}
void special(int k,int x,int y) {
switch (k) {
case GLUT_KEY_UP : if ( ext )
s.pi.y += 1 ;
else
s.pf.y += 1 ;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN : if ( ext )
s.pi.y -= 1 ;
else
s.pf.y -= 1 ;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT : if ( ext )
s.pi.x -= 1 ;
else
s.pf.x -= 1 ;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT : if ( ext )
s.pi.x += 1 ;
else
s.pf.x += 1 ;
glutPostRedisplay();
break; }
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitWindowSize(300,300);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutCreateWindow("Clipping recursif");
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutMotionFunc(motion);
glutMouseFunc(souris);
glutDisplayFunc(display);
init();
creationMenuBasique();
glutReshapeFunc(reshape);
glutMainLoop();
return(0);
}