#include "MVCUtils.h" void canonicalRect(int *x1, int *y1, int *x2, int *y2) { // The "canonical" form of a rectangle is such that (x1,y1) is // the "upper left" corner and (x2,y2) is the "lower right" corner. // Mathmatically, we want x1 <= x2 and y1 >= y2 int tmp; if (*x1 > *x2) { tmp = *x1; *x1 = *x2; *x2 = tmp; } if (*y1 < *y2) { tmp = *y1; *y1 = *y2; *y2 = tmp; } } void canonicalRect(double *x1, double *y1, double *x2, double *y2) { // The "canonical" form of a rectangle is such that (x1,y1) is // the "upper left" corner and (x2,y2) is the "lower right" corner. // Mathmatically, we want x1 <= x2 and y1 >= y2 double tmp; if (*x1 > *x2) { tmp = *x1; *x1 = *x2; *x2 = tmp; } if (*y1 < *y2) { tmp = *y1; *y1 = *y2; *y2 = tmp; } } /* Author: Jamie Moyers */ /* Started: October 7 1991 */ /* Modification History: */ /* November 29 1994 -- Modified for use with MVC graphics package. /* Implementation of the Cohen-Sutherland Outcode algorithm for */ /* clipping an arbitrary line against a rectangle. The main procedure */ /* is called clip_line. */ /* Bit masks for outcode: xxxx => top bottom right left */ #define TOP 0x08 #define BOTTOM 0x04 #define RIGHT 0x02 #define LEFT 0x01 #define INSIDE 0x00 int compute_outcode(double x1,double y1,double rx1,double ry1, double rx2,double ry2) { /* Determines outcodes for (x1,y1) relative to rectangle defined */ /* by (rx1,ry1),(rx2,ry2). It is assumed (rx1,ry1) = lower left */ /* corner, (rx2,ry2) = upper right corner. */ int oc; oc = 0; if (y1 > ry2) oc = oc | TOP; else if (y1 < ry1) oc = oc | BOTTOM; if (x1 > rx2) oc = oc | RIGHT; else if (x1 < rx1) oc = oc | LEFT; return(oc); } bool clip_line(double *x1, double *y1, double *x2, double *y2, double rec_x1, double rec_y1, double rec_x2, double rec_y2) { #if 0 Input: (x1,y1),(x2,y2) Endpoints of line to clip to rectangle. (rec_x1,rec_y1), (rec_x2,rec_y2) Lower left and upper right corners of rectangle to clip to. Output: return value Set to one of the following: false - None of the line segment is visible. true - Part or all of line is visible. (x1,y1),(x2,y2) Replaced with endpoints of new line resulting from clipping old line to clip rectangle. (Different from input values only if return_code = 1) #endif bool accept,done,visible; int outcode0,outcode1,outcodeOut; double x,y; accept = false; done = false; outcode0 = compute_outcode(*x1,*y1,rec_x1,rec_y1, rec_x2,rec_y2); outcode1 = compute_outcode(*x2,*y2,rec_x1,rec_y1, rec_x2,rec_y2); visible = false; /* None of line is visible. */ do { if ((outcode0 == INSIDE) && (outcode1 == INSIDE)) { /* Trivial accept and exit */ accept = true; done = true; visible = true; /* Part or all is visible. */ } else if ((outcode0 & outcode1) != 0) /* Logical intersection is true, so trival reject and exit */ done = true; else /* Failed both tests, so calculate the line segment to clip. */ /* from and outside point to an intersection with clip edge. */ { /* At least one endpoint is outside the clip rectangle. */ /* Pick it. */ if (outcode0 != 0) outcodeOut = outcode0; else outcodeOut = outcode1; /* Now find intersection point */ if (outcodeOut & TOP) { x = *x1 + (*x2 - *x1) * (rec_y2 - *y1) / (*y2 - *y1); y = rec_y2; } else if (outcodeOut & BOTTOM) { x = *x1 + (*x2 - *x1) * (rec_y1 - *y1) / (*y2 - *y1); y = rec_y1; } else if (outcodeOut & RIGHT) { y = *y1 + (*y2 - *y1) * (rec_x2 - *x1) / (*x2 - *x1); x = rec_x2; } else if (outcodeOut & LEFT) { y = *y1 + (*y2 - *y1) * (rec_x1 - *x1) / (*x2 - *x1); x = rec_x1; } /* Now move outside point to intersection point to clip, */ /* and get ready for next pass. */ if (outcodeOut == outcode0) { *x1 = x; *y1 = y; outcode0 = compute_outcode(*x1,*y1,rec_x1,rec_y1, rec_x2,rec_y2); } else { *x2 = x; *y2 = y; outcode1 = compute_outcode(*x2,*y2,rec_x1,rec_y1, rec_x2,rec_y2); } } } while (!done); return(visible); }