Annotation of 43BSD/usr.bin/plot/crtplot.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)crtplot.c  4.1 (Berkeley) 11/11/83";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6: This plotting routine interprets plot commands and outputs them onto
        !             7: intelligent terminals (ie, terminals with clear screen and cursor
        !             8: addressability.  It uses the curses library.  It should be compiled
        !             9: as follows:
        !            10:        cc crtdriver.c crtplot.c -lcurses -ltermcap -lm
        !            11: Note:  This requires as slightly modified driver from the standard driver
        !            12: because some function names conflicted with the curses library.
        !            13: (That's what you get when you have a flat name space!)
        !            14: */
        !            15: 
        !            16: 
        !            17: #include <curses.h>
        !            18: #include <math.h>
        !            19: #include <signal.h>
        !            20: 
        !            21: 
        !            22: /*  These map from plot routine coordinates to screen coordinates.  */
        !            23: #define scaleX(x)              (int) ((x-lowX)*rangeX + 0.5)
        !            24: #define scaleY(y)              (int) (LINES-0.5 - ((y-lowY)*rangeY))
        !            25: 
        !            26: #define plot_movech(y, x, ch)  { plot_move(x, y); plot_addch(ch); }
        !            27: 
        !            28: 
        !            29: static double lowX, rangeX;    /* min and range of x */
        !            30: static double lowY, rangeY;    /* min and range of y */
        !            31: static int lastX, lastY;       /* last point plotted */
        !            32: 
        !            33: 
        !            34: char *getenv();
        !            35: extern char _putchar(); 
        !            36: 
        !            37: /* This routine just moves the cursor. */
        !            38: screen_move(y, x)
        !            39: int x,y;
        !            40: {
        !            41:        /* must check for automatic wrap at last col */
        !            42:        if (!AM || (y < LINES -1) || (x < COLS -1)) {
        !            43:                mvcur(lastY, lastX, y, x);
        !            44:                lastY = y;
        !            45:                lastX = x;
        !            46:                }
        !            47: }
        !            48: 
        !            49: 
        !            50: /* This routine assumes the cursor is positioned correctly. */
        !            51: plot_addch(ch)
        !            52: char ch;
        !            53: {
        !            54:        putchar(ch);
        !            55:        if (++lastX >= COLS) {
        !            56:                if (AM) {
        !            57:                        lastX = 0;
        !            58:                        lastY++;
        !            59:                } else {
        !            60:                        lastX = COLS - 1;
        !            61:                        }
        !            62:                }
        !            63: }              
        !            64: 
        !            65: 
        !            66: 
        !            67: 
        !            68: /* See the curses manual for what is been done and why. */
        !            69: openpl()
        !            70: {
        !            71: char *sp;
        !            72: int closepl();
        !            73: 
        !            74: gettmode();
        !            75: if (sp=getenv("TERM"))
        !            76:        setterm(sp);
        !            77: signal(SIGINT, closepl);
        !            78: 
        !            79: }
        !            80: 
        !            81: 
        !            82: 
        !            83: 
        !            84: closepl()
        !            85: {
        !            86: signal(SIGINT, SIG_IGN);
        !            87: /* Leave cursor at top of screen. */
        !            88: mvcur(LINES-1, COLS-1, 0, 0);
        !            89: endwin();
        !            90: exit(0);
        !            91: }
        !            92: 
        !            93: 
        !            94: 
        !            95: plot_move(x,y)
        !            96: int x, y;
        !            97: {
        !            98: screen_move(scaleY(y), scaleX(x));
        !            99: }
        !           100: 
        !           101: 
        !           102: 
        !           103: line(x0, y0, x1, y1)
        !           104: int x0, y0, x1, y1;
        !           105: {
        !           106: plot_movech(y0, x0, '*');
        !           107: dda_line('*', scaleX(x0), scaleY(y0), scaleX(x1), scaleY(y1));
        !           108: }
        !           109: 
        !           110: label(str)
        !           111: char *str;
        !           112: {
        !           113:        reg i, length;
        !           114:        int strlen();
        !           115: 
        !           116:        if ( (length=strlen(str)) > (COLS-lastX) )
        !           117:                length = COLS - lastX;
        !           118:        for (i=0; i<length; ++i)
        !           119:                plot_addch(str[i]);
        !           120: }
        !           121: 
        !           122: plot_erase()
        !           123: {
        !           124: /*
        !           125: Some of these functions probably belong in openpl().  However, if the
        !           126: input is being typed in, putting them in openpl would not work
        !           127: since "noecho", etc would prevent (sort of) input.  Notice that
        !           128: the driver calls openpl before doing anything.  This is actually
        !           129: wrong, but it is what whoever originally wrote the driver decided
        !           130: to do.  (openpl() in libplot does nothing -- that is the main problem!)
        !           131: */
        !           132: _puts(TI);
        !           133: _puts(VS);
        !           134: 
        !           135: noecho();
        !           136: nonl();
        !           137: tputs(CL, LINES, _putchar);
        !           138: mvcur(0, COLS-1, LINES-1, 0);
        !           139: lastX = 0;
        !           140: lastY = LINES-1;
        !           141: }
        !           142: 
        !           143: 
        !           144: point(x, y)
        !           145: int x,y;
        !           146: {
        !           147: plot_movech(y, x, '*');
        !           148: }
        !           149: 
        !           150: 
        !           151: cont(x, y)
        !           152: int x,y;
        !           153: {
        !           154: dda_line('*', lastX-1, lastY, scaleX(x), scaleY(y));
        !           155: }
        !           156: 
        !           157: 
        !           158: space(x0, y0, x1, y1)
        !           159: int x0, y0, x1, y1;
        !           160: {
        !           161: lowX = (double) x0;
        !           162: lowY = (double) y0;
        !           163: rangeX = COLS/(double) (x1 - x0);
        !           164: rangeY = LINES/(double) (y1 - y0);
        !           165: }
        !           166: 
        !           167: 
        !           168: linemod(string)
        !           169: char *string;
        !           170: {
        !           171: }
        !           172: 
        !           173: 
        !           174: 
        !           175: /* See Neuman & Sproul for explanation and rationale. */
        !           176: /* Does not plot first point -- assumed that it is already plotted */
        !           177: dda_line(ch, x0, y0, x1, y1)
        !           178: char ch;
        !           179: int x0, y0, x1, y1;    /* already transformed to screen coords */
        !           180: {
        !           181:        int length, i;
        !           182:        double deltaX, deltaY;
        !           183:        double x, y;
        !           184:        double floor();
        !           185:        int abs();
        !           186: 
        !           187: length = abs(x1 - x0);
        !           188: if (abs(y1 -y0) > length)
        !           189:        length = abs(y1 - y0);
        !           190: 
        !           191: if (length == 0)
        !           192:        return;
        !           193: 
        !           194: deltaX = (double) (x1 - x0)/(double) length;
        !           195: deltaY = (double) (y1 - y0)/(double) length;
        !           196: 
        !           197: x = (double) x0 + 0.5;
        !           198: y = (double) y0 + 0.5;
        !           199: 
        !           200: for (i=0; i < length; ++i)
        !           201:        {
        !           202:        x += deltaX;
        !           203:        y += deltaY;
        !           204:        screen_move((int) floor(y), (int) floor(x));
        !           205:        plot_addch(ch);
        !           206:        }
        !           207: }
        !           208: 
        !           209: 
        !           210: circle (xc,yc,r)
        !           211: int xc,yc,r;
        !           212: {
        !           213:        arc(xc,yc, xc+r,yc, xc-r,yc);
        !           214:        arc(xc,yc, xc-r,yc, xc+r,yc);
        !           215: }
        !           216: 
        !           217: 
        !           218: /* should include test for equality? */
        !           219: #define side(x,y)      (a*(x)+b*(y)+c > 0.0 ? 1 : -1)
        !           220: 
        !           221: arc(xc,yc,xbeg,ybeg,xend,yend)
        !           222: int xc,yc,xbeg,ybeg,xend,yend;
        !           223: {
        !           224:        double r, radius, costheta, sintheta;
        !           225:        double a, b, c, x, y, tempX;
        !           226:        int right_side;
        !           227: 
        !           228:        xbeg -= xc; ybeg -= yc;
        !           229:        xend -= xc; yend -= yc;
        !           230: 
        !           231:        /* probably should check that arc is truely circular */
        !           232:        /* Note: r is in screen coordinates. */
        !           233:        r = sqrt( rangeX*rangeX*xbeg*xbeg + rangeY*rangeY*ybeg*ybeg);
        !           234: 
        !           235:        /*
        !           236:        This method is reasonably efficient, clean, and clever.
        !           237:        The easy part is generating the next point on the arc.  This is
        !           238:        done by rotating the points by the angle theta.  Theta is chosen
        !           239:        so that no rotation will cause more than one pixel of a move.
        !           240:        This corresponds to a triangle having 'x side' of r and 'y side' of 1.
        !           241:        The rotation is done (way) below inside the loop.
        !           242:        */
        !           243:        if (r <= 1.0) {
        !           244:                /* radius is mapped to length < 1*/
        !           245:                point(xc,yc);
        !           246:                return;
        !           247:                }
        !           248: 
        !           249:        radius = sqrt(r*r + 1.0);
        !           250:        sintheta = 1.0/radius;
        !           251:        costheta = r/radius;
        !           252: 
        !           253:        /*
        !           254:        The hard part of drawing an arc is figuring out when to stop.
        !           255:        This method works by drawing the line from the beginning point
        !           256:        to the ending point.  This splits the plane in half, with the
        !           257:        arc that we wish to draw on one side of the line.  If we evaluate
        !           258:        side(x,y) = a*x + b*y + c, then all of the points on one side of the
        !           259:        line will result in side being positive, and all the points on the
        !           260:        other side of the line will result in side being negative.
        !           261: 
        !           262:        We want to draw the arc in a counter-clockwise direction, so we
        !           263:        must find out what the sign of "side" is for a point which is to the 
        !           264:        "right" of a line drawn from "beg" to "end".  A point which must lie 
        !           265:        on the right is [xbeg + (yend-ybeg), ybeg - (xend-xbeg)].  (This
        !           266:        point is perpendicular to the line at "beg").
        !           267: 
        !           268:        Thus, we compute "side" of the above point, and then compare the
        !           269:        sign of side for each new point with the sign of the above point.
        !           270:        When they are different, we terminate the loop.
        !           271:        */
        !           272: 
        !           273:        a = (double) (yend - ybeg);
        !           274:        b = (double) (xend - xbeg);
        !           275:        c = (double) (yend*xbeg - xend*ybeg);
        !           276:        right_side = side(xbeg + (yend-ybeg),
        !           277:                          ybeg - (xend-xbeg) );
        !           278: 
        !           279:        x = xbeg;
        !           280:        y = ybeg;
        !           281:        plot_move(xbeg+xc, ybeg+yc);
        !           282:        do {
        !           283:                dda_line('*',lastX-1, lastY, scaleX(xc + x), scaleY(yc + y ));
        !           284:                /*
        !           285:                screen_move( scaleY(yc + y), scaleX(xc + x) );
        !           286:                plot_addch('*');
        !           287:                */
        !           288:                tempX = x;
        !           289:                x = x*costheta - y*sintheta;
        !           290:                y = tempX*sintheta + y*costheta;
        !           291:        } while( side(x,y) == right_side );
        !           292: }

unix.superglobalmegacorp.com

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