Annotation of researchv8dc/cmd/grap/ticks.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include "grap.h"
                      3: #include "y.tab.h"
                      4: 
                      5: #define        MAXTICK 200
                      6: int    ntick   = 0;
                      7: double tickval[MAXTICK];       /* tick values (one axis at a time */
                      8: char   *tickstr[MAXTICK];      /* and labels */
                      9: 
                     10: int    tside   = 0;
                     11: int    tlist   = 0;            /* 1 => explicit values given */
                     12: int    toffside = 0;           /* no ticks on these sides */
                     13: int    tick_dir = OUT;
                     14: double ticklen = TICKLEN;      /* default tick length */
                     15: int    autoticks = LEFT|BOT;
                     16: 
                     17: savetick(f, s) /* remember tick location and label */
                     18:        double f;
                     19:        char *s;
                     20: {
                     21:        if (ntick >= MAXTICK)
                     22:                fatal("too many ticks (%d)", MAXTICK);
                     23:        tickval[ntick] = f;
                     24:        tickstr[ntick] = s;
                     25:        ntick++;
                     26: }
                     27: 
                     28: tickside(n)    /* remember which side these ticks go on */
                     29:        int n;
                     30: {
                     31:        tside |= n;
                     32: }
                     33: 
                     34: tickoff(side)  /* remember explicit sides */
                     35:        int side;
                     36: {
                     37:        toffside |= side;
                     38: }
                     39: 
                     40: setlist()      /* remember that there was an explicit list */
                     41: {
                     42:        tlist = 1;
                     43: }
                     44: 
                     45: tickdir(dir, val, explicit)    /* remember in/out [expr] */
                     46:        int dir, explicit;
                     47:        double val;
                     48: {
                     49:        tick_dir = dir;
                     50:        if (explicit)
                     51:                ticklen = val;
                     52: }
                     53: 
                     54: ticks()                /* set autoticks after ticks statement */
                     55: {
                     56:        /* was there an explicit "ticks [side] off"? */
                     57:        if (toffside)
                     58:                autoticks &= ~toffside;
                     59:        /* was there an explicit list? */
                     60:        if (tlist) {
                     61:                if (tside & (BOT|TOP))
                     62:                        autoticks &= ~(BOT|TOP);
                     63:                if (tside & (LEFT|RIGHT))
                     64:                        autoticks &= ~(LEFT|RIGHT);
                     65:        }
                     66:        /* was there a side without a list? */
                     67:        if (tside && !tlist) {
                     68:                if (tside & (BOT|TOP))
                     69:                        autoticks = (autoticks & ~(BOT|TOP)) | (tside & (BOT|TOP));
                     70:                if (tside & (LEFT|RIGHT))
                     71:                        autoticks = (autoticks & ~(LEFT|RIGHT)) | (tside & (LEFT|RIGHT));
                     72:        }
                     73:        tlist = tside = toffside = 0;
                     74: }
                     75: 
                     76: double modfloor(f, t)
                     77:        double f, t;
                     78: {
                     79:        t = fabs(t);
                     80:        return floor(f/t) * t;
                     81: }
                     82: 
                     83: double modceil(f, t)
                     84:        double f, t;
                     85: {
                     86:        t = fabs(t);
                     87:        return ceil(f/t) * t;
                     88: }
                     89: 
                     90: double xtmin, xtmax;   /* range of ticks */
                     91: double ytmin, ytmax;
                     92: double xquant, xmult;  /* quantization & scale for auto x ticks */
                     93: double yquant, ymult;
                     94: double lograt = 5;
                     95: 
                     96: do_autoticks(p)        /* make set of ticks for default coord only */
                     97:        Obj *p;
                     98: {
                     99:        double x, xl, xu, q;
                    100: 
                    101:        if (p == NULL)
                    102:                return;
                    103:        fprintf(tfd, "Autoticks:\t# x %g..%g, y %g..%g",
                    104:                p->pt.x, p->pt1.x, p->pt.y, p->pt1.y);
                    105:        fprintf(tfd, ";   xt %g,%g, yt %g,%g, xq,xm = %g,%g, yq,ym = %g,%g\n",
                    106:                xtmin, xtmax, ytmin, ytmax, xquant, xmult, yquant, ymult);
                    107:        if ((autoticks & (BOT|TOP)) && p->pt1.x > p->pt.x) {    /* make x ticks */
                    108:                q = xquant;
                    109:                xl = p->pt.x;
                    110:                xu = p->pt1.x;
                    111:                if ((p->log & XFLAG) && xu/xl >= lograt) {
                    112:                        for (x = q; x < xu; x *= 10) {
                    113:                                logtick(x, xl, xu);
                    114:                                if (xu/xl <= 100) {
                    115:                                        logtick(2*x, xl, xu);
                    116:                                        logtick(5*x, xl, xu);
                    117:                                }
                    118:                        }
                    119:                } else {
                    120:                        xl = modceil(xtmin - q/100, q);
                    121:                        xu = modfloor(xtmax + q/100, q) + q/2;
                    122:                        for (x = xl; x <= xu; x += q)
                    123:                                savetick(x, tostring("%g"));
                    124:                }
                    125:                tside = autoticks & (BOT|TOP);
                    126:                ticklist(p);
                    127:        }
                    128:        if ((autoticks & (LEFT|RIGHT)) && p->pt1.y > p->pt.y) { /* make y ticks */
                    129:                q = yquant;
                    130:                xl = p->pt.y;
                    131:                xu = p->pt1.y;
                    132:                if ((p->log & YFLAG) && xu/xl >= lograt) {
                    133:                        for (x = q; x < xu; x *= 10) {
                    134:                                logtick(x, xl, xu);
                    135:                                if (xu/xl <= 100) {
                    136:                                        logtick(2*x, xl, xu);
                    137:                                        logtick(5*x, xl, xu);
                    138:                                }
                    139:                        }
                    140:                } else {
                    141:                        xl = modceil(ytmin - q/100, q);
                    142:                        xu = modfloor(ytmax + q/100, q) + q/2;
                    143:                        for (x = xl; x <= xu; x += q)
                    144:                                savetick(x, tostring("%g"));
                    145:                }
                    146:                tside = autoticks & (LEFT|RIGHT);
                    147:                ticklist(p);
                    148:        }
                    149: }
                    150: 
                    151: logtick(v, lb, ub)
                    152:        double v, lb, ub;
                    153: {
                    154:        float slop = 1.0;       /* was 1.001 */
                    155: 
                    156:        if (slop * lb <= v && ub >= slop * v)
                    157:                savetick(v, tostring("%g"));
                    158: }
                    159: 
                    160: Obj *setauto() /* compute new min,max, and quant & mult */
                    161: {
                    162:        Obj *p, *q;
                    163: 
                    164:        if ((q = lookup("lograt",0)) != NULL)
                    165:                lograt = q->fval;
                    166:        for (p = objlist; p; p = p->next)
                    167:                if (p->type == NAME && strcmp(p->name,dflt_coord) == 0)
                    168:                        break;
                    169:        if (p) {
                    170:                if ((p->log & XFLAG) && p->pt1.x/p->pt.x >= lograt)
                    171:                        autolog(p, 'x');
                    172:                else
                    173:                        autoside(p, 'x');
                    174:                if ((p->log & YFLAG) && p->pt1.y/p->pt.y >= lograt)
                    175:                        autolog(p, 'y');
                    176:                else
                    177:                        autoside(p, 'y');
                    178:        }
                    179:        return p;
                    180: }
                    181: 
                    182: autoside(p, side)
                    183:        Obj *p;
                    184:        int side;
                    185: {
                    186:        double r, s, d, ub, lb;
                    187: 
                    188:        if (side == 'x') {
                    189:                xtmin = lb = p->pt.x;
                    190:                xtmax = ub = p->pt1.x;
                    191:        } else {
                    192:                ytmin = lb = p->pt.y;
                    193:                ytmax = ub = p->pt1.y;
                    194:        }
                    195:        if (ub <= lb)
                    196:                return 0;       /* cop out on little ranges */
                    197:        d = ub - lb;
                    198:        r = s = 1;
                    199:        while (d * s < 10)
                    200:                s *= 10;
                    201:        d *= s;
                    202:        lb *= s;
                    203:        ub *= s;
                    204:        while (10 * r < d)
                    205:                r *= 10;
                    206:        if (r > d/3)
                    207:                r /= 2;
                    208:        else if (r <= d/6)
                    209:                r *= 2;
                    210:        if (side == 'x') {
                    211:                xquant = r / s;
                    212:        } else {
                    213:                yquant = r / s;
                    214:        }
                    215: }
                    216: 
                    217: autolog(p, side)
                    218:        Obj *p;
                    219:        int side;
                    220: {
                    221:        double r, s, t, d, ub, lb;
                    222:        int flg;
                    223: 
                    224:        if (side == 'x') {
                    225:                xtmin = lb = p->pt.x;
                    226:                xtmax = ub = p->pt1.x;
                    227:                flg = p->coord & XFLAG;
                    228:        } else {
                    229:                ytmin = lb = p->pt.y;
                    230:                ytmax = ub = p->pt1.y;
                    231:                flg = p->coord & YFLAG;
                    232:        }
                    233:        for (s = 1; lb * s < 1; s *= 10)
                    234:                ;
                    235:        lb *= s;
                    236:        ub *= s;
                    237:        for (r = 1; 10 * r < lb; r *= 10)
                    238:                ;
                    239:        for (t = 1; t < ub; t *= 10)
                    240:                ;
                    241:        if (side == 'x')
                    242:                xquant = r / s;
                    243:        else
                    244:                yquant = r / s;
                    245:        if (flg)
                    246:                return;
                    247:        if (ub / lb < 100) {
                    248:                if (lb >= 5 * r)
                    249:                        r *= 5;
                    250:                else if (lb >= 2 * r)
                    251:                        r *= 2;
                    252:                if (ub * 5 <= t)
                    253:                        t /= 5;
                    254:                else if (ub * 2 <= t)
                    255:                        t /= 2;
                    256:                if (side == 'x') {
                    257:                        xtmin = r / s;
                    258:                        xtmax = t / s;
                    259:                } else {
                    260:                        ytmin = r / s;
                    261:                        ytmax = t / s;
                    262:                }
                    263:        }
                    264: }
                    265: 
                    266: iterator(from, to, op, by, fmt)        /* create an iterator */
                    267:        double from, to, by;
                    268:        int op;
                    269:        char *fmt;
                    270: {
                    271:        double x;
                    272: 
                    273:        /* should validate limits, etc. */
                    274:        /* punt for now */
                    275: 
                    276:        if (fmt == NULL)
                    277:                fmt = tostring("%g");
                    278:        dprintf("iterate from %g to %g by %g, op = %c, fmt=%s\n",
                    279:                from, to, by, op, fmt);
                    280:        switch (op) {
                    281:        case '+':
                    282:        case ' ':
                    283:                for (x = from; x <= SLOP * to; x += by)
                    284:                        savetick(x, tostring(fmt));
                    285:                break;
                    286:        case '-':
                    287:                for (x = from; x >= to; x -= by)
                    288:                        savetick(x, tostring(fmt));
                    289:                break;
                    290:        case '*':
                    291:                for (x = from; x <= SLOP * to; x *= by)
                    292:                        savetick(x, tostring(fmt));
                    293:                break;
                    294:        case '/':
                    295:                for (x = from; x >= to; x /= by)
                    296:                        savetick(x, tostring(fmt));
                    297:                break;
                    298:        }
                    299:        if (fmt)
                    300:                free(fmt);
                    301: }
                    302: 
                    303: ticklist(p)    /* fire out the accumulated ticks */
                    304:        Obj *p;
                    305: {
                    306:        if (p == NULL)
                    307:                return;
                    308:        fprintf(tfd, "Ticks_%s:\n\tticklen = %g\n", p->name, ticklen);
                    309:        print_ticks(TICKS, p, "ticklen", "");
                    310: }
                    311: 
                    312: print_ticks(type, p, lenstr, descstr)
                    313:        int type;
                    314:        Obj *p;
                    315:        char *lenstr, *descstr;
                    316: {
                    317:        int i, logflag;
                    318:        char buf[100];
                    319:        double tv;
                    320: 
                    321:        for (i = 0; i < ntick; i++)     /* any ticks given explicitly? */
                    322:                if (tickstr[i] != NULL)
                    323:                        break;
                    324:        if (i >= ntick && type == TICKS)        /* no, so use values */
                    325:                for (i = 0; i < ntick; i++) {
                    326:                        sprintf(buf, "%g", tickval[i]);
                    327:                        tickstr[i] = tostring(buf);
                    328:                }
                    329:        else
                    330:                for (i = 0; i < ntick; i++) {
                    331:                        if (tickstr[i] != NULL) {
                    332:                                sprintf(buf, tickstr[i], tickval[i]);
                    333:                                free(tickstr[i]);
                    334:                                tickstr[i] = tostring(buf);
                    335:                        }
                    336:                }
                    337:        logflag = sidelog(p->log, tside);
                    338:        for (i = 0; i < ntick; i++) {
                    339:                tv = tickval[i];
                    340:                halfrange(p, tside, tv);
                    341:                if (logflag) {
                    342:                        if (tv <= 0.0)
                    343:                                fatal("can't take log of tick value %g", tv);
                    344:                        logit(tv);
                    345:                }
                    346:                if (tside & BOT)
                    347:                        maketick(p->name, BOT, tv, tickstr[i], lenstr, descstr);
                    348:                if (tside & TOP)
                    349:                        maketick(p->name, TOP, tv, tickstr[i], lenstr, descstr);
                    350:                if (tside & LEFT)
                    351:                        maketick(p->name, LEFT, tv, tickstr[i], lenstr, descstr);
                    352:                if (tside & RIGHT)
                    353:                        maketick(p->name, RIGHT, tv, tickstr[i], lenstr, descstr);
                    354:                if (tickstr[i]) {
                    355:                        free(tickstr[i]);
                    356:                        tickstr[i] = NULL;
                    357:                }
                    358:        }
                    359:        ntick = 0;
                    360: }
                    361: 
                    362: maketick(name, side, val, lab, lenstr, descstr)
                    363:        char *name;
                    364:        int side;
                    365:        double val;
                    366:        char *lab, *lenstr, *descstr;
                    367: {
                    368:        char *sidestr, *td;
                    369: 
                    370:        fprintf(tfd, "\tline %s ", descstr);
                    371:        switch (side) {
                    372:        case BOT:
                    373:        case 0:
                    374:                td = tick_dir == IN ? "up" : "down";
                    375:                fprintf(tfd, "%s %s from (x_%s(%g),0)", td, lenstr, name, val);
                    376:                break;
                    377:        case TOP:
                    378:                td = tick_dir == IN ? "down" : "up";
                    379:                fprintf(tfd, "%s %s from (x_%s(%g),frameht)", td, lenstr, name, val);
                    380:                break;
                    381:        case LEFT:
                    382:                td = tick_dir == IN ? "right" : "left";
                    383:                fprintf(tfd, "%s %s from (0,y_%s(%g))", td, lenstr, name, val);
                    384:                break;
                    385:        case RIGHT:
                    386:                td = tick_dir == IN ? "left" : "right";
                    387:                fprintf(tfd, "%s %s from (framewid,y_%s(%g))", td, lenstr, name, val);
                    388:                break;
                    389:        }
                    390:        fprintf(tfd, "\n");
                    391:        sidestr = tick_dir == IN ? "start" : "end";
                    392:        if (lab != NULL) {
                    393:                /* BUG: should fix size of lab here */
                    394:                switch (side) {
                    395:                case BOT: case 0:
                    396:                        /* can drop "box invis" with new pic */
                    397:                        fprintf(tfd, "\tbox invis \"%s\" ht .25 wid 0 with .n at last line.%s",
                    398:                                lab, sidestr);
                    399:                        break;
                    400:                case TOP:
                    401:                        fprintf(tfd, "\tbox invis \"%s\" ht .2 wid 0 with .s at last line.%s",
                    402:                                lab, sidestr);
                    403:                        break;
                    404:                case LEFT:
                    405:                        fprintf(tfd, "\t\"%s \" rjust at last line.%s",
                    406:                                lab, sidestr);
                    407:                        break;
                    408:                case RIGHT:
                    409:                        fprintf(tfd, "\t\" %s\" ljust at last line.%s",
                    410:                                lab, sidestr);
                    411:                        break;
                    412:                }
                    413:                /* BUG: works only if "down x" comes before "at wherever" */
                    414:                lab_adjust();
                    415:                fprintf(tfd, "\n");
                    416:        }
                    417: }
                    418: 
                    419: Attr   *grid_desc      = 0;
                    420: 
                    421: griddesc(a)
                    422:        Attr *a;
                    423: {
                    424:        grid_desc = a;
                    425: }
                    426: 
                    427: gridlist(p)
                    428:        Obj *p;
                    429: {
                    430:        int i, logflag;
                    431:        double tv;
                    432:        char *framestr;
                    433: 
                    434:        if ((tside & (BOT|TOP)) || tside == 0)
                    435:                framestr = "frameht";
                    436:        else
                    437:                framestr = "framewid";
                    438:        fprintf(tfd, "Grid_%s:\n", p->name);
                    439:        tick_dir = IN;
                    440:        print_ticks(GRID, p, framestr, desc_str(grid_desc));
                    441:        if (grid_desc) {
                    442:                freeattr(grid_desc);
                    443:                free(grid_desc);
                    444:                grid_desc = 0;
                    445:        }
                    446: }
                    447: 
                    448: char *desc_str(a)      /* convert DOT to "dotted", etc. */
                    449:        Attr *a;
                    450: {
                    451:        static char buf[50], *p;
                    452: 
                    453:        if (a == NULL)
                    454:                return p = "";
                    455:        switch (a->type) {
                    456:        case DOT:       p = "dotted"; break;
                    457:        case DASH:      p = "dashed"; break;
                    458:        case INVIS:     p = "invis"; break;
                    459:        default:        p = "";
                    460:        }
                    461:        if (a->fval != 0.0) {
                    462:                sprintf(buf, "%s %g", p, a->fval);
                    463:                return buf;
                    464:        } else
                    465:                return p;
                    466: }
                    467: 
                    468: sidelog(logflag, side) /* figure out whether to scale a side */
                    469:        int logflag, side;
                    470: {
                    471:        if ((logflag & XFLAG) && ((side & (BOT|TOP)) || side == 0))
                    472:                return 1;
                    473:        else if ((logflag & YFLAG) && (side & (LEFT|RIGHT)))
                    474:                return 1;
                    475:        else
                    476:                return 0;
                    477: }

unix.superglobalmegacorp.com

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