summaryrefslogtreecommitdiff
path: root/usr/src/ucbcmd/plot/crtplot.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/ucbcmd/plot/crtplot.c
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/ucbcmd/plot/crtplot.c')
-rw-r--r--usr/src/ucbcmd/plot/crtplot.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/usr/src/ucbcmd/plot/crtplot.c b/usr/src/ucbcmd/plot/crtplot.c
new file mode 100644
index 0000000000..5eeefb2f65
--- /dev/null
+++ b/usr/src/ucbcmd/plot/crtplot.c
@@ -0,0 +1,305 @@
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+
+
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * Copyright (c) 1983, 1984 1985, 1986, 1987, 1988, Sun Microsystems, Inc.
+ * All Rights Reserved.
+ */
+
+
+/*
+This plotting routine interprets plot commands and outputs them onto
+intelligent terminals (ie, terminals with clear screen and cursor
+addressability. It uses the curses library. It should be compiled
+as follows:
+ cc crtdriver.c crtplot.c -lcurses -ltermcap -lm
+Note: This requires as slightly modified driver from the standard driver
+because some function names conflicted with the curses library.
+(That's what you get when you have a flat name space!)
+*/
+
+
+#include <curses.h>
+#include <math.h>
+#include <signal.h>
+
+/* These map from plot routine coordinates to screen coordinates. */
+#define scaleX(x) (int) ((x-lowX)*rangeX + 0.5)
+#define scaleY(y) (int) (LINES-0.5 - ((y-lowY)*rangeY))
+
+#define plot_movech(y, x, ch) { plot_move(x, y); plot_addch(ch); }
+
+
+static double lowX, rangeX; /* min and range of x */
+static double lowY, rangeY; /* min and range of y */
+static int lastX, lastY; /* last point plotted */
+
+
+char *getenv();
+/* This routine just moves the cursor. */
+screen_move(y, x)
+int x,y;
+{
+ /* must check for automatic wrap at last col */
+ if (!AM || (y < LINES -1) || (x < COLS -1)) {
+ mvcur(lastY, lastX, y, x);
+ lastY = y;
+ lastX = x;
+ }
+}
+
+
+/* This routine assumes the cursor is positioned correctly. */
+plot_addch(ch)
+char ch;
+{
+ putchar(ch);
+ if (++lastX >= COLS) {
+ if (AM) {
+ lastX = 0;
+ lastY++;
+ } else {
+ lastX = COLS - 1;
+ }
+ }
+}
+
+
+
+
+/* See the curses manual for what is been done and why. */
+openpl()
+{
+char *sp;
+void closepl();
+
+gettmode();
+if (sp=getenv("TERM"))
+ setterm(sp);
+signal(SIGINT, closepl);
+
+}
+
+
+
+
+void closepl()
+{
+signal(SIGINT, SIG_IGN);
+/* Leave cursor at top of screen. */
+mvcur(LINES-1, COLS-1, 0, 0);
+endwin();
+exit(0);
+}
+
+
+
+plot_move(x,y)
+int x, y;
+{
+screen_move(scaleY(y), scaleX(x));
+}
+
+
+
+line(x0, y0, x1, y1)
+int x0, y0, x1, y1;
+{
+plot_movech(y0, x0, '*');
+dda_line('*', scaleX(x0), scaleY(y0), scaleX(x1), scaleY(y1));
+}
+
+label(str)
+char *str;
+{
+ reg i, length;
+ int strlen();
+
+ if ( (length=strlen(str)) > (COLS-lastX) )
+ length = COLS - lastX;
+ for (i=0; i<length; ++i)
+ plot_addch(str[i]);
+}
+
+plot_erase()
+{
+int _putchar();
+/*
+Some of these functions probably belong in openpl(). However, if the
+input is being typed in, putting them in openpl would not work
+since "noecho", etc would prevent (sort of) input. Notice that
+the driver calls openpl before doing anything. This is actually
+wrong, but it is what whoever originally wrote the driver decided
+to do. (openpl() in libplot does nothing -- that is the main problem!)
+*/
+_puts(TI);
+_puts(VS);
+
+noecho();
+nonl();
+tputs(CL, LINES, _putchar);
+mvcur(0, COLS-1, LINES-1, 0);
+lastX = 0;
+lastY = LINES-1;
+}
+
+
+point(x, y)
+int x,y;
+{
+plot_movech(y, x, '*');
+}
+
+
+cont(x, y)
+int x,y;
+{
+dda_line('*', lastX-1, lastY, scaleX(x), scaleY(y));
+}
+
+
+space(x0, y0, x1, y1)
+int x0, y0, x1, y1;
+{
+lowX = (double) x0;
+lowY = (double) y0;
+rangeX = COLS/(double) (x1 - x0);
+rangeY = LINES/(double) (y1 - y0);
+}
+
+
+linemod(string)
+char *string;
+{
+}
+
+
+
+/* See Neuman & Sproul for explanation and rationale. */
+/* Does not plot first point -- assumed that it is already plotted */
+dda_line(ch, x0, y0, x1, y1)
+char ch;
+int x0, y0, x1, y1; /* already transformed to screen coords */
+{
+ int length, i;
+ double deltaX, deltaY;
+ double x, y;
+ double floor();
+ int abs();
+
+length = abs(x1 - x0);
+if (abs(y1 -y0) > length)
+ length = abs(y1 - y0);
+
+if (length == 0)
+ return;
+
+deltaX = (double) (x1 - x0)/(double) length;
+deltaY = (double) (y1 - y0)/(double) length;
+
+x = (double) x0 + 0.5;
+y = (double) y0 + 0.5;
+
+for (i=0; i < length; ++i)
+ {
+ x += deltaX;
+ y += deltaY;
+ screen_move((int) floor(y), (int) floor(x));
+ plot_addch(ch);
+ }
+}
+
+
+circle (xc,yc,r)
+int xc,yc,r;
+{
+ arc(xc,yc, xc+r,yc, xc-r,yc);
+ arc(xc,yc, xc-r,yc, xc+r,yc);
+}
+
+
+/* should include test for equality? */
+#define side(x,y) (a*(x)+b*(y)+c > 0.0 ? 1 : -1)
+
+arc(xc,yc,xbeg,ybeg,xend,yend)
+int xc,yc,xbeg,ybeg,xend,yend;
+{
+ double r, radius, costheta, sintheta;
+ double a, b, c, x, y, tempX;
+ int right_side;
+
+ xbeg -= xc; ybeg -= yc;
+ xend -= xc; yend -= yc;
+
+ /* probably should check that arc is truely circular */
+ /* Note: r is in screen coordinates. */
+ r = sqrt( rangeX*rangeX*xbeg*xbeg + rangeY*rangeY*ybeg*ybeg);
+
+ /*
+ This method is reasonably efficient, clean, and clever.
+ The easy part is generating the next point on the arc. This is
+ done by rotating the points by the angle theta. Theta is chosen
+ so that no rotation will cause more than one pixel of a move.
+ This corresponds to a triangle having 'x side' of r and 'y side' of 1.
+ The rotation is done (way) below inside the loop.
+ */
+ if (r <= 1.0) {
+ /* radius is mapped to length < 1*/
+ point(xc,yc);
+ return;
+ }
+
+ radius = sqrt(r*r + 1.0);
+ sintheta = 1.0/radius;
+ costheta = r/radius;
+
+ /*
+ The hard part of drawing an arc is figuring out when to stop.
+ This method works by drawing the line from the beginning point
+ to the ending point. This splits the plane in half, with the
+ arc that we wish to draw on one side of the line. If we evaluate
+ side(x,y) = a*x + b*y + c, then all of the points on one side of the
+ line will result in side being positive, and all the points on the
+ other side of the line will result in side being negative.
+
+ We want to draw the arc in a counter-clockwise direction, so we
+ must find out what the sign of "side" is for a point which is to the
+ "right" of a line drawn from "beg" to "end". A point which must lie
+ on the right is [xbeg + (yend-ybeg), ybeg - (xend-xbeg)]. (This
+ point is perpendicular to the line at "beg").
+
+ Thus, we compute "side" of the above point, and then compare the
+ sign of side for each new point with the sign of the above point.
+ When they are different, we terminate the loop.
+ */
+
+ a = (double) (yend - ybeg);
+ b = (double) (xend - xbeg);
+ c = (double) (yend*xbeg - xend*ybeg);
+ right_side = side(xbeg + (yend-ybeg),
+ ybeg - (xend-xbeg) );
+
+ x = xbeg;
+ y = ybeg;
+ plot_move(xbeg+xc, ybeg+yc);
+ do {
+ dda_line('*',lastX-1, lastY, scaleX(xc + x), scaleY(yc + y ));
+ /*
+ screen_move( scaleY(yc + y), scaleX(xc + x) );
+ plot_addch('*');
+ */
+ tempX = x;
+ x = x*costheta - y*sintheta;
+ y = tempX*sintheta + y*costheta;
+ } while( side(x,y) == right_side );
+}