# 2.11BSD#431 - /usr/src/usr.bin/plot/crtplot.c

##### Functions

    arc               X
    circle            X
    closepl           X
    cont              X
    dda_line          X
    label             X
    line              X
    linemod           X
    openpl            X
    plot_addch        X
    plot_erase        X
    plot_move         X
    point             X
    screen_move       X
    space             X

##### Macros

    plot_movech       X
    scaleX            X
    scaleY            X
    side              X

       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: }

#### Defined functions

arc defined in line 221; used 2 times

- in line 213-214(2)

circle defined in line 210; never used
closepl defined in line 84; used 2 times

- in line 72-77(2)

cont defined in line 151; never used
dda_line defined in line 177; used 3 times

- in line 107, 154, 283

label defined in line 110; never used
line defined in line 103; never used
linemod defined in line 168; never used
openpl defined in line 69; never used
plot_addch defined in line 51; used 3 times

- in line 26, 119, 205

plot_erase defined in line 122; used 1 times

- in /usr/src/usr.bin/plot/crtdriver.c line 78

plot_move defined in line 95; used 3 times

- in line 26, 281
- in /usr/src/usr.bin/plot/crtdriver.c line 64

point defined in line 144; used 1 times

- in line 245

screen_move defined in line 38; used 2 times

- in line 98, 204

space defined in line 158; never used

#### Defined variables

lastX defined in line 31; used 10 times

- in line 43-45(2), 55-60(3), 116-117(2), 139, 154, 283

lastY defined in line 31; used 6 times

- in line 43-44(2), 58, 140, 154, 283

lowX defined in line 29; used 2 times

- in line 23, 161

lowY defined in line 30; used 2 times

- in line 24, 162

rangeX defined in line 29; used 4 times

- in line 23, 163, 233(2)

rangeY defined in line 30; used 4 times

- in line 24, 164, 233(2)

sccsid defined in line 2; never used

#### Defined macros

plot_movech defined in line 26; used 2 times

- in line 106, 147

scaleX defined in line 23; used 5 times

- in line 98, 107(2), 154, 283

scaleY defined in line 24; used 5 times

- in line 98, 107(2), 154, 283

side defined in line 219; used 2 times

- in line 276, 291

Last modified: 1987-02-17 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 831 |