📄 devpoly.c
字号:
} while (i-- > 0) { ptsOut->y = y; /* * reverse the edges if necessary */ if (xl < xr) { *(width++) = xr - xl; (ptsOut++)->x = xl; } else { *(width++) = xl - xr; (ptsOut++)->x = xr; } y++; /* increment down the edges */ BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l); BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r); } } while (y != ymax); /* * Finally, fill the spans */ i = ptsOut-FirstPoint; ptsOut = FirstPoint; width = FirstWidth; while (--i >= 0) { /* calc x extent from width*/ int e = *width++ - 1; if (e >= 0) { drawrow(psd, ptsOut->x, ptsOut->x + e, ptsOut->y); } ++ptsOut; } FREEA(FirstWidth); FREEA(FirstPoint); GdFixCursor(psd);}#endif#if 0 /* original convex only polygon fill routine*//* * Fill a polygon in the foreground color, applying clipping if necessary. * The last point may be a duplicate of the first point, but this is * not required. * Note: this routine currently only correctly fills convex polygons. *//* Utility routine for filling polygons. Find the intersection point (if * any) of a horizontal line with an arbitrary line, and extend the current * minimum and maximum x values as needed to include the intersection point. * Input parms: * y row to check for intersection * x1, y1 first endpoint * x2, y2 second enpoint * minxptr address of current minimum x * maxxptr address of current maximum x */static voidextendrow(MWCOORD y,MWCOORD x1,MWCOORD y1,MWCOORD x2,MWCOORD y2, MWCOORD *minxptr,MWCOORD *maxxptr){ MWCOORD x; /* x coordinate of intersection */ typedef long NUM; NUM num; /* numerator of fraction */ /* First make sure the specified line segment includes the specified * row number. If not, then there is no intersection. */ if (((y < y1) || (y > y2)) && ((y < y2) || (y > y1))) return; /* If a horizontal line, then check the two endpoints. */ if (y1 == y2) { if (*minxptr > x1) *minxptr = x1; if (*minxptr > x2) *minxptr = x2; if (*maxxptr < x1) *maxxptr = x1; if (*maxxptr < x2) *maxxptr = x2; return; } /* If a vertical line, then check the x coordinate. */ if (x1 == x2) { if (*minxptr > x1) *minxptr = x1; if (*maxxptr < x1) *maxxptr = x1; return; } /* An arbitrary line. Calculate the intersection point using the * formula x = x1 + (y - y1) * (x2 - x1) / (y2 - y1). */ num = ((NUM) (y - y1)) * (x2 - x1); x = x1 + num / (y2 - y1); if (*minxptr > x) *minxptr = x; if (*maxxptr < x) *maxxptr = x;}voidGdFillPoly(PSD psd, int count, MWPOINT *points){ MWPOINT *pp; /* current point */ MWCOORD miny; /* minimum row */ MWCOORD maxy; /* maximum row */ MWCOORD minx; /* minimum column */ MWCOORD maxx; /* maximum column */ int i; /* counter */ if (count <= 0) return; /* First determine the minimum and maximum rows for the polygon. */ pp = points; miny = pp->y; maxy = pp->y; for (i = count; i-- > 0; pp++) { if (miny > pp->y) miny = pp->y; if (maxy < pp->y) maxy = pp->y; } if (miny < 0) miny = 0; if (maxy >= psd->yvirtres) maxy = psd->yvirtres - 1; if (miny > maxy) return; /* Now for each row, scan the list of points and determine the * minimum and maximum x coordinate for each line, and plot the row. * The last point connects with the first point automatically. */ for (; miny <= maxy; miny++) { minx = MAX_MWCOORD; maxx = MIN_MWCOORD; pp = points; for (i = count; --i > 0; pp++) extendrow(miny, pp[0].x, pp[0].y, pp[1].x, pp[1].y, &minx, &maxx); extendrow(miny, pp[0].x, pp[0].y, points[0].x, points[0].y, &minx, &maxx); if (minx <= maxx) drawrow(psd, minx, maxx, miny); } GdFixCursor(psd);}#endif#if 0 /* irregular polygon fill, uses edge table, malloc, qsort*//* * Fill a polygon in the foreground color, applying clipping if necessary. * The last point may be a duplicate of the first point, but this is * not required. * Note: this routine correctly draws convex, concave, regular, * and irregular polygons. */#define USE_FLOAT HAVEFLOAT /* set to use floating point*/#define swap(a,b) do { a ^= b; b ^= a; a ^= b; } while (0)typedef struct { int x1, y1, x2, y2;#if USE_FLOAT double x, m;#else int cx, fn, mn, d;#endif} edge_t;static int edge_cmp(const void *lvp, const void *rvp){ /* convert from void pointers to structure pointers */ const edge_t *lp = (const edge_t *)lvp; const edge_t *rp = (const edge_t *)rvp; /* if the minimum y values are different, sort on minimum y */ if (lp->y1 != rp->y1) return lp->y1 - rp->y1; /* if the current x values are different, sort on current x */#if USE_FLOAT if (lp->x < rp->x) return -1; else if (lp->x > rp->x) return +1;#else if (lp->cx != rp->cx) return lp->cx - rp->cx;#endif /* otherwise they are equal */ return 0;}voidGdFillPoly(PSD psd, int count, MWPOINT * pointtable){ edge_t *get; /* global edge table */ int nge = 0; /* num global edges */ int cge = 0; /* cur global edge */ edge_t *aet; /* active edge table */ int nae = 0; /* num active edges */ int i, y; if (count < 3) { /* error, polygons require at least three edges (a triangle) */ return; } get = (edge_t *) calloc(count, sizeof(edge_t)); aet = (edge_t *) calloc(count, sizeof(edge_t)); if ((get == 0) || (aet == 0)) { /* error, couldn't allocate one or both of the needed tables */ if (get) free(get); if (aet) free(aet); return; } /* setup the global edge table */ for (i = 0; i < count; ++i) { get[nge].x1 = pointtable[i].x; get[nge].y1 = pointtable[i].y; get[nge].x2 = pointtable[(i + 1) % count].x; get[nge].y2 = pointtable[(i + 1) % count].y; if (get[nge].y1 != get[nge].y2) { if (get[nge].y1 > get[nge].y2) { swap(get[nge].x1, get[nge].x2); swap(get[nge].y1, get[nge].y2); }#if USE_FLOAT get[nge].x = get[nge].x1; get[nge].m = get[nge].x2 - get[nge].x1; get[nge].m /= get[nge].y2 - get[nge].y1;#else get[nge].cx = get[nge].x1; get[nge].mn = get[nge].x2 - get[nge].x1; get[nge].d = get[nge].y2 - get[nge].y1; get[nge].fn = get[nge].mn / 2;#endif ++nge; } } qsort(get, nge, sizeof(get[0]), edge_cmp); /* start with the lowest y in the table */ y = get[0].y1; do { /* add edges to the active table from the global table */ while ((nge > 0) && (get[cge].y1 == y)) { aet[nae] = get[cge++]; --nge; aet[nae++].y1 = 0; } qsort(aet, nae, sizeof(aet[0]), edge_cmp); /* using odd parity, render alternating line segments */ for (i = 1; i < nae; i += 2) {#if USE_FLOAT int l = (int)aet[i - 1].x; int r = (int)aet[i].x;#else int l = (int)aet[i - 1].cx; int r = (int)aet[i].cx;#endif if (r > l) drawrow(psd, l, r - 1, y); } /* prepare for the next scan line */ ++y; /* remove inactive edges from the active edge table */ /* or update the current x position of active edges */ for (i = 0; i < nae; ++i) { if (aet[i].y2 == y) aet[i--] = aet[--nae]; else {#if USE_FLOAT aet[i].x += aet[i].m;#else aet[i].fn += aet[i].mn; if (aet[i].fn < 0) { aet[i].cx += aet[i].fn / aet[i].d - 1; aet[i].fn %= aet[i].d; aet[i].fn += aet[i].d; } if (aet[i].fn >= aet[i].d) { aet[i].cx += aet[i].fn / aet[i].d; aet[i].fn %= aet[i].d; }#endif } } /* keep doing this while there are any edges left */ } while ((nae > 0) || (nge > 0)); /* all done, free the edge tables */ free(get); free(aet); GdFixCursor(psd);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -