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

unix.superglobalmegacorp.com

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