|
|
1.1 ! root 1: ! 2: #include "jerq.h" ! 3: ! 4: /* jerq routines: circle, disc, ellipse, eldisc, arc */ ! 5: ! 6: /* circle: ! 7: Form a circle of radius r centered at x1,y1 ! 8: The boundary is a sequence of vertically, horizontally, ! 9: or diagonally adjacent points that minimize ! 10: abs(x^2+y^2-r^2). ! 11: The circle is guaranteed to be symmetric about ! 12: the horizontal, vertical, and diagonal axes ! 13: */ ! 14: circle (b, p, r, f) ! 15: Bitmap *b; ! 16: Point p; ! 17: { ! 18: int x1=p.x; ! 19: register y1 = p.y; ! 20: register eps = 0; /* x^2 + y^2 - r^2 */ ! 21: register dxsq = 1; /* (x+dx)^2-x^2*/ ! 22: register dysq = 1 - 2*r; ! 23: register exy; ! 24: int x0 = x1; ! 25: register y0 = y1 - r; ! 26: y1 += r; ! 27: initpoints(b, f); ! 28: if(f == F_XOR){ /* endpoints coincide */ ! 29: points(Pt(x0,y0)); ! 30: points(Pt(x0,y1)); ! 31: } ! 32: while(y1 > y0){ ! 33: points(Pt(x0,y0)); ! 34: points(Pt(x0,y1)); ! 35: points(Pt(x1,y0)); ! 36: points(Pt(x1,y1)); ! 37: exy = eps + dxsq + dysq; ! 38: if(-exy <= eps + dxsq){ ! 39: y1--; ! 40: y0++; ! 41: eps += dysq; ! 42: dysq += 2; ! 43: } ! 44: if(exy <= -eps){ ! 45: x1++; ! 46: x0--; ! 47: eps += dxsq; ! 48: dxsq += 2; ! 49: } ! 50: } ! 51: points(Pt(x0,y0)); ! 52: points(Pt(x1,y0)); ! 53: endpoints(); ! 54: } ! 55: ! 56: /* Fill a disc of radius r centered at x1,y1 ! 57: The boundary is a sequence of vertically, horizontally, ! 58: or diagonally adjacent points that minimize ! 59: abs(x^2+y^2-r^2). ! 60: The circle is guaranteed to be symmetric about ! 61: the horizontal, vertical, and diagonal axes ! 62: */ ! 63: disc (b, p, r, f) ! 64: Bitmap *b; ! 65: Point p; ! 66: int r; ! 67: int f; ! 68: { ! 69: register x1, y1; ! 70: register eps = 0; /* x^2 + y^2 - r^2 */ ! 71: int dxsq = 1; /* (x+dx)^2-x^2 */ ! 72: int dysq = 1 - 2 * r; ! 73: int exy; ! 74: register x0; ! 75: register y0; ! 76: ! 77: if(b->flag & BI_OFFSCREEN) ! 78: p = sub(p, b->rect.origin); ! 79: x1 = p.x; ! 80: y1 = p.y; ! 81: x0 = x1; ! 82: y0 = y1 - r; ! 83: x1++; /* to offset jerq's half-open lines */ ! 84: y1 += r; ! 85: while(y1 > y0){ ! 86: exy = eps + dxsq + dysq; ! 87: if(-exy <= eps + dxsq){ ! 88: rectf(b, Rect(x0, y0, x1, y0+1), f); ! 89: rectf(b, Rect(x0, y1, x1, y1+1), f); ! 90: y1--; ! 91: y0++; ! 92: eps += dysq; ! 93: dysq += 2; ! 94: } ! 95: if(exy <= -eps){ ! 96: x1++; ! 97: x0--; ! 98: eps += dxsq; ! 99: dxsq += 2; ! 100: } ! 101: } ! 102: rectf(b, Rect(x0, y0, x1, y0+1), f); ! 103: } ! 104: ! 105: /* arc: ! 106: draw an approximate arc centered at x0,y0 of an ! 107: integer grid and running anti-clockwise from ! 108: x1,y1 to the vicinity of x2,y2. ! 109: If the endpoints coincide, draw a complete circle. ! 110: The "arc" is a sequence of vertically, horizontally, ! 111: or diagonally adjacent points that minimize ! 112: abs(x^2+y^2-r^2). ! 113: The circle is guaranteed to be symmetric about ! 114: the horizontal, vertical, and diagonal axes ! 115: */ ! 116: #define sq(x) ((long)(x)*(x)) ! 117: #define sgn(x) ((x) < 0 ? -1 : (x)==0 ? 0 : 1) ! 118: #define mabs(x) (x < 0 ? -x : x) ! 119: ! 120: static ! 121: Point ! 122: nearby (p1, p2) /* called by arc() */ ! 123: Point p1, p2; ! 124: { ! 125: long eps, exy; /*integers but many bits*/ ! 126: int d; ! 127: register dy; ! 128: register dx; ! 129: register x1 = p1.x; ! 130: register y1 = p1.y; ! 131: register x2 = p2.x; ! 132: register y2 = p2.y; ! 133: eps = sq(x2) + sq(y2) - sq(x1) - sq(y1); ! 134: d = eps>0? -1: 1; ! 135: for( ; ; eps=exy, x2+=dx, y2+=dy){ ! 136: if(abs(y2) > abs(x2)){ ! 137: dy = d*sgn(y2); ! 138: dx = 0; ! 139: } ! 140: else{ ! 141: dy = 0; ! 142: dx = d*sgn(x2); ! 143: if(dx==0) ! 144: dx = 1; ! 145: } ! 146: exy = eps + (2*x2+dx)*dx + (2*y2+dy)*dy; ! 147: if(mabs(eps) <= mabs(exy)) ! 148: break; ! 149: } ! 150: p2.x = x2; ! 151: p2.y = y2; ! 152: return(p2); ! 153: } ! 154: ! 155: arc (bp, p0, p2, p1, f) ! 156: register Bitmap *bp; ! 157: Point p0, p1, p2; ! 158: { ! 159: register dx, dy; ! 160: register eps; /* x^2 + y^2 - r^2 */ ! 161: int dxsq, dysq; /* (x+dx)^2-x^2, ...*/ ! 162: int ex, ey, exy; ! 163: p1 = sub(p1, p0); ! 164: p2 = sub(p2, p0); ! 165: p2 = nearby(p1, p2); ! 166: dx = -sgn(p1.y); /* y1==0 is soon fixed */ ! 167: dy = sgn(p1.x); ! 168: dxsq = (2*p1.x + dx)*dx; ! 169: dysq = (2*p1.y + dy)*dy; ! 170: eps = 0; ! 171: initpoints(bp, f); ! 172: do{ ! 173: if(p1.x == 0){ ! 174: dy = -sgn(p1.y); ! 175: dysq = (2*p1.y + dy)*dy; ! 176: } ! 177: else if(p1.y == 0){ ! 178: dx = -sgn(p1.x); ! 179: dxsq = (2*p1.x + dx)*dx; ! 180: } ! 181: ex = abs(eps + dxsq); ! 182: ey = abs(eps + dysq); ! 183: exy = abs(eps + dxsq + dysq); ! 184: if(ex<ey || exy<=ey){ ! 185: p1.x += dx; ! 186: eps += dxsq; ! 187: dxsq += 2; ! 188: } ! 189: if(ey<ex || exy<=ex){ ! 190: p1.y += dy; ! 191: eps += dysq; ! 192: dysq += 2; ! 193: } ! 194: points(Pt(p0.x+p1.x, p0.y+p1.y)); ! 195: } while(!(p1.x==p2.x && p1.y==p2.y)); ! 196: /* the equality end test is justified ! 197: because it is impossible that ! 198: abs(x^2+y^2-r^2)==abs((x++-1)^2+y^2-r^2) or ! 199: abs(x^2+y^2-r^2)==abs(x^2+(y++-1)-r^2), ! 200: and no values of x or y are skipped. */ ! 201: endpoints(); ! 202: } ! 203: ! 204: ellipse (bp, p, a, b, f) ! 205: Bitmap *bp; ! 206: Point p; ! 207: long a, b; ! 208: Code f; ! 209: { ! 210: if(a==0 || b==0) ! 211: segment(bp, Pt(p.x-a, p.y-b), Pt(p.x+a, p.y+b), f); ! 212: else ! 213: ellip2(bp, p, a, b, Pt(0, b), Pt(0, b), f); ! 214: } ! 215: ! 216: #define BIG 077777 ! 217: #define HUGE 07777777777L ! 218: /* ! 219: resid: calculate b*b*x*x + a*a*y*y - a*a*b*b avoiding ovfl ! 220: called by ellip1() and ellip2() ! 221: */ ! 222: static long ! 223: resid (a,b,x,y) ! 224: register long a, b; ! 225: long x, y; ! 226: { ! 227: long e = 0; ! 228: long u = b*(a*a - x*x); ! 229: long v = a*y*y; ! 230: register q = u>BIG? HUGE/u: BIG; ! 231: register r = v>BIG? HUGE/v: BIG; ! 232: while(a || b){ ! 233: if(e>=0 && b){ ! 234: if(q>b) q = b; ! 235: e -= q*u; ! 236: b -= q; ! 237: } ! 238: else{ ! 239: if(r>a) r = a; ! 240: e += r*v; ! 241: a -= r; ! 242: } ! 243: } ! 244: return(e); ! 245: } ! 246: ! 247: #define labs(x,y) if((x=y)<0) x = -x ! 248: #define samesign(x,y) (((int)(x)^(int)(y)) > 0) ! 249: ! 250: ellip2 (bp, p0, a, b, p1, p2, f) ! 251: Point p0, p1, p2; ! 252: long a, b; ! 253: register Bitmap *bp; ! 254: Code f; ! 255: { ! 256: int dx = p1.y>0 ? 1 : p1.y<0 ? -1 : p1.x>0 ? -1 : 1; ! 257: int dy = p1.x>0 ? -1 : p1.x<0 ? 1 : p1.y>0 ? -1 : 1; ! 258: long a2 = a*a; ! 259: long b2 = b*b; ! 260: register long dex = b2*(2*dx*p1.x+1); ! 261: register long e; ! 262: register long dey = a2*(2*dy*p1.y+1); ! 263: register long ex, ey, exy; ! 264: int partial = !eqpt(p1, p2); ! 265: ! 266: if(partial && ! 267: (p1.x==0 && p2.x==0 && samesign(p1.y, p2.y) || ! 268: p1.y==0 && p2.y==0 && samesign(p1.x, p2.x))) { ! 269: segment(bp, add(p0, p1), add(p0,p2), f); ! 270: return; ! 271: } ! 272: e = resid(a, b, p1.x, p1.y); ! 273: a2 *= 2; ! 274: b2 *= 2; ! 275: initpoints(bp, f); ! 276: do{ ! 277: labs(ex, e+dex); ! 278: labs(ey, e+dey); ! 279: labs(exy, e+dex+dey); ! 280: if(exy<=ex || ey<ex){ ! 281: p1.y += dy; ! 282: e += dey; ! 283: dey += a2; ! 284: } ! 285: if(exy<=ey || ex<ey){ ! 286: p1.x += dx; ! 287: e += dex; ! 288: dex += b2; ! 289: } ! 290: if(p1.x == 0){ ! 291: if(abs(p1.y) == b){ ! 292: dy = -dy; ! 293: dey = -dey + a2; ! 294: partial = 0; ! 295: } ! 296: /* don't double-draw skinny ends */ ! 297: else if(!samesign(p1.y, dy) && !partial) ! 298: continue; ! 299: } ! 300: else if(p1.y == 0){ ! 301: if(abs(p1.x) == a){ ! 302: dx = -dx; ! 303: dex = -dex + b2; ! 304: partial = 0; ! 305: } ! 306: else if(!samesign(p1.x, dx) && !partial) ! 307: continue; ! 308: } ! 309: points(add(p0, p1)); ! 310: } while(! eqpt(p1, p2)); ! 311: endpoints(); ! 312: } ! 313: ! 314: ellip1 (bp, p0, a, b, action, p1, p2, f) ! 315: Bitmap *bp; ! 316: Point p0, p1, p2; ! 317: long a, b; ! 318: register void (*action) (); ! 319: int f; ! 320: { ! 321: int dx = p1.y > 0 ? 1 : p1.y < 0 ? -1 : p1.x > 0 ? -1 : 1; ! 322: int dy = p1.x > 0 ? -1 : p1.x < 0 ? 1 : p1.y > 0 ? -1 : 1; ! 323: long a2 = a * a; ! 324: long b2 = b * b; ! 325: register long dex = b2 * (2 * dx * p1.x + 1); ! 326: register long e; ! 327: register long dey = a2 * (2 * dy * p1.y + 1); ! 328: register long ex, ey, exy; ! 329: int partial = !eqpt (p1, p2); ! 330: ! 331: if(partial && ! 332: (p1.x == 0 && p2.x == 0 && samesign (p1.y, p2.y) || ! 333: p1.y == 0 && p2.y == 0 && samesign (p1.x, p2.x))){ ! 334: segment(bp, add (p0, p1), add (p0, p2), f); ! 335: return; ! 336: } ! 337: e = resid(a, b, p1.x, p1.y); ! 338: a2 *= 2; ! 339: b2 *= 2; ! 340: do{ ! 341: labs(ex, e + dex); ! 342: labs(ey, e + dey); ! 343: labs(exy, e + dex + dey); ! 344: if(exy <= ex || ey < ex){ ! 345: p1.y += dy; ! 346: e += dey; ! 347: dey += a2; ! 348: } ! 349: if(exy <= ey || ex < ey){ ! 350: p1.x += dx; ! 351: e += dex; ! 352: dex += b2; ! 353: } ! 354: if(p1.x == 0){ ! 355: if(abs(p1.y) == b){ ! 356: dy = -dy; ! 357: dey = -dey + a2; ! 358: partial = 0; ! 359: } ! 360: else ! 361: if(!samesign (p1.y, dy) && !partial) ! 362: continue; ! 363: /* don't double-draw skinny ends */ ! 364: } ! 365: else ! 366: if(p1.y == 0){ ! 367: if(abs (p1.x) == a){ ! 368: dx = -dx; ! 369: dex = -dex + b2; ! 370: partial = 0; ! 371: } ! 372: else ! 373: if(!samesign (p1.x, dx) && !partial) ! 374: continue; ! 375: } ! 376: (*action)(bp, add (p0, p1), f); ! 377: } while(!eqpt (p1, p2)); ! 378: } ! 379: ! 380: static int yaxis; /* used in scan and eldisc */ ! 381: static int xaxis; /* used in scan and eldisc */ ! 382: static Point lp; /* used in scan and eldisc */ ! 383: ! 384: static ! 385: void ! 386: scan (bp, p, f) /* called by eldisc() and ellip1() */ ! 387: Bitmap *bp; ! 388: Point p; ! 389: Code f; ! 390: { ! 391: register x, y; ! 392: ! 393: if((p.y != lp.y) && (lp.y != -1)){ ! 394: x = xaxis - lp.x; ! 395: y = yaxis - lp.y; ! 396: rectf(bp, Rect(lp.x, lp.y, x+1, lp.y+1), f); ! 397: rectf(bp, Rect(lp.x, y, x+1, y+1), f); ! 398: } ! 399: lp = p; ! 400: } ! 401: ! 402: eldisc (bp, p, a, b, f) ! 403: Bitmap *bp; ! 404: Point p; ! 405: int a, b; ! 406: Code f; ! 407: { ! 408: register x0 = p.x; ! 409: register y0 = p.y; ! 410: ! 411: yaxis = 2*p.y; ! 412: xaxis = 2*p.x; ! 413: lp.y = -1; ! 414: if(a==0 || b==0) ! 415: segment(bp, Pt(x0-a,y0-b), Pt(x0+a,y0+b), f); ! 416: else{ ! 417: ellip1(bp, p, a, b, scan, Pt(0, -b), Pt(-a, 0), f); ! 418: scan(bp, Pt(0, -1), f); ! 419: rectf(bp, Rect(p.x-a, p.y, p.x+a+1, p.y+1), f); ! 420: } ! 421: } ! 422: ! 423: /* elarc routines */ ! 424: ! 425: static struct dist { ! 426: Point s; ! 427: Point m; ! 428: long e; ! 429: } d1, d2; ! 430: ! 431: static ! 432: void ! 433: test(x, p) /* called by survet() */ ! 434: Point x; ! 435: register struct dist *p; ! 436: { ! 437: register long dx = x.x - p->s.x; ! 438: register long dy = x.y - p->s.y; ! 439: register long e = dx*dx+dy*dy; ! 440: ! 441: if(e <= p->e){ ! 442: p->m = x; ! 443: p->e = e; ! 444: } ! 445: } ! 446: ! 447: static ! 448: void ! 449: survey(bp, x, f) /* called by elarc() */ ! 450: Bitmap *bp; ! 451: Point x; ! 452: Code f; ! 453: { ! 454: test(x, &d1); ! 455: test(x, &d2); ! 456: } ! 457: ! 458: #define HUGE2 017777777777 ! 459: #define sgn2(x) ((x)<0? -1 : (x)==0? 0 : 1) ! 460: ! 461: /* ! 462: elarc(bp,p0,a,b,p1,p2,f) draws in bitmap bp an arc of the ellipse ! 463: centered at p0 with half-axes a,b extending counterclockwise ! 464: from a point near p1 to a point near p2 ! 465: args reversed because ellip1 draws clockwise ! 466: */ ! 467: elarc (bp, p0, a, b, p1, p2, f) ! 468: Bitmap *bp; ! 469: Point p0, p1, p2; ! 470: Code f; ! 471: { ! 472: if(a==0) ! 473: segment(bp, Pt(p0.x, p1.y), Pt(p0.x, p2.y), f); ! 474: else if(b==0) ! 475: segment(bp, Pt(p1.x, p0.y), Pt(p2.x, p0.y), f); ! 476: else{ ! 477: int sx1; ! 478: int sy1; ! 479: int sx2; ! 480: int sy2; ! 481: ! 482: d1.s = sub(p1, p0); ! 483: d2.s = sub(p2, p0); ! 484: sx1 = sgn2(d1.s.x); ! 485: sy1 = sgn2(d1.s.y); ! 486: sx2 = sgn2(d2.s.x); ! 487: sy2 = sgn2(d2.s.y); ! 488: d1.s.x *= sx1; ! 489: d1.s.y *= sy1; ! 490: d2.s.x *= sx2; ! 491: d2.s.y *= sy2; ! 492: d1.e = d2.e = HUGE2; ! 493: survey(bp, Pt(0, b), f); ! 494: ellip1(bp, Pt(0, 0), a, b, survey, Pt(0,b), Pt(a, 0), f); ! 495: if(!eqpt(d1.m, d2.m)) ! 496: point(bp, d1.m, f); ! 497: ellip1(bp, p0, a, b, point, ! 498: Pt(d1.m.x*sx1, d1.m.y*sy1), ! 499: Pt(d2.m.x*sx2, d2.m.y*sy2), f); ! 500: } ! 501: } ! 502: ! 503: /* ! 504: dak's points routines for buffering X calls ! 505: */ ! 506: #ifdef X11 ! 507: #define PBSIZE 100 ! 508: #define flushpt() if (xpcnt) flushpoints(); ! 509: static XPoint xp[PBSIZE]; ! 510: static xpcnt; ! 511: #endif X11 ! 512: static Code fc; ! 513: static ispixmap; ! 514: static Bitmap *bitm; ! 515: ! 516: points (p) ! 517: Point p; ! 518: { ! 519: #ifdef SUNTOOLS ! 520: point(bitm,p,fc); ! 521: #endif SUNTOOLS ! 522: #ifdef X11 ! 523: register XPoint *x; ! 524: ! 525: if(ispixmap) ! 526: p = sub(p, bitm->rect.origin); ! 527: x = &xp[xpcnt]; ! 528: x->x = p.x; ! 529: x->y = p.y; ! 530: if (++xpcnt == PBSIZE) ! 531: flushpoints(); ! 532: #endif X11 ! 533: } ! 534: ! 535: initpoints (b, f) ! 536: Bitmap *b; ! 537: Code f; ! 538: { ! 539: if(b->flag & BI_OFFSCREEN) ! 540: ispixmap = 1; ! 541: else { ! 542: #ifdef SUNTOOLS ! 543: struct rect lkrect; ! 544: if(!(b->flag & BI_OFFSCREEN)){ ! 545: win_getsize(displayfd, &lkrect); ! 546: pw_lock((Pixwin *)b->dr, &lkrect); ! 547: } ! 548: #endif SUNTOOLS ! 549: ispixmap = 0; ! 550: } ! 551: bitm = b; ! 552: #ifdef X11 ! 553: XSetFunction(dpy, gc, f); ! 554: #endif X11 ! 555: fc = f; ! 556: } ! 557: ! 558: endpoints() ! 559: { ! 560: #ifdef SUNTOOLS ! 561: if(!ispixmap) ! 562: pw_unlock((Pixwin *)bitm->dr); ! 563: #endif SUNTOOLS ! 564: #ifdef X11 ! 565: flushpt(); ! 566: #endif X11 ! 567: } ! 568: ! 569: #ifdef X11 ! 570: flushpoints() ! 571: { ! 572: if(xpcnt){ ! 573: XDrawPoints(dpy, bitm->dr, gc, xp, xpcnt, CoordModeOrigin); ! 574: xpcnt = 0; ! 575: } ! 576: } ! 577: #endif X11
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.