void main() { int gd=DETECT,gm; int left,top,right,bottom; int x1,x2,y1,y2; int maxx, maxy; /* our polygon array */ int poly[10]; void clipline(dcpt,dcpt,wcpt2,wcpt2); clrscr(); initgraph(&gd,&gm,"c:\\tc30\\bgi"); maxx = getmaxx()/4; maxy = getmaxy()/4; poly[0] = 20; /* 1st vertex */ poly[1] = maxy / 2; poly[2] = maxx - 10; /* 2nd */ poly[3] = 10; poly[4] = maxx - 50; /* 3rd */ poly[5] = maxy - 20; poly[6] = maxx / 2; /* 4th */ poly[7] = maxy / 2; /* drawpoly doesn't automatically close the polygon, so we close it. */ poly[8] = poly[0]; poly[9] = poly[1]; /* draw the polygon */ drawpoly(5, poly); rectangle(20,25,80,125); wcpt2 pt1,pt2; dcpt winmin,winmax; winmin.x=20; winmin.y=25; winmax.x=80; winmax.y=125; pt1.x=20; pt1.y=maxy/2; pt2.x=maxx-10; pt2.y=10; // clipline(winmin,winmax,pt1,pt2); int i=0; for(int index=0;index<n;index++) { if(index==n-1) { pt1.x=poly[i]; pt1.y=poly[i+1]; i=0; pt2.x=poly[i]; pt2.y=poly[i+1]; clipline(winmin,winmax,pt1,pt2); } else { pt1.x=poly[i]; pt1.y=poly[i+1]; pt2.x=poly[i+2]; pt2.y=poly[i+3]; clipline(winmin,winmax,pt1,pt2); } i+=2; } pt1.x=poly[i]; pt1.y=poly[i+1]; clipline(winmin,winmax,pt1,pt2); getch(); }
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 ); } }
LOCAL void fbp_drawline(struct rfb_Display *mod, struct rfb_Window *v, TINT rect[4], struct rfb_Pen *pen) { struct Region R; if (!rfb_getlayermask(mod, &R, v->rfbw_ClipRect.r, v, 0, 0)) return; struct Coord res[2]; TINT dx, dy, d, x, y; TINT incE, incNE, incSE, incN, incS; TINT l0, l1, l2, l3; if (rect[2] < rect[0]) { l0 = rect[2]; l1 = rect[3]; l2 = rect[0]; l3 = rect[1]; } else { l0 = rect[0]; l1 = rect[1]; l2 = rect[2]; l3 = rect[3]; } TUINT dfmt = v->rfbw_PixBuf.tpb_Format; TUINT p = pixconv_rgbfmt(dfmt, pen->rgb); struct TNode *next, *node = R.rg_Rects.rl_List.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct RectNode *rn = (struct RectNode *) node; TINT *r = rn->rn_Rect; if (!clipline(res, l0, l1, l2, l3, r[0], r[1], r[2], r[3])) continue; TINT x0 = res[0].x; TINT y0 = res[0].y; TINT x1 = res[1].x; TINT y1 = res[1].y; rfb_markdirty(mod, v, (TINT *) res); dx = x1 - x0; dy = y1 - y0; x = x0; y = y0; pixconv_setpixelbuf(&v->rfbw_PixBuf, x, y, p); if ((y0 <= y1) && (dy <= dx)) { /* m <= 1 */ d = 2 * dy - dx; incE = 2 * dy; incNE = 2 * (dy - dx); while (x < x1) { if (d <= 0) { d = d + incE; x++; } else { d = d + incNE; x++; y++; } pixconv_setpixelbuf(&v->rfbw_PixBuf, x, y, p); } } if ((y0 <= y1) && (dy > dx)) { /* m > 1 */ d = 2 * dx - dy; incN = 2 * dx; incNE = 2 * (dx - dy); while (y < y1) { if (d <= 0) { d = d + incN; y++; } else { d = d + incNE; x++; y++; } pixconv_setpixelbuf(&v->rfbw_PixBuf, x, y, p); } } if ((y0 > y1) && (-dy <= dx)) { dy = -dy; d = 2 * dy - dx; incE = 2 * dy; incSE = 2 * (dy - dx); while (x < x1) { if (d <= 0) { d = d + incE; x++; } else { d = d + incSE; x++; y--; } pixconv_setpixelbuf(&v->rfbw_PixBuf, x, y, p); } } if ((y0 > y1) && (-dy > dx)) { dy = -dy; d = 2 * dx - dy; incS = 2 * dx; incSE = 2 * (dx - dy); while (y > y1) { if (d <= 0) { d = d + incS; y--; } else { d = d + incSE; x++; y--; } pixconv_setpixelbuf(&v->rfbw_PixBuf, x, y, p); } } } region_free(&mod->rfb_RectPool, &R); }
void plP_pllclp(PLINT *x, PLINT *y, PLINT npts, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax, void (*draw) (short *, short *, PLINT)) { PLINT xx1, xx2, yy1, yy2; PLINT i, iclp = 0; short _xclp[PL_MAXPOLY], _yclp[PL_MAXPOLY]; short *xclp, *yclp; int drawable; if ( npts < PL_MAXPOLY ) { xclp = _xclp; yclp = _yclp; } else { xclp = (short *) malloc( npts*sizeof(short) ) ; yclp = (short *) malloc( npts*sizeof(short) ) ; } 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) { /* First point of polyline. */ if (iclp == 0) { xclp[iclp] = xx1; yclp[iclp] = yy1; iclp++; xclp[iclp] = xx2; yclp[iclp] = yy2; } /* Not first point. Check if first point of this segment matches up to previous point, and if so, add it to the current polyline buffer. */ else if (xx1 == xclp[iclp] && yy1 == yclp[iclp]) { iclp++; xclp[iclp] = xx2; yclp[iclp] = yy2; } /* Otherwise it's time to start a new polyline */ else { if (iclp + 1 >= 2) (*draw)(xclp, yclp, iclp + 1); iclp = 0; xclp[iclp] = xx1; yclp[iclp] = yy1; iclp++; xclp[iclp] = xx2; yclp[iclp] = yy2; } } } /* Handle remaining polyline */ if (iclp + 1 >= 2) (*draw)(xclp, yclp, iclp + 1); plsc->currx = x[npts-1]; plsc->curry = y[npts-1]; 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); }