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

unix.superglobalmegacorp.com

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