Anda di halaman 1dari 7

/* Refer #include #include #include #define #define #define #define #define #define #define

to the Cohen_Sutherland algorithm in the textbook. */ <GL/glut.h> <stdio.h> <stdlib.h> X_COORDINATE 0 Y_COORDINATE 1 Z_COORDINATE 2 b0 0 b1 1 b2 2 b3 3

float xBoundaryRight, xBoundaryLeft, yBoundaryUpper, yBoundaryLower; float p1[3], p2[3], p3[3], p4[3]; /* corners of the clipping rectangle, clock-wise from top left */ float givenLineSegmentP1[3], givenLineSegmentP2[3]; float clippedLineP1[3], clippedLineP2[3]; void display (); void myInit (); int main (int argc, char **argv) { char outP1[4], outP2[4], outTemp[4]; /* b0, b1, b2 and b3 as described in th e text book. */ int i; float m, c, tempPoint[3]; printf ("Enter X-Boundary (right): "); scanf ("%f", &xBoundaryRight); printf ("Enter X-Boundary (left): "); scanf ("%f", &xBoundaryLeft); printf ("Enter Y-Boundary (upper): "); scanf ("%f", &yBoundaryUpper); printf ("Enter Y-Boundary (lower): "); scanf ("%f", &yBoundaryLower); printf ("Enter the first point of the the line segment to be clipped (x, y): "); scanf ("%f %f", &givenLineSegmentP1[X_COORDINATE], &givenLineSegmentP1[Y_COO RDINATE]); printf ("Enter the second point of the the line segment to be clipped (x, y) : "); scanf ("%f %f", &givenLineSegmentP2[X_COORDINATE], &givenLineSegmentP2[Y_COO RDINATE]); givenLineSegmentP2[Z_COORDINATE] = givenLineSegmentP1[Z_COORDINATE] = 0; /* Now calcluate the corners of the clipping rectangle */ p1[X_COORDINATE] = xBoundaryLeft; p1[Y_COORDINATE] = yBoundaryUpper; p1[Z_COORDINATE] = 0; p2[X_COORDINATE] = xBoundaryRight; p2[Y_COORDINATE] = yBoundaryUpper; p2[Z_COORDINATE] = 0;

p3[X_COORDINATE] = xBoundaryRight; p3[Y_COORDINATE] = yBoundaryLower; p3[Z_COORDINATE] = 0; p4[X_COORDINATE] = xBoundaryLeft; p4[Y_COORDINATE] = yBoundaryLower; p4[Z_COORDINATE] = 0; /* Do the required calculations. */ /* b0 is 1 if point is outside of yBoundaryUpper b1 is 1 if point is outside of yBoundaryLower b2 is 1 if point is outside of xBoundaryLeft and b3 is 1 if point is outside of xBoundaryRight. */ outP1[b0] outP1[b1] outP1[b2] outP1[b3] outP2[b0] outP2[b1] outP2[b2] outP2[b3] = = = = = = = = (givenLineSegmentP1[Y_COORDINATE] (givenLineSegmentP1[Y_COORDINATE] (givenLineSegmentP1[X_COORDINATE] (givenLineSegmentP1[X_COORDINATE] (givenLineSegmentP2[Y_COORDINATE] (givenLineSegmentP2[Y_COORDINATE] (givenLineSegmentP2[X_COORDINATE] (givenLineSegmentP2[X_COORDINATE] > < < > > < < > yBoundaryUpper) ? 1 : 0; yBoundaryLower) ? 1 : 0; xBoundaryLeft) ? 1 : 0; xBoundaryRight) ? 1 : 0; yBoundaryUpper) ? 1 : 0; yBoundaryLower) ? 1 : 0; xBoundaryLeft) ? 1 : 0; xBoundaryRight) ? 1 : 0;

/* We now have four cases to consider according to the Cohen-Sutherland Algo rithm. */ /* The point may be out of more than one side. In which case, we first clip w.r.t one side and continue the loop (updating the outP[] and clippedLine[] arr ays */ for (i = 0; i < 3; i++) clippedLineP1[i] = givenLineSegmentP1[i]; for (i = 0; i < 3; i++) clippedLineP2[i] = givenLineSegmentP2[i]; /* Henceforth, only clippedLineP[] will be used. */ while (1) { /* case 1 */ if (outP1[b0] == 0 && outP1[b1] == 0 && outP1[b2] == 0 && outP1[b3] == 0 && outP2[b0] == 0 && outP2[b1] == 0 && outP2[b2] == 0 && outP2[b3] == 0) { break; } /* case 2. One point inside and the other outside the rect. Split into two c ases. */ /* case 2a: outP1 != 0 && outP2 == 0: First point is outside and second insi de. */ else if ((outP1[b0] != 0 || outP1[b1] != 0 || outP1[b2] != 0 || outP1[b3] != 0) && (outP2[b0] == 0 && outP2[b1] == 0 && outP2[b2] == 0 && outP2[b3] == 0)) { if (clippedLineP1[X_COORDINATE] == clippedLineP2[X_COORDINATE]) { /* then m = (y2-y1)/(x2-x1) would be infinity. */ if (outP1[b0] == 1) { clippedLineP1[Y_COORDINATE] = yBoundaryUpper; outP1[b0] = 0; } else { clippedLineP1[Y_COORDINATE] = yBoundaryLower; outP1[b2] = 0;

} continue; } m = clippedLineP1[Y_COORDINATE]-clippedLineP2[Y_COORDINATE]; m /= clippedLineP1[X_COORDINATE]-clippedLineP2[X_COORDINATE]; if (m == 0) { if (outP1[b2] == 1) { clippedLineP1[X_COORDINATE] = outP1[b2] = 0; } else { clippedLineP1[X_COORDINATE] = outP1[b3] = 0; } continue; } /* Line is neither horizontal nor /* We try to clip whichever bound ing at that point, we immediately check if the other (if any) has been cl ipped too. */ c = clippedLineP1[Y_COORDINATE]-(m*clippedLineP1[X_COORDINATE]); if (outP1[b0] == 1) { clippedLineP1[Y_COORDINATE] = yBoundaryUpper; clippedLineP1[X_COORDINATE] = (yBoundaryUpper-c)/m; outP1[b0] = 0; if (clippedLineP1[X_COORDINATE] <= xBoundaryRight && clippedLineP1[X_COORDINATE] >= xBoundaryLeft) { outP1[b2] = outP1[b3] = 0; break; } continue; } if (outP1[b1] == 1) { clippedLineP1[Y_COORDINATE] = yBoundaryLower; clippedLineP1[X_COORDINATE] = (yBoundaryLower-c)/m; outP1[b1] = 0; if (clippedLineP1[X_COORDINATE] <= xBoundaryRight && clippedLineP1[X_COORDINATE] >= xBoundaryLeft) { outP1[b2] = outP1[b3] = 0; break; } continue; } if (outP1[b2] == 1) { clippedLineP1[X_COORDINATE] = xBoundaryLeft; clippedLineP1[Y_COORDINATE] = (m*xBoundaryLeft)+c; outP1[b2] = 0; if (clippedLineP1[Y_COORDINATE] <= yBoundaryUpper && clippedLineP1[Y_COORDINATE] >= yBoundaryLower) { outP1[b0] = outP1[b1] = 0; break; } continue; } if (outP1[b3] == 1) { clippedLineP1[X_COORDINATE] = xBoundaryRight;

xBoundaryLeft;

xBoundaryRight;

vertical at this point */ exceeds that we see first. After clipp

clippedLineP1[Y_COORDINATE] = (m*xBoundaryRight)+c; outP1[b3] = 0; if (clippedLineP1[Y_COORDINATE] <= yBoundaryUpper && clippedLineP1[Y_COORDINATE] >= yBoundaryLower) { outP1[b0] = outP1[b1] = 0; break; } continue; } } /* Case2b: If first point is inside and second point is outside. */ else if ((outP2[b0] != 0 || outP2[b1] != 0 || outP2[b2] != 0 || outP2[b3] != 0) && (outP1[b0] == 0 && outP1[b1] == 0 && outP1[b2] == 0 && outP1[b3] == 0)) { /* Exchange first and second points completely including outP[] and cont inue. */ for (i = 0; i < 3; i++) tempPoint[i] = clippedLineP1[i]; for (i = 0; i < 3; i++) clippedLineP1[i] = clippedLineP2[i]; for (i = 0; i < 3; i++) clippedLineP2[i] = tempPoint[i]; for (i = 0; i < 4; i++) outTemp[i] = outP1[i]; for (i = 0; i < 4; i++) outP1[i] = outP2[i]; for (i = 0; i < 4; i++) outP2[i] = outTemp[i]; continue; } /* Case 3. if (outP1 & outP2 != 0): Both points exceed the same boundary. */ else if ((outP1[b0] && outP2[b0] == 1) || (outP1[b1] && outP2[b1] == 1) || (outP1[b2] && outP2[b2] == 1) || (outP1[b3] && outP2[b3] == 1)) { /* set clippedLineP1 and clippedLineP2 both to 0,0,0 */ for (i = 0; i < 3; i++) clippedLineP2[i] = clippedLineP1[i] = 0; break; } /* case 4. Both endpoints are outside, but of different edges. */ else { /* Determine the points of intersection of the line with the four bounda ries and determine the outcode for each of these intersection points. We c an then estimate if the line is entirely out of the boundary or not. */ float intersectionP1[3], intersectionP2[3], intersectionP3[3], intersect ionP4[3]; int validIntersections = 0; /* check for special cases where line is horizontal or vertical. */ if (clippedLineP1[X_COORDINATE] == clippedLineP2[X_COORDINATE]) { /* The line starts from above yBoundaryUpper and ends below yBoundaryLow er. */ clippedLineP1[Y_COORDINATE] = yBoundaryUpper; clippedLineP2[Y_COORDINATE] = yBoundaryLower; break; } if (clippedLineP1[Y_COORDINATE] == clippedLineP2[Y_COORDINATE]) { /* The line starts from left of xBoundaryLeft and ends after xBoundaryRi ght. */ clippedLineP1[X_COORDINATE] = xBoundaryLeft; clippedLineP2[X_COORDINATE] = xBoundaryRight; break; }

/* Line is neither vertical nor horizontal. Do all four intersections. * / m = clippedLineP1[Y_COORDINATE] - clippedLineP2[Y_COORDINATE]; m /= clippedLineP1[X_COORDINATE] - clippedLineP2[X_COORDINATE]; c = clippedLineP1[Y_COORDINATE] - (m*clippedLineP1[X_COORDINATE]); /* Intersection with yBoundaryUpper */ intersectionP1[Y_COORDINATE] = yBoundaryUpper; intersectionP1[X_COORDINATE] = (yBoundaryUpper-c)/m; intersectionP1[Z_COORDINATE] = 0; /* Intersection with yBoundaryLower */ intersectionP2[Y_COORDINATE] = yBoundaryLower; intersectionP2[X_COORDINATE] = (yBoundaryLower-c)/m; intersectionP2[Z_COORDINATE] = 0; /* Intersection with xBoundaryLeft */ intersectionP3[X_COORDINATE] = xBoundaryLeft; intersectionP3[Y_COORDINATE] = (m*xBoundaryLeft)+c; intersectionP3[Z_COORDINATE] = 0; /* Intersection with xBoundaryRight */ intersectionP4[X_COORDINATE] = xBoundaryRight; intersectionP4[Y_COORDINATE] = (m*xBoundaryRight)+c; intersectionP4[Z_COORDINATE] = 0; /* If all these intersections are "outside", line is outside. If atleast one intersection is inside, there is one more intersection that is inside. These two intersections form the clipped line. (unless the line passes through a corner). */ /* The line cannot pass through the viewing rectange at more than two points. If there are more than two points (among the above intersection points) that are inside the viewing rectangle, some are identical. We need to set clippedLineP1 and clippedLineP2 to these two points (if any). */ /* When we find the 2nd valid intersection, we verify that it is not the same as the first and then only use it. At the end, if we have only one valid intersection, we reset both end points to 0,0,0 so that the line is not displayed as clipped. */ /* WE NEED TO FIND UNIQUE INTERSECTION POINTS THAT ARE INSIDE (if any). */ /* intersectionP1 (intersection with yBoundaryUpper). */ if (intersectionP1[X_COORDINATE] <= xBoundaryRight && intersectionP1[X_COORDINATE] >= xBoundaryLeft) { for (i = 0; i < 3; i++) clippedLineP1[i] = intersectionP1[i]; validIntersections++; } /* intersectionP2 (intersection with yBoundaryLower). */ if (intersectionP2[X_COORDINATE] <= xBoundaryRight && intersectionP2[X_COORDINATE] >= xBoundaryLeft) { if (validIntersections == 1) { /* we need to verify if its the same point as the first one. */ if (intersectionP2[X_COORDINATE] == clippedLineP1[X_COORDINATE] && intersectionP2[Y_COORDINATE] == clippedLineP1[Y_COORDINATE] && intersectionP2[Z_COORDINATE] == clippedLineP1[Z_COORDINATE]) /* do nothing. */ ; else { for (i = 0; i < 3; i++) clippedLineP2[i] = intersectionP2[i]; validIntersections++;

break; } } else { for (i = 0; i < 3; i++) clippedLineP1[i] = intersectionP2[i]; validIntersections++; } } /* intersectionP3 (intersection with xBoundaryLeft). */ if (intersectionP3[Y_COORDINATE] <= yBoundaryUpper && intersectionP3[Y_COORDINATE] >= yBoundaryLower) { if (validIntersections == 1) { /* we need to verify if its the same point as the first one. */ if (intersectionP3[X_COORDINATE] == clippedLineP1[X_COORDINATE] && intersectionP3[Y_COORDINATE] == clippedLineP1[Y_COORDINATE] && intersectionP3[Z_COORDINATE] == clippedLineP1[Z_COORDINATE]) /* do nothing. */ ; else { for (i = 0; i < 3; i++) clippedLineP2[i] = intersectionP3[i]; validIntersections++; break; } } else { for (i = 0; i < 3; i++) clippedLineP1[i] = intersectionP3[i]; validIntersections++; } } /* intersectionP4 (intersection with xBoundaryRight */ if (intersectionP4[Y_COORDINATE] <= yBoundaryUpper && intersectionP4[Y_COORDINATE] >= yBoundaryLower) { if (validIntersections == 1) { /* we need to verify if its the same point as the first one. */ if (intersectionP4[X_COORDINATE] == clippedLineP1[X_COORDINATE] && intersectionP4[Y_COORDINATE] == clippedLineP1[Y_COORDINATE] && intersectionP4[Z_COORDINATE] == clippedLineP1[Z_COORDINATE]) /* do nothing. */ ; else { for (i = 0; i < 3; i++) clippedLineP2[i] = intersectionP4[i]; validIntersections++; break; } } else { for (i = 0; i < 3; i++) clippedLineP1[i] = intersectionP4[i]; validIntersections++; } } /* If validIntersections <= 1 at this point, we set both clippedLineP1 and clippedLineP2 to 0,0,0. Only one validIntersection means that the line just passes through a corner of the viewing rectangle. */ if (validIntersections <= 1) for (i = 0; i < 3; i++) clippedLineP2[i] = clippedLineP1[i] = 0; break; } } glutInit (&argc, argv); glutCreateWindow ("Cohen-Sutherland Line Clipping");

glutInitWindowPosition (400, 400); glutInitWindowSize (640, 480); glutDisplayFunc (display); myInit(); glutMainLoop(); } void myInit () { glClearColor (1.0, 1.0, 1.0, 1.0); glPointSize (1); glColor3f (0.0, 0.0, 0.0); glMatrixMode (GL_PROJECTION); glLoadIdentity(); glOrtho (-50.0, 50.0, -50.0, 50.0, -50.0, 50.0); glMatrixMode (GL_MODELVIEW); } void display () { /* Clipped line is displayed in red, and unclipped in black. */ glClear (GL_COLOR_BUFFER_BIT); glColor3f (0.0, 0.0, 0.0); glBegin (GL_LINE_LOOP); glVertex3fv (p1); glVertex3fv (p2); glVertex3fv (p3); glVertex3fv (p4); glEnd (); glBegin (GL_LINES); glVertex3fv (givenLineSegmentP1); glVertex3fv (givenLineSegmentP2); glColor3f (1.0, 0.0, 0.0); glLineWidth (2); glVertex3fv (clippedLineP1); glVertex3fv (clippedLineP2); glEnd(); glFlush(); }

Anda mungkin juga menyukai