IGL_INLINE void igl::circulation( const int e, const bool ccw, const Eigen::MatrixXi & F, const Eigen::MatrixXi & E, const Eigen::VectorXi & EMAP, const Eigen::MatrixXi & EF, const Eigen::MatrixXi & EI, Eigen::VectorXi & vN) { std::vector<int> N = circulation(e,ccw,F,E,EMAP,EF,EI); igl::list_to_matrix(N,vN); }
void plP_plfclp(PLINT *x, PLINT *y, PLINT npts, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax, void (*draw) (short *, short *, PLINT)) { PLINT i, xx1, xx2, yy1, yy2; int iclp = 0, iout = 2; short _xclp[2*PL_MAXPOLY+2], _yclp[2*PL_MAXPOLY+2]; short *xclp, *yclp; int drawable; int crossed_xmin1 = 0, crossed_xmax1 = 0; int crossed_ymin1 = 0, crossed_ymax1 = 0; int crossed_xmin2 = 0, crossed_xmax2 = 0; int crossed_ymin2 = 0, crossed_ymax2 = 0; int crossed_up = 0, crossed_down = 0; int crossed_left = 0, crossed_right = 0; int inside_lb ; int inside_lu ; int inside_rb ; int inside_ru ; /* Must have at least 3 points and draw() specified */ if (npts < 3 || !draw) return; if ( npts < PL_MAXPOLY ) { xclp = _xclp; yclp = _yclp; } else { xclp = (short *) malloc( (2*npts+2)*sizeof(short) ) ; yclp = (short *) malloc( (2*npts+2)*sizeof(short) ) ; } inside_lb = pointinpolygon(npts,x,y,xmin,ymin) ; inside_lu = pointinpolygon(npts,x,y,xmin,ymax) ; inside_rb = pointinpolygon(npts,x,y,xmax,ymin) ; inside_ru = pointinpolygon(npts,x,y,xmax,ymax) ; for (i = 0; i < npts - 1; i++) { xx1 = x[i]; xx2 = x[i+1]; yy1 = y[i]; yy2 = y[i+1]; drawable = (INSIDE(xx1, yy1) && INSIDE(xx2, yy2)); if ( ! drawable) drawable = ! clipline(&xx1, &yy1, &xx2, &yy2, xmin, xmax, ymin, ymax); if (drawable) { /* Boundary crossing condition -- coming in. */ crossed_xmin2 = (xx1 == xmin); crossed_xmax2 = (xx1 == xmax); crossed_ymin2 = (yy1 == ymin); crossed_ymax2 = (yy1 == ymax); crossed_left = (crossed_left || crossed_xmin2); crossed_right = (crossed_right || crossed_xmax2); crossed_down = (crossed_down || crossed_ymin2); crossed_up = (crossed_up || crossed_ymax2); iout = iclp+2; /* If the first segment, just add it. */ if (iclp == 0) { xclp[iclp] = xx1; yclp[iclp] = yy1; iclp++; xclp[iclp] = xx2; yclp[iclp] = yy2; iclp++; } /* Not first point. If first point of this segment matches up to the previous point, just add it. */ else if (xx1 == xclp[iclp-1] && yy1 == yclp[iclp-1]) { xclp[iclp] = xx2; yclp[iclp] = yy2; iclp++; } /* Otherwise, we need to add both points, to connect the points in the * polygon along the clip boundary. If we encircled a corner, we have * to add that first. */ else { /* Treat the case where we encircled two corners: Construct a polygon out of the subset of vertices Note that the direction is important too when adding the extra points */ xclp[iclp+1] = xx2; yclp[iclp+1] = yy2; xclp[iclp+2] = xx1; yclp[iclp+2] = yy1; iout = iout - iclp + 1; /* Upper two */ if ( ((crossed_xmin1 && crossed_xmax2) || (crossed_xmin2 && crossed_xmax1)) && inside_lu ) { if ( crossed_xmin1 ) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } } /* Lower two */ else if ( ((crossed_xmin1 && crossed_xmax2) || (crossed_xmin2 && crossed_xmax1)) && inside_lb ) { if ( crossed_xmin1 ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } /* Left two */ else if ( ((crossed_ymin1 && crossed_ymax2) || (crossed_ymin2 && crossed_ymax1)) && inside_lb ) { if ( crossed_ymin1 ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } /* Right two */ else if ( ((crossed_ymin1 && crossed_ymax2) || (crossed_ymin2 && crossed_ymax1)) && inside_rb ) { if ( crossed_ymin1 ) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } } /* Now the case where we encircled one corner */ /* Lower left */ else if ( (crossed_xmin1 && crossed_ymin2) || (crossed_ymin1 && crossed_xmin2) ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } /* Lower right */ else if ( (crossed_xmax1 && crossed_ymin2) || (crossed_ymin1 && crossed_xmax2) ) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* Upper left */ else if ( (crossed_xmin1 && crossed_ymax2) || (crossed_ymax1 && crossed_xmin2) ) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* Upper right */ else if ( (crossed_xmax1 && crossed_ymax2) || (crossed_ymax1 && crossed_xmax2) ) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* Now add current segment. */ xclp[iclp] = xx1; yclp[iclp] = yy1; iclp++; xclp[iclp] = xx2; yclp[iclp] = yy2; iclp++; } /* Boundary crossing condition -- going out. */ crossed_xmin1 = (xx2 == xmin); crossed_xmax1 = (xx2 == xmax); crossed_ymin1 = (yy2 == ymin); crossed_ymax1 = (yy2 == ymax); } } /* Limit case - all vertices are outside of bounding box. So just fill entire box, *if* the bounding box is completely encircled. */ if (iclp == 0) { PLINT xmin1, xmax1, ymin1, ymax1; xmin1 = xmax1 = x[0]; ymin1 = ymax1 = y[0]; for (i = 1; i < npts; i++) { if (x[i] < xmin1) xmin1 = x[i]; if (x[i] > xmax1) xmax1 = x[i]; if (y[i] < ymin1) ymin1 = y[i]; if (y[i] > ymax1) ymax1 = y[i]; } if (xmin1 <= xmin && xmax1 >= xmax && ymin1 <= ymin && ymax1 >= ymax ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; (*draw)(xclp, yclp, iclp); if ( xclp != _xclp ) { free( xclp ); free( yclp ); } return; } } /* Now handle cases where fill polygon intersects two sides of the box */ if (iclp >= 2) { int debug=0; int dir = circulation(x, y, npts); if (debug) { if ( (xclp[0] == xmin && xclp[iclp-1] == xmax) || (xclp[0] == xmax && xclp[iclp-1] == xmin) || (yclp[0] == ymin && yclp[iclp-1] == ymax) || (yclp[0] == ymax && yclp[iclp-1] == ymin) || (xclp[0] == xmin && yclp[iclp-1] == ymin) || (yclp[0] == ymin && xclp[iclp-1] == xmin) || (xclp[0] == xmax && yclp[iclp-1] == ymin) || (yclp[0] == ymin && xclp[iclp-1] == xmax) || (xclp[0] == xmax && yclp[iclp-1] == ymax) || (yclp[0] == ymax && xclp[iclp-1] == xmax) || (xclp[0] == xmin && yclp[iclp-1] == ymax) || (yclp[0] == ymax && xclp[iclp-1] == xmin) ) { printf("dir=%d, clipped points:\n", dir); for (i=0; i < iclp; i++) printf(" x[%d]=%d y[%d]=%d", i, xclp[i], i, yclp[i]); printf("\n"); printf("pre-clipped points:\n"); for (i=0; i < npts; i++) printf(" x[%d]=%d y[%d]=%d", i, x[i], i, y[i]); printf("\n"); } } /* The cases where the fill region is divided 2/2 */ /* Divided horizontally */ if (xclp[0] == xmin && xclp[iclp-1] == xmax) { if (dir > 0) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } else if (xclp[0] == xmax && xclp[iclp-1] == xmin) { if (dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } else { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } } /* Divided vertically */ else if (yclp[0] == ymin && yclp[iclp-1] == ymax) { if (dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } } else if (yclp[0] == ymax && yclp[iclp-1] == ymin) { if (dir > 0) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } } /* The cases where the fill region is divided 3/1 -- LL LR UR UL +-----+ +-----+ +-----+ +-----+ | | | | | \| |/ | | | | | | | | | |\ | | /| | | | | +-----+ +-----+ +-----+ +-----+ Note when we go the long way around, if the direction is reversed the three vertices must be visited in the opposite order. */ /* LL, short way around */ else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir < 0) || (yclp[0] == ymin && xclp[iclp-1] == xmin && dir > 0) ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } /* LL, long way around, counterclockwise */ else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir > 0)) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* LL, long way around, clockwise */ else if ((yclp[0] == ymin && xclp[iclp-1] == xmin && dir < 0)) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* LR, short way around */ else if ((xclp[0] == xmax && yclp[iclp-1] == ymin && dir > 0) || (yclp[0] == ymin && xclp[iclp-1] == xmax && dir < 0) ) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* LR, long way around, counterclockwise */ else if (yclp[0] == ymin && xclp[iclp-1] == xmax && dir > 0) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } /* LR, long way around, clockwise */ else if (xclp[0] == xmax && yclp[iclp-1] == ymin && dir < 0) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* UR, short way around */ else if ((xclp[0] == xmax && yclp[iclp-1] == ymax && dir < 0) || (yclp[0] == ymax && xclp[iclp-1] == xmax && dir > 0) ) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* UR, long way around, counterclockwise */ else if (xclp[0] == xmax && yclp[iclp-1] == ymax && dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* UR, long way around, clockwise */ else if (yclp[0] == ymax && xclp[iclp-1] == xmax && dir < 0) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* UL, short way around */ else if ((xclp[0] == xmin && yclp[iclp-1] == ymax && dir > 0) || (yclp[0] == ymax && xclp[iclp-1] == xmin && dir < 0) ) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* UL, long way around, counterclockwise */ else if (yclp[0] == ymax && xclp[iclp-1] == xmin && dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* UL, long way around, clockwise */ else if (xclp[0] == xmin && yclp[iclp-1] == ymax && dir < 0) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } /* Check for the case that only one side has been crossed (AM) Just checking a single point turns out not to be enough, apparently the crossed_*1 and crossed_*2 variables are not quite what I expected. */ if ( crossed_left+crossed_right+crossed_down+crossed_up == 1 && inside_lb+inside_rb+inside_lu+inside_ru == 4 ) { int dir = circulation(x, y, npts); PLINT xlim[4], ylim[4]; int insert; int incr; xlim[0] = xmin ; ylim[0] = ymin ; xlim[1] = xmax ; ylim[1] = ymin ; xlim[2] = xmax ; ylim[2] = ymax ; xlim[3] = xmin ; ylim[3] = ymax ; if ( dir > 0 ) { incr = 1; insert = 0*crossed_left + 1*crossed_down + 2*crossed_right + 3*crossed_up ; } else { incr = -1; insert = 3*crossed_left + 2*crossed_up + 1*crossed_right + 0*crossed_down ; } for ( i=0; i < 4; i ++ ) { xclp[iclp] = xlim[insert] ; yclp[iclp] = ylim[insert] ; iclp ++ ; insert += incr ; if ( insert > 3 ) insert = 0 ; if ( insert < 0 ) insert = 3 ; } } /* Draw the sucker */ if (iclp >= 3) (*draw)(xclp, yclp, iclp); if ( xclp != _xclp ) { free( xclp ); free( yclp ); } }
void plP_plfclp(PLINT *x, PLINT *y, PLINT npts, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax, void (*draw) (short *, short *, PLINT)) { PLINT i, x1, x2, y1, y2; int iclp = 0, iout = 2; short xclp[2*PL_MAXPOLY+2], yclp[2*PL_MAXPOLY+2]; int drawable; int crossed_xmin1 = 0, crossed_xmax1 = 0; int crossed_ymin1 = 0, crossed_ymax1 = 0; int crossed_xmin2 = 0, crossed_xmax2 = 0; int crossed_ymin2 = 0, crossed_ymax2 = 0; /* Must have at least 3 points and draw() specified */ if (npts < 3 || !draw) return; for (i = 0; i < npts - 1; i++) { x1 = x[i]; x2 = x[i+1]; y1 = y[i]; y2 = y[i+1]; drawable = (INSIDE(x1, y1) && INSIDE(x2, y2)); if ( ! drawable) drawable = ! clipline(&x1, &y1, &x2, &y2, xmin, xmax, ymin, ymax); if (!drawable) { /* Store the edges outside the viewport */ xclp[iout] = x2; yclp[iout] = y2; iout ++; } else { /* Boundary crossing condition -- coming in. */ crossed_xmin2 = (x1 == xmin); crossed_xmax2 = (x1 == xmax); crossed_ymin2 = (y1 == ymin); crossed_ymax2 = (y1 == ymax); iout = iclp+2; /* If the first segment, just add it. */ if (iclp == 0) { xclp[iclp] = x1; yclp[iclp] = y1; iclp++; xclp[iclp] = x2; yclp[iclp] = y2; iclp++; } /* Not first point. If first point of this segment matches up to the previous point, just add it. */ else if (x1 == xclp[iclp-1] && y1 == yclp[iclp-1]) { xclp[iclp] = x2; yclp[iclp] = y2; iclp++; } /* Otherwise, we need to add both points, to connect the points in the * polygon along the clip boundary. If we encircled a corner, we have * to add that first. */ else { /* Treat the case where we encircled two corners: Construct a polygon out of the subset of vertices Note that the direction is important too when adding the extra points */ xclp[iclp+1] = x2; yclp[iclp+1] = y2; xclp[iclp+2] = x1; yclp[iclp+2] = y1; iout = iout - iclp; /* Upper two */ if ( ((crossed_xmin1 && crossed_xmax2) || (crossed_xmin2 && crossed_xmax1)) && pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmin,ymax) ) { if ( crossed_xmin1 ) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } } /* Lower two */ else if ( ((crossed_xmin1 && crossed_xmax2) || (crossed_xmin2 && crossed_xmax1)) && pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmin,ymin) ) { if ( crossed_xmin1 ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } /* Left two */ else if ( ((crossed_ymin1 && crossed_ymax2) || (crossed_ymin2 && crossed_ymax1)) && pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmin,ymin) ) { if ( crossed_ymin1 ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } /* Right two */ else if ( ((crossed_ymin1 && crossed_ymax2) || (crossed_ymin2 && crossed_ymax1)) && pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmax,ymin) ) { if ( crossed_ymin1 ) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } } /* Now the case where we encircled one corner */ /* Lower left */ else if ( (crossed_xmin1 && crossed_ymin2) || (crossed_ymin1 && crossed_xmin2) ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } /* Lower right */ else if ( (crossed_xmax1 && crossed_ymin2) || (crossed_ymin1 && crossed_xmax2) ) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* Upper left */ else if ( (crossed_xmin1 && crossed_ymax2) || (crossed_ymax1 && crossed_xmin2) ) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* Upper right */ else if ( (crossed_xmax1 && crossed_ymax2) || (crossed_ymax1 && crossed_xmax2) ) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* Now add current segment. */ xclp[iclp] = x1; yclp[iclp] = y1; iclp++; xclp[iclp] = x2; yclp[iclp] = y2; iclp++; } /* Boundary crossing condition -- going out. */ crossed_xmin1 = (x2 == xmin); crossed_xmax1 = (x2 == xmax); crossed_ymin1 = (y2 == ymin); crossed_ymax1 = (y2 == ymax); } } /* Limit case - all vertices are outside of bounding box. So just fill entire box, *if* the bounding box is completely encircled. */ if (iclp == 0) { PLINT xmin1, xmax1, ymin1, ymax1; xmin1 = xmax1 = x[0]; ymin1 = ymax1 = y[0]; for (i = 1; i < npts; i++) { if (x[i] < xmin1) xmin1 = x[i]; if (x[i] > xmax1) xmax1 = x[i]; if (y[i] < ymin1) ymin1 = y[i]; if (y[i] > ymax1) ymax1 = y[i]; } if (xmin1 <= xmin && xmax1 >= xmax && ymin1 <= ymin && ymax1 >= ymax ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; (*draw)(xclp, yclp, iclp); return; } } /* Now handle cases where fill polygon intersects two sides of the box */ if (iclp >= 2) { int debug=0; int dir = circulation(x, y, npts); if (debug) { if ( (xclp[0] == xmin && xclp[iclp-1] == xmax) || (xclp[0] == xmax && xclp[iclp-1] == xmin) || (yclp[0] == ymin && yclp[iclp-1] == ymax) || (yclp[0] == ymax && yclp[iclp-1] == ymin) || (xclp[0] == xmin && yclp[iclp-1] == ymin) || (yclp[0] == ymin && xclp[iclp-1] == xmin) || (xclp[0] == xmax && yclp[iclp-1] == ymin) || (yclp[0] == ymin && xclp[iclp-1] == xmax) || (xclp[0] == xmax && yclp[iclp-1] == ymax) || (yclp[0] == ymax && xclp[iclp-1] == xmax) || (xclp[0] == xmin && yclp[iclp-1] == ymax) || (yclp[0] == ymax && xclp[iclp-1] == xmin) ) { printf("dir=%d, clipped points:\n", dir); for (i=0; i < iclp; i++) printf(" x[%d]=%d y[%d]=%d", i, xclp[i], i, yclp[i]); printf("\n"); printf("pre-clipped points:\n"); for (i=0; i < npts; i++) printf(" x[%d]=%d y[%d]=%d", i, x[i], i, y[i]); printf("\n"); } } /* The cases where the fill region is divided 2/2 */ /* Divided horizontally */ if (xclp[0] == xmin && xclp[iclp-1] == xmax) { if (dir > 0) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } else if (xclp[0] == xmax && xclp[iclp-1] == xmin) { if (dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } else { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } } /* Divided vertically */ else if (yclp[0] == ymin && yclp[iclp-1] == ymax) { if (dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } else { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } } else if (yclp[0] == ymax && yclp[iclp-1] == ymin) { if (dir > 0) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } else { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } } /* The cases where the fill region is divided 3/1 -- LL LR UR UL +-----+ +-----+ +-----+ +-----+ | | | | | \| |/ | | | | | | | | | |\ | | /| | | | | +-----+ +-----+ +-----+ +-----+ Note when we go the long way around, if the direction is reversed the three vertices must be visited in the opposite order. */ /* LL, short way around */ else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir < 0) || (yclp[0] == ymin && xclp[iclp-1] == xmin && dir > 0) ) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } /* LL, long way around, counterclockwise */ else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir > 0)) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* LL, long way around, clockwise */ else if ((yclp[0] == ymin && xclp[iclp-1] == xmin && dir < 0)) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* LR, short way around */ else if ((xclp[0] == xmax && yclp[iclp-1] == ymin && dir > 0) || (yclp[0] == ymin && xclp[iclp-1] == xmax && dir < 0) ) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* LR, long way around, counterclockwise */ else if (yclp[0] == ymin && xclp[iclp-1] == xmax && dir > 0) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } /* LR, long way around, clockwise */ else if (xclp[0] == xmax && yclp[iclp-1] == ymin && dir < 0) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* UR, short way around */ else if ((xclp[0] == xmax && yclp[iclp-1] == ymax && dir < 0) || (yclp[0] == ymax && xclp[iclp-1] == xmax && dir > 0) ) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* UR, long way around, counterclockwise */ else if (xclp[0] == xmax && yclp[iclp-1] == ymax && dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; } /* UR, long way around, clockwise */ else if (yclp[0] == ymax && xclp[iclp-1] == xmax && dir < 0) { xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* UL, short way around */ else if ((xclp[0] == xmin && yclp[iclp-1] == ymax && dir > 0) || (yclp[0] == ymax && xclp[iclp-1] == xmin && dir < 0) ) { xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; } /* UL, long way around, counterclockwise */ else if (yclp[0] == ymax && xclp[iclp-1] == xmin && dir > 0) { xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++; xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; } /* UL, long way around, clockwise */ else if (xclp[0] == xmin && yclp[iclp-1] == ymax && dir < 0) { xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++; xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++; } } /* Draw the sucker */ if (iclp >= 3) (*draw)(xclp, yclp, iclp); }