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
circle defined in line 210; never used
closepl defined in line 84; used 2 times
cont defined in line 151; never used
dda_line defined in line 177; used 3 times
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
plot_erase defined in line 122; used 1 times
plot_move defined in line 95; used 3 times
point defined in line 144; used 1 times
screen_move defined in line 38; used 2 times
space defined in line 158; never used

Defined variables

lastX defined in line 31; used 10 times
lastY defined in line 31; used 6 times
lowX defined in line 29; used 2 times
lowY defined in line 30; used 2 times
rangeX defined in line 29; used 4 times
rangeY defined in line 30; used 4 times
sccsid defined in line 2; never used

Defined macros

plot_movech defined in line 26; used 2 times
scaleX defined in line 23; used 5 times
scaleY defined in line 24; used 5 times
side defined in line 219; used 2 times
Last modified: 1987-02-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3326
Valid CSS Valid XHTML 1.0 Strict