jonnyg@aardvark.umd.EDU (Jon Greenblatt) (05/11/89)
There have been so many complaints about slow/buggy circles, I though I'd throw in my 70 lines. This routine, Draw_ellipse, will draw fast simple ellipses. It has been set up so that small filled ellipses work correctly under different raster ops but large and hollow circles need some work to work with GXor and other raster ops. I wrote this to do fast animation using circles and to solve the problem of a buggy clip algorithm for large hollow circles on my server. Circulate this as you wish. If someone is motivated, maybe they can throw this in the server as a speacial case. Note: no floating point here! /* * Draw_ellipse. A fast hollow/filled ellipse routine. * * Written by: Jonathan R. Greenblatt (jonnyg@rover.umd.edu) * Organization: University of Maryland at College Park. * Date: May 10, 1989 * */ Draw_ellipse(Dpy,win,gc,cx,cy,rx,ry,fill) Display *Dpy; Drawable w; GC gc; int cy, cy; /* X/Y coordinates for center of the ellipse */ int rx, ry; /* X and Y radius for ellipse */ int fill; /* Boolean for fill mode */ { long int r, r2, xr, yr, xp, yp; int x, y, xf, xo, yo, xs, ys; XPoint p[256]; rx = abs(rx); ry = abs(ry); if (rx == 0) rx = 1; if (ry == 0) ry = 1; xo = -1; yo = -1; yp = 0l; r = (rx > ry) ? rx: ry; /* Largest radius */ xr = rx; yr = ry; r2 = r * r; /* Radius squared */ ry = r * 2; rx = 0; for (xp = r; xp >= 0; xp--) /* Loop through quarter circle */ do { if (rx > 250) { if (fill) XDrawSegments(Dpy,win,gc,p,rx/2); else XDrawPoints(Dpy,win,gc,p,rx,CoordModeOrigin); rx = 0; } if ((int)r != (int)yr) { ys = (yp * yr) / r; xs = xp;} else { xs = (xp * xr) / r; ys = yp;}; if (!(xo == xs && yo == ys)) if (fill) { /* Filled */ if (ys != ry) { /* Take this conditional out if you are only using GXcopy */ ry = ys; xf = cx + xs; x = cx - xs; p[rx].x = x; p[rx++].y = cy-ys; p[rx].x = xf; p[rx++].y = cy-ys; if (ys > 0) { p[rx].x = x; p[rx++].y = cy+ys; p[rx].x = xf; p[rx++].y = cy+ys; } }} else { /* Hollow */ xo = xs; yo = ys; x = cx - xs; y = cy - ys; p[rx].x = x; p[rx++].y = y; y = cy + ys; p[rx].x = x; p[rx++].y = y; x = cx + xs; p[rx].x = x; p[rx++].y = y; y = cy - ys; p[rx].x = x; p[rx++].y = y; }; if ((yp * yp) >= (r2 - xp * xp)) break; yp++; } while (1); if (rx > 0) { if (fill) XDrawSegments(Dpy,win,gc,p,rx/2); else XDrawPoints(Dpy,win,gc,p,rx,CoordModeOrigin); rx = 0; } }