En blanc, le rectangle de clipping, en bleu le segment complet, en rouge le segment clippé.
#include <windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <stdio.h> #include <stdlib.h> #include <math.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 fenetre ; static int height ; static int mouvement = 0 ; static int button = 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 }; glColor3f(1.0f,1.0f,1.0f); traceRectangle(&r); glColor3f(0.0f,0.0f,1.0f); traceSegment(&s); glColor3f(1.0f,0.0f,0.0f); printf("(%d,%d) et (%d,%d)\n",s.pi.x,s.pi.y,s.pf.x,s.pf.y); clippingRecursif(&s,&r); glPopMatrix(); glFlush(); glutSwapBuffers() ; } static 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 ; } glutPostWindowRedisplay(fenetre); } 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 ; } glutPostWindowRedisplay(fenetre); } } static void motion(int x,int y) { switch ( button ) { case GLUT_LEFT_BUTTON : if ( mouvement == 1 ) { s.pi.x = x ; s.pi.y = height-y ; glutPostWindowRedisplay(fenetre); } break; case GLUT_RIGHT_BUTTON : if ( mouvement == 1 ) { s.pf.x = x ; s.pf.y = height-y ; glutPostWindowRedisplay(fenetre); } } } 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 CALLBACK init() { glShadeModel(GL_SMOOTH); glClearColor(0.8F,0.8F,0.8F,1.0F); } void main(void) { glutInitWindowSize(300,300); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); fenetre = glutCreateWindow("Clipping recursif"); glutMotionFunc(motion); glutMouseFunc(souris); glutDisplayFunc(display); init(); glutReshapeFunc(reshape); glutMainLoop(); }
RETOUR