Annotation of 43BSDTahoe/usr.bin/plot/crtplot.c, revision 1.1.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.