Annotation of researchv9/jtools/src/sunlib/circle.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.