home *** CD-ROM | disk | FTP | other *** search
- /* :set tabstops=4 */
- static char *RCSid = "$Header: functions.c,v 1.1 86/04/20 16:16:38 sysad Exp $";
-
- /*
- * $Log: functions.c,v $
- * Revision 1.1 86/04/20 16:16:38 sysad
- * Initial distribution version
- *
- *
- */
-
-
- /* It is the intent of the author that this software may be distributed
- * and used freely, without restriction. If you make improvements or
- * enhancements, I would appreciate a copy.
- *
- * Duane H. Hesser Teltone Corporation
- * ....uw-beaver!tikal!sysad
- * ....uw-beaver!tikal!dhh
- */
-
- #include "defs.h"
- #include "extern.h"
-
- space(x0,y0,x1,y1)
- short x0,y0,x1,y1;
- {
- static int noinit = 1;
- double tmp;
-
- #ifdef DEBUG
- if(debug & 1) printf("space(%d,%d,%d,%d)\n",x0,y0,x1,y1);
- #endif
- lowx_space = (double)x0;
- lowy_space = (double)y0;
- highx_space = (double)x1;
- highy_space = (double)y1;
- xspace = highx_space - lowx_space;
- yspace = highy_space - lowy_space;
- if(maxcol > XDOTS) maxcol = XDOTS;
- if(maxrow > YDOTS) maxrow = YDOTS;
- #ifdef QUICKPLOT
- /* Autowrap can be a problem; some terminals and/or screen packages
- * wrap early (i.e., they wrap when the last character is
- * placed in the row, rather than waiting for the next character.
- * Safest way seems to be to waste a column.
- */
- if(autowrap) maxcol--;
- #endif
- maxx = maxcol - 1;
- maxy = maxrow - 1;
- if(Rotate)
- {
- if(noinit)
- {
- noinit = 0;
- tmp = spacex;
- spacex = spacey;
- spacey = tmp;
- tmp = maxx;
- maxx = maxy;
- maxy = tmp;
- /* re-compute the margins */
- tmp = (Xmargin / XPERINCH) * YPERINCH;
- Xmargin = (Ymargin / YPERINCH) * XPERINCH;
- Ymargin = tmp;
- }
- }
- if(spacex > maxx) spacex = maxx;
- if(spacey > maxy) spacey = maxy;
- xfac = ( spacex/xspace ) * argxfac;
- yfac = ( spacey/yspace ) * argyfac;
- mapxfac = xfac * Scalfac;
- mapyfac = yfac * Scalfac;
- #ifdef DEBUG
- if(debug &2)
- {
- printf("maxrow=%d,maxcol=%d,maxx=%d,maxy=%d\n",maxrow,maxcol,maxx,maxy);
- printf("xfac=%G,yfac=%G,mapxfac=%G,mapyfac=%G\n",xfac,yfac,mapxfac,mapyfac);
- printf("spacex=%G,spacey=%G,xspace=%G,yspace=%G\n",spacex,spacey,xspace,yspace);
- }
- #endif
- }
-
- cont(x,y)
- short x,y;
- {
- x = (short)mapx(x);
- y = (short)mapy(y);
- make_line(curxdot,curydot,x,y);
- curxdot = x;
- curydot = y;
- #ifdef DEBUG
- if(debug & 1) printf("cont(%d,%d)\n",curxdot,curydot);
- #endif
- }
-
- move(x,y)
- short x,y;
- {
- curxdot = (short)mapx(x);
- curydot = (short)mapy(y);
- #ifdef DEBUG
- if(debug & 1) printf("move(%d,%d)\n",curxdot,curydot);
- #endif
- }
-
- line(x0,y0,x1,y1)
- short x0,y0,x1,y1;
- {
- x0 = (short)mapx(x0);
- x1 = (short)mapx(x1);
- y0 = (short)mapy(y0);
- y1 = (short)mapy(y1);
- make_line(x0,y0,x1,y1);
- #ifdef DEBUG
- if(debug & 1) printf("line(%d,%d,%d,%d)\n",x0,y0,x1,y1);
- #endif
- curxdot = x1;
- curydot = y1;
- }
-
- make_line(x0,y0,x1,y1)
- short x0,y0,x1,y1;
- {
- short xdots,ydots,i,j,signx,signy;
- double tanxy;
- #ifdef QUICKPLOT
- char pc = plotchar;
- #endif
-
- xdots = x1 - x0;
- ydots = y1 - y0;
- signx = (xdots > 0) ? 1 : -1;
- signy = (ydots > 0) ? 1 : -1;
- point(x0,y0);
- if(xdots == 0)
- {
- if(ydots == 0) return;
- for(i = signy; i != ydots; i += signy)
- {
- #ifndef QUICKPLOT
- if(!(abs(i) & linemask)) continue;
- #else
- if(abs(i) & 1) plotchar = linemask;
- else plotchar = pc;
- #endif
- point(x0,y0 + i);
- }
- }
- else if(ydots == 0)
- {
- for(i = signx; i != xdots; i += signx)
- {
- #ifndef QUICKPLOT
- if(!(abs(i) & linemask)) continue;
- #else
- if(abs(i) & 1) plotchar = linemask;
- else plotchar = pc;
- #endif
- point(x0 + i,y0);
- }
- }
- else if(abs(xdots) >= abs(ydots))
- {
- tanxy = (double)ydots / (double)xdots;
- for(i = signx; i != xdots; i += signx)
- {
- #ifndef QUICKPLOT
- if(!(abs(i) & linemask)) continue;
- #else
- if(abs(i) & 1) plotchar = linemask;
- else plotchar = pc;
- #endif
- j = i * tanxy;
- point(x0 + i,y0 + j);
- }
- }
- else
- {
- tanxy = (double)xdots / (double)ydots;
- for(i = signy; i != ydots; i += signy)
- {
- #ifndef QUICKPLOT
- if(!(abs(i) & linemask)) continue;
- #else
- if(abs(i) & 1) plotchar = linemask;
- else plotchar = pc;
- #endif
- j = i * tanxy;
- point(x0 + j,y0 + i);
- }
- }
- point(x1,y1);
- #ifdef QUICKPLOT
- plotchar = pc;
- #endif
- }
-
-
- circle(x,y,r)
- short x,y,r;
- {
- short x0;
-
- x0 = x + r;
- arc(x,y,x0,y,x0,y);
- move(x,y);
- }
-
- label(str,len)
- char *str;
- int len;
- {
- int i;
- char *rp;
-
- #ifdef DEBUG
- if(debug & 1) printf("label(%s,%d)\n",str,len);
- #endif
- for(i=0; i < len && str[i] != '\n'; i++)
- {
- if((str[i] < ' ') || (str[i] >= '\177')) continue;
- #ifndef QUICKPLOT
- alpha_plot(str[i]);
- #else
- if(Rotate)
- {
- rp = &Row[curxdot][maxy-curydot];
- if(*rp && (*rp != plotchar)) ++curxdot;
- Row[curxdot][maxy-curydot] = str[i];
- }
- else
- {
- rp = &Row[curydot][curxdot];
- if(*rp && (*rp != plotchar)) ++curxdot;
- Row[curydot][curxdot] = str[i];
- }
- #endif
- }
- }
-
- #ifndef QUICKPLOT
- point(x,y)
- short x,y;
- {
- short row,byte,bit;
- if(x > maxx)
- {
- x = maxx;
- }
- else if(x < 0)
- {
- x = 0;
- }
- if(y > maxy)
- {
- y = maxy;
- }
- else if(y < 0)
- {
- y = 0;
- }
-
- if(Rotate)
- {
- row = x;
- byte = (maxy - y) / 6;
- bit = 5 - (y % 6);
- }
- else
- {
- row = y;
- byte = x/6;
- bit = x%6;
- }
- Row[row][byte] |= BIT[bit];
- }
-
- #else QUICKPLOT
-
- point(x,y)
- short x,y;
- {
- short row,col;
- char pc;
-
- pc = plotchar;
- if(x > maxx)
- {
- x = maxx;
- pc = '@';
- }
- else if(x < 0)
- {
- x = 0;
- pc = '@';
- }
- if(y > maxy)
- {
- y = maxy;
- pc = '@';
- }
- else if(y < 0)
- {
- y = 0;
- pc = '@';
- }
-
- if(Rotate)
- {
- row = x;
- col = maxy - y;
- }
- else
- {
- row = y;
- col = x;
- }
- if(!Row[row][col]) Row[row][col] = pc;
- }
- #endif QUICKPLOT
-
- /* Make an arc with (x,y) as center, (x0,y0) as starting point,
- * and (x1,y1) as end point.
- *
- * The algorithm here is simpler than it looks; the intent is to
- * compute the points required just once in the first quadrant,
- * then reflect them across the axes or origin if they are required
- * in the other quadrants.
- * 1. Find the starting and ending quadrants.
- * 2. Verify the end point, and make sure it is on the arc thru (x0,y0)
- * with center (x,Y).
- * 3. Determine which quadrants require points to be plotted.
- * 4. Determine the minimum and maximum "y" deltas in each quadrant.
- * and set the starting point for line drawing in each quadrant.
- * 5. Pot the arc by incrementing the delta "y" and computing the
- * corresponding "x" delta in the first quadrant. Then check each
- * quadrant to see if the corresponding point is needed, and draw a
- * line from the last point plotted in that quadrant to the current
- * point in that quadrant.
- */
- #include <math.h>
- arc(x,y,x0,y0,x1,y1)
- short x,y,x0,y0,x1,y1;
- {
- int i,ystart,ymax,dx,dy,sq,endq,nq;
- int q[4],qmin[4],qmax[4];
- short lx[4],ly[4],nx,ny,r,rx,ry;
- double asin(),sin(),cos(),ra,theta;
-
- #ifdef DEBUG
- if(debug & 3)
- printf("to arc(%d,%d,%d,%d,%d,%d)\n",x,y,x0,y0,x1,y1);
- #endif
- /* find starting quadrant */
- if(y0 >= y)
- {
- if(x0 > x) sq = 1;
- else if(y0 == y) sq = 3;
- else sq = 2;
- }
- else if(x0 >= x) sq = 4;
- else sq = 3;
- /* find ending quadrant */
- if(x1 >= x)
- {
- if(y1 > y) endq = 1;
- else if(x1 == x) endq = 3;
- else endq = 4;
- }
- else if(y1 >= y) endq = 2;
- else endq = 3;
-
- /* The calling program can easily pass a phony x1,y1 which
- * doesn't lie on the arc thru x0,y0 with center x,y.
- * Fix it.
- */
- dx = abs(x0 - x); dy = abs(y0 - y);
- if(dx == 0)
- {
- if(dy == 0) return; /* 0 radius; that's easy */
- r = dy;
- }
- else if(dy == 0) r = dx;
- else
- {
- r = sqrt(((double)dx * (double)dx) + ((double)dy * (double)dy));
- /* r should never be <= 0, unless integer truncation occurs */
- if(r <= 0) r = 1;
- }
-
- ra = (double)abs(y1 - y) / (double)r;
- theta = asin(ra);
- dx = r * cos(theta) + 0.5;
- dy = r * sin(theta) + 0.5;
- /* make sure these are positive */
- if((dx == 0) && (dy == 0)) return;
- r = abs((int)r);
- dx = abs(dx);
- dy = abs(dy);
-
- if(debug & 3) printf("dx=%d,dy=%d\n",dx,dy);
- if(endq & 2) x1 = x - dx;
- else x1 = x + dx;
- if(endq > 2) y1 = y - dy;
- else y1 = y + dy;
- if(debug & 3) printf("x1=%d,y1=%d\n",x1,y1);
-
- /* Map to device units. Radius is mapped for both x direction
- * and y direction because resolution differs in the two directions.
- */
- x = (short)mapx(x);
- x0 = (short)mapx(x0);
- x1 = (short)mapx(x1);
- y = (short)mapy(y);
- y0 = (short)mapy(y0);
- y1 = (short)mapy(y1);
- rx = (short)(((double)r * mapxfac) + .01);
- ry = (short)(((double)r * mapyfac) + .01);
-
- /* Mark the quadrants which require plotting.
- * Note that quadrants are numbered from 1-4, just like in math
- * class, but the "q" arrays run from 0-3
- */
- q[0] = q[1] = q[2] = q[3] = 0;
- if(sq <= endq)
- {
- for(i = sq; i <= endq; ++i)
- {
- ++q[i - 1];
- nq++; /* number of quadrants */
- }
- }
- else
- {
- for(i = sq; i <= 4; ++i)
- {
- ++q[i - 1];
- nq++;
- }
- for(i = 1; i <= endq; ++i)
- {
- ++q[i - 1];
- nq++;
- }
- }
- if(debug & 1)
- {
- printf("arc(%d,%d,%d,%d,%d,%d)\n",x,y,x0,y0,x1,y1);
- printf("(radius=%d,%d,%d)\n",r,rx,ry);;
- }
-
- /* find the min and max y increments */
- if(nq >= 3)
- {
- ystart = 0;
- ymax = ry;
- }
- else if(nq == 1)
- {
- if((sq == 1) || (sq == 3))
- {
- ystart = abs(y0 - y);
- ymax = abs(y1 - y);
- }
- else
- {
- ymax = abs(y0 - y);
- ystart = abs(y1 - y);
- }
- }
- else if((sq + endq) == 5) /* 1 & 4 or 2 & 3 */
- {
- ystart = 0;
- ymax = (abs(y0 - y) > abs(y1 - y)) ? abs(y0 - y) : abs(y1 - y);
- }
- else
- {
- ymax = ry;
- ystart = (abs(y0 - y) > abs(y1 - y)) ? abs(y1 - y) : abs(y0 - y);
- }
- /* now find the min and max y increments for each quadrant */
- if(q[0]) /* 1st quadrant */
- {
- if(sq == 1)
- {
- qmin[0] = y0 - y;
- ly[0] = y0;
- lx[0] = x0;
- }
- else
- {
- qmin[0] = 0;
- ly[0] = y;
- lx[0] = x + rx;
- }
- if(endq == 1) qmax[0] = y1 - y;
- else qmax[0] = ry;
- }
- if(q[1]) /* 2nd quadrant */
- {
- if(sq == 2)
- {
- qmax[1] = y0 - y;
- }
- else
- {
- qmax[1] = ry;
- }
- if(endq == 2)
- {
- qmin[1] = y1 - y;
- ly[1] = y1;
- lx[1] = x1;
- }
- else
- {
- qmin[1] = 0;
- ly[1] = y;
- lx[1] = x - rx;
- }
- }
- if(q[2]) /* 3rd quadrant */
- {
- if(sq == 3)
- {
- qmin[2] = y - y0;
- ly[2] = y0;
- lx[2] = x0;
- }
- else
- {
- qmin[2] = 0;
- ly[2] = y;
- lx[2] = x - rx;
- }
- if(endq == 3)
- {
- qmax[2] = y - y1;
- }
- else
- {
- qmax[2] = ry;
- }
- }
- if(q[3]) /* 4th quadrant */
- {
- if(sq == 4)
- {
- qmax[3] = y - y0;
- }
- else
- {
- qmax[3] = ry;
- }
- if(endq == 4)
- {
- qmin[3] = y - y1;
- ly[3] = y1;
- lx[3] = x1;
- }
- else
- {
- qmin[3] = 0;
- ly[3] = y;
- lx[3] = x + rx;
- }
- }
- #ifdef DEBUG
- if(debug & 3)
- {
- printf("sq=%d,endq=%d,ystart=%d,ymax=%d\n",sq,endq,ystart,ymax);
- printf("q\t min \t max \t lx \t ly\n");
- for(i=0; i < 4; ++i)
- {
- if(q[i])
- printf("%d\t%d\t%d\t%d\t%d\n",i+1,qmin[i],qmax[i],lx[i],ly[i]);
- }
- }
- #endif DEBUG
- /* finally ready to plot */
- for(i = ystart; i <= ymax; ++i)
- {
- ra = ry ? (double)i / (double)ry: 0;
- theta = asin(ra);
- dx = (double)rx * cos(theta) + 0.5;
- if(q[0] && (i >= qmin[0]) && (i <= qmax[0]))
- {
- nx = x + dx;
- ny = y + i;
- make_line(lx[0],ly[0],nx,ny);
- lx[0] = nx;
- ly[0] = ny;
- }
- if(q[1] && (i >= qmin[1]) && (i <= qmax[1]))
- {
- nx = x - dx;
- ny = y + i;
- make_line(lx[1],ly[1],nx,ny);
- lx[1] = nx;
- ly[1] = ny;
- }
- if(q[2] && (i >= qmin[2]) && (i <= qmax[2]))
- {
- nx = x - dx;
- ny = y - i;
- make_line(lx[2],ly[2],nx,ny);
- lx[2] = nx;
- ly[2] = ny;
- }
- if(q[3] && (i >= qmin[3]) && (i <= qmax[3]))
- {
- nx = x + dx;
- ny = y - i;
- make_line(lx[3],ly[3],nx,ny);
- lx[3] = nx;
- ly[3] = ny;
- }
- }
- }
-