home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / quickplot / part2 / functions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  11.2 KB  |  622 lines

  1. /* :set tabstops=4                                                    */
  2. static char *RCSid = "$Header: functions.c,v 1.1 86/04/20 16:16:38 sysad Exp $";
  3.  
  4. /*
  5.  * $Log:    functions.c,v $
  6.  * Revision 1.1  86/04/20  16:16:38  sysad
  7.  * Initial distribution version
  8.  * 
  9.  * 
  10.  */
  11.  
  12.  
  13. /* It is the intent of the author that this software may be distributed
  14.  * and used freely, without restriction.  If you make improvements or
  15.  * enhancements, I would appreciate a copy.
  16.  *
  17.  * Duane H. Hesser    Teltone Corporation
  18.  * ....uw-beaver!tikal!sysad
  19.  * ....uw-beaver!tikal!dhh
  20.  */
  21.  
  22. #include "defs.h"
  23. #include "extern.h"
  24.  
  25. space(x0,y0,x1,y1)
  26. short x0,y0,x1,y1;
  27. {
  28.     static int noinit = 1;
  29.     double tmp;
  30.  
  31. #ifdef DEBUG
  32.     if(debug & 1) printf("space(%d,%d,%d,%d)\n",x0,y0,x1,y1);
  33. #endif
  34.     lowx_space = (double)x0;
  35.     lowy_space = (double)y0;
  36.     highx_space = (double)x1;
  37.     highy_space = (double)y1;
  38.     xspace = highx_space - lowx_space;
  39.     yspace = highy_space - lowy_space;
  40.     if(maxcol > XDOTS) maxcol = XDOTS;
  41.     if(maxrow > YDOTS) maxrow = YDOTS;
  42. #ifdef QUICKPLOT
  43.     /* Autowrap can be a problem; some terminals and/or screen packages
  44.      * wrap early (i.e., they wrap when the last character is
  45.      * placed in the row, rather than waiting for the next character.
  46.      * Safest way seems to be to waste a column.
  47.      */
  48.     if(autowrap) maxcol--;
  49. #endif
  50.     maxx = maxcol - 1;
  51.     maxy = maxrow - 1;
  52.     if(Rotate)
  53.     {
  54.         if(noinit)
  55.         {
  56.             noinit = 0;
  57.             tmp = spacex;
  58.             spacex = spacey;
  59.             spacey = tmp;
  60.             tmp = maxx;
  61.             maxx = maxy;
  62.             maxy = tmp;
  63.             /* re-compute the margins */
  64.             tmp = (Xmargin / XPERINCH) * YPERINCH;
  65.             Xmargin = (Ymargin / YPERINCH) * XPERINCH;
  66.             Ymargin = tmp;
  67.         }
  68.     }
  69.     if(spacex > maxx) spacex = maxx;
  70.     if(spacey > maxy) spacey = maxy;
  71.     xfac = ( spacex/xspace ) * argxfac;
  72.     yfac = ( spacey/yspace ) * argyfac;
  73.     mapxfac = xfac * Scalfac;
  74.     mapyfac = yfac * Scalfac;
  75. #ifdef DEBUG
  76.     if(debug &2)
  77.     {
  78.         printf("maxrow=%d,maxcol=%d,maxx=%d,maxy=%d\n",maxrow,maxcol,maxx,maxy);
  79.         printf("xfac=%G,yfac=%G,mapxfac=%G,mapyfac=%G\n",xfac,yfac,mapxfac,mapyfac);
  80.         printf("spacex=%G,spacey=%G,xspace=%G,yspace=%G\n",spacex,spacey,xspace,yspace);
  81.     }
  82. #endif
  83. }
  84.  
  85. cont(x,y)
  86. short x,y;
  87. {
  88.     x = (short)mapx(x);
  89.     y = (short)mapy(y);
  90.     make_line(curxdot,curydot,x,y);
  91.     curxdot = x;
  92.     curydot = y;
  93. #ifdef DEBUG
  94.     if(debug & 1) printf("cont(%d,%d)\n",curxdot,curydot);
  95. #endif
  96. }
  97.  
  98. move(x,y)
  99. short x,y;
  100. {
  101.     curxdot = (short)mapx(x);
  102.     curydot = (short)mapy(y);
  103. #ifdef DEBUG
  104.     if(debug & 1) printf("move(%d,%d)\n",curxdot,curydot);
  105. #endif
  106. }
  107.  
  108. line(x0,y0,x1,y1)
  109. short x0,y0,x1,y1;
  110. {
  111.     x0 = (short)mapx(x0);
  112.     x1 = (short)mapx(x1);
  113.     y0 = (short)mapy(y0);
  114.     y1 = (short)mapy(y1);
  115.     make_line(x0,y0,x1,y1);
  116. #ifdef DEBUG
  117.     if(debug & 1) printf("line(%d,%d,%d,%d)\n",x0,y0,x1,y1);
  118. #endif
  119.     curxdot = x1;
  120.     curydot = y1;
  121. }
  122.  
  123. make_line(x0,y0,x1,y1)
  124. short x0,y0,x1,y1;
  125. {
  126.     short xdots,ydots,i,j,signx,signy;
  127.     double tanxy;
  128. #ifdef QUICKPLOT
  129.     char pc = plotchar;
  130. #endif
  131.  
  132.     xdots = x1 - x0;
  133.     ydots = y1 - y0;
  134.     signx = (xdots > 0) ? 1 : -1;
  135.     signy = (ydots > 0) ? 1 : -1;
  136.     point(x0,y0);
  137.     if(xdots == 0)
  138.     {
  139.         if(ydots == 0) return;
  140.         for(i = signy; i != ydots; i += signy)
  141.         {
  142. #ifndef QUICKPLOT
  143.             if(!(abs(i) & linemask)) continue;
  144. #else
  145.             if(abs(i) & 1) plotchar = linemask;
  146.             else plotchar = pc;
  147. #endif
  148.             point(x0,y0 + i);
  149.         }
  150.     }
  151.     else if(ydots == 0)
  152.     {
  153.         for(i = signx; i != xdots; i += signx)
  154.         {
  155. #ifndef QUICKPLOT
  156.             if(!(abs(i) & linemask)) continue;
  157. #else
  158.             if(abs(i) & 1) plotchar = linemask;
  159.             else plotchar = pc;
  160. #endif
  161.             point(x0 + i,y0);
  162.         }
  163.     }
  164.     else if(abs(xdots) >= abs(ydots))
  165.     {
  166.         tanxy = (double)ydots / (double)xdots;
  167.         for(i = signx; i != xdots; i += signx)
  168.         {
  169. #ifndef QUICKPLOT
  170.             if(!(abs(i) & linemask)) continue;
  171. #else
  172.             if(abs(i) & 1) plotchar = linemask;
  173.             else plotchar = pc;
  174. #endif
  175.             j = i * tanxy;
  176.             point(x0 + i,y0 + j);
  177.         }
  178.     }
  179.     else
  180.     {
  181.         tanxy = (double)xdots / (double)ydots;
  182.         for(i = signy; i != ydots; i += signy)
  183.         {
  184. #ifndef QUICKPLOT
  185.             if(!(abs(i) & linemask)) continue;
  186. #else
  187.             if(abs(i) & 1) plotchar = linemask;
  188.             else plotchar = pc;
  189. #endif
  190.             j = i * tanxy;
  191.             point(x0 + j,y0 + i);
  192.         }
  193.     }
  194.     point(x1,y1);
  195. #ifdef QUICKPLOT
  196.     plotchar = pc;
  197. #endif
  198. }
  199.  
  200.  
  201. circle(x,y,r)
  202. short x,y,r;
  203. {
  204.     short x0;
  205.  
  206.     x0 = x + r;
  207.     arc(x,y,x0,y,x0,y);
  208.     move(x,y);
  209. }
  210.  
  211. label(str,len)
  212. char *str;
  213. int len;
  214. {
  215.     int i;
  216.     char *rp;
  217.  
  218. #ifdef DEBUG
  219.     if(debug & 1) printf("label(%s,%d)\n",str,len);
  220. #endif
  221.     for(i=0; i < len && str[i] != '\n'; i++) 
  222.     {
  223.         if((str[i] < ' ') || (str[i] >= '\177')) continue;
  224. #ifndef QUICKPLOT
  225.         alpha_plot(str[i]);
  226. #else
  227.         if(Rotate)
  228.         {
  229.             rp = &Row[curxdot][maxy-curydot];
  230.             if(*rp && (*rp != plotchar))  ++curxdot;
  231.             Row[curxdot][maxy-curydot] = str[i];
  232.         }
  233.         else
  234.         {
  235.             rp = &Row[curydot][curxdot];
  236.             if(*rp && (*rp != plotchar))  ++curxdot;
  237.             Row[curydot][curxdot] = str[i];
  238.         }
  239. #endif
  240.     }
  241. }
  242.  
  243. #ifndef QUICKPLOT
  244. point(x,y)
  245. short x,y;
  246. {
  247.     short row,byte,bit;
  248.     if(x > maxx)
  249.     {
  250.         x = maxx;
  251.     }
  252.     else if(x < 0)
  253.     {
  254.         x = 0;
  255.     }
  256.     if(y > maxy)
  257.     {
  258.         y = maxy;
  259.     }
  260.     else if(y < 0)
  261.     {
  262.         y = 0;
  263.     }
  264.  
  265.     if(Rotate)
  266.     {
  267.         row = x;
  268.         byte = (maxy - y) / 6;
  269.         bit = 5 - (y % 6);
  270.     }
  271.     else
  272.     {
  273.         row = y;
  274.         byte = x/6;
  275.         bit = x%6;
  276.     }
  277.     Row[row][byte] |= BIT[bit];
  278. }
  279.  
  280. #else QUICKPLOT
  281.  
  282. point(x,y)
  283. short x,y;
  284. {
  285.     short row,col;
  286.     char pc;
  287.  
  288.     pc = plotchar;
  289.     if(x > maxx)
  290.     {
  291.         x = maxx;
  292.         pc = '@';
  293.     }
  294.     else if(x < 0)
  295.     {
  296.         x = 0;
  297.         pc = '@';
  298.     }
  299.     if(y > maxy)
  300.     {
  301.         y = maxy;
  302.         pc = '@';
  303.     }
  304.     else if(y < 0)
  305.     {
  306.         y = 0;
  307.         pc = '@';
  308.     }
  309.  
  310.     if(Rotate)
  311.     {
  312.         row = x;
  313.         col = maxy - y;
  314.     }
  315.     else
  316.     {
  317.         row = y;
  318.         col = x;
  319.     }
  320.     if(!Row[row][col]) Row[row][col] = pc;
  321. }
  322. #endif QUICKPLOT
  323.  
  324. /* Make an arc with (x,y) as center, (x0,y0) as starting point,
  325.  * and (x1,y1) as end point.
  326.  *
  327.  * The algorithm here is simpler than it looks; the intent is to
  328.  * compute the points required just once in the first quadrant,
  329.  * then reflect them across the axes or origin if they are required
  330.  * in the other quadrants.
  331.  * 1. Find the starting and ending quadrants.
  332.  * 2. Verify the end point, and make sure it is on the arc thru (x0,y0)
  333.  *    with center (x,Y).
  334.  * 3. Determine which quadrants require points to be plotted.
  335.  * 4. Determine the minimum and maximum "y" deltas in each quadrant.
  336.  *    and set the starting point for line drawing in each quadrant.
  337.  * 5. Pot the arc by incrementing the delta "y" and computing the
  338.  *    corresponding "x" delta in the first quadrant.  Then check each
  339.  *    quadrant to see if the corresponding point is needed, and draw a
  340.  *    line from the last point plotted in that quadrant to the current
  341.  *    point in that quadrant.
  342.  */
  343. #include <math.h>
  344. arc(x,y,x0,y0,x1,y1)
  345. short x,y,x0,y0,x1,y1;
  346. {
  347.     int i,ystart,ymax,dx,dy,sq,endq,nq;
  348.     int q[4],qmin[4],qmax[4];
  349.     short lx[4],ly[4],nx,ny,r,rx,ry;
  350.     double asin(),sin(),cos(),ra,theta;
  351.  
  352. #ifdef DEBUG
  353.     if(debug & 3)
  354.         printf("to arc(%d,%d,%d,%d,%d,%d)\n",x,y,x0,y0,x1,y1);
  355. #endif
  356.     /* find starting quadrant                                        */
  357.     if(y0 >= y)
  358.     {
  359.         if(x0 > x) sq = 1;
  360.         else if(y0 == y) sq = 3;
  361.         else sq = 2;
  362.     }
  363.     else if(x0 >= x) sq = 4;
  364.     else sq = 3;
  365.     /* find ending quadrant                                            */
  366.     if(x1 >= x)
  367.     {
  368.         if(y1 > y) endq = 1;
  369.         else if(x1 == x) endq = 3;
  370.         else endq = 4;
  371.     }
  372.     else if(y1 >= y) endq = 2;
  373.     else endq = 3;
  374.  
  375.     /* The calling program can easily pass a phony x1,y1 which
  376.      * doesn't lie on the arc thru x0,y0 with center x,y.
  377.      * Fix it.
  378.      */
  379.     dx = abs(x0 - x); dy = abs(y0 - y);
  380.     if(dx == 0)
  381.     {
  382.         if(dy == 0) return;    /* 0 radius; that's easy            */
  383.         r = dy;
  384.     }
  385.     else if(dy == 0) r = dx;
  386.     else
  387.     {
  388.         r = sqrt(((double)dx * (double)dx) + ((double)dy * (double)dy));
  389.         /* r should never be <= 0, unless integer truncation occurs    */
  390.         if(r <= 0) r = 1;
  391.     }
  392.  
  393.     ra = (double)abs(y1 - y) / (double)r;
  394.     theta = asin(ra);
  395.     dx = r * cos(theta) + 0.5;
  396.     dy = r * sin(theta) + 0.5;
  397.     /* make sure these are positive                                    */
  398.     if((dx == 0) && (dy == 0)) return;
  399.     r = abs((int)r);
  400.     dx = abs(dx);
  401.     dy = abs(dy);
  402.  
  403.     if(debug & 3) printf("dx=%d,dy=%d\n",dx,dy);
  404.     if(endq & 2) x1 = x - dx;
  405.     else x1 = x + dx;
  406.     if(endq > 2) y1 = y - dy;
  407.     else y1 = y + dy;
  408.     if(debug & 3) printf("x1=%d,y1=%d\n",x1,y1);
  409.  
  410.     /* Map to device units.  Radius is mapped for both x direction
  411.      * and y direction because resolution differs in the two directions.
  412.      */
  413.     x = (short)mapx(x);
  414.     x0 = (short)mapx(x0);
  415.     x1 = (short)mapx(x1);
  416.     y = (short)mapy(y);
  417.     y0 = (short)mapy(y0);
  418.     y1 = (short)mapy(y1);
  419.     rx = (short)(((double)r * mapxfac) + .01);
  420.     ry = (short)(((double)r * mapyfac) + .01);
  421.  
  422.     /* Mark the quadrants which require plotting.
  423.      * Note that quadrants are numbered from 1-4, just like in math
  424.      * class, but the "q" arrays run from 0-3
  425.      */
  426.     q[0] = q[1] = q[2] = q[3] = 0;
  427.     if(sq <= endq)
  428.     {
  429.         for(i = sq; i <= endq; ++i)
  430.         {
  431.             ++q[i - 1];
  432.             nq++;        /* number of quadrants                        */
  433.         }
  434.     }
  435.     else
  436.     {
  437.         for(i = sq; i <= 4; ++i)
  438.         {
  439.             ++q[i - 1];
  440.             nq++;
  441.         }
  442.         for(i = 1; i <= endq; ++i)
  443.         {
  444.             ++q[i - 1];
  445.             nq++;
  446.         }
  447.     }
  448.     if(debug & 1)
  449.     {
  450.         printf("arc(%d,%d,%d,%d,%d,%d)\n",x,y,x0,y0,x1,y1);
  451.         printf("(radius=%d,%d,%d)\n",r,rx,ry);;
  452.     }
  453.  
  454.     /* find the min and max y increments                            */
  455.     if(nq >= 3)
  456.     {
  457.         ystart = 0;
  458.         ymax = ry;
  459.     }
  460.     else if(nq == 1)
  461.     {
  462.         if((sq == 1) || (sq == 3))
  463.         {
  464.             ystart = abs(y0 - y);
  465.             ymax = abs(y1 - y);
  466.         }
  467.         else
  468.         {
  469.             ymax = abs(y0 - y);
  470.             ystart = abs(y1 - y);
  471.         }
  472.     }
  473.     else if((sq + endq) == 5)    /* 1 & 4 or 2 & 3                    */
  474.     {
  475.         ystart = 0;
  476.         ymax = (abs(y0 - y) > abs(y1 - y)) ? abs(y0 - y) : abs(y1 - y);
  477.     }
  478.     else
  479.     {
  480.         ymax = ry;
  481.         ystart = (abs(y0 - y) > abs(y1 - y)) ? abs(y1 - y) : abs(y0 - y);
  482.     }
  483.     /* now find the min and max y increments for each quadrant        */
  484.     if(q[0])        /* 1st quadrant                                    */
  485.     {
  486.         if(sq == 1)
  487.         {
  488.             qmin[0] = y0 - y;
  489.             ly[0] = y0;
  490.             lx[0] = x0;
  491.         }
  492.         else
  493.         {
  494.             qmin[0] = 0;
  495.             ly[0] = y;
  496.             lx[0] = x + rx;
  497.         }
  498.         if(endq == 1) qmax[0] = y1 - y;
  499.         else qmax[0] = ry;
  500.     }
  501.     if(q[1])        /* 2nd quadrant                                    */
  502.     {
  503.         if(sq == 2)
  504.         {
  505.             qmax[1] = y0 - y;
  506.         }
  507.         else
  508.         {
  509.             qmax[1] = ry;
  510.         }
  511.         if(endq == 2)
  512.         {
  513.             qmin[1] = y1 - y;
  514.             ly[1] = y1;
  515.             lx[1] = x1;
  516.         }
  517.         else
  518.         {
  519.             qmin[1] = 0;
  520.             ly[1] = y;
  521.             lx[1] = x - rx;
  522.         }
  523.     }
  524.     if(q[2])        /* 3rd    quadrant                                */
  525.     {
  526.         if(sq == 3)
  527.         {
  528.             qmin[2] = y - y0;
  529.             ly[2] = y0;
  530.             lx[2] = x0;
  531.         }
  532.         else
  533.         {
  534.             qmin[2] = 0;
  535.             ly[2] = y;
  536.             lx[2] = x - rx;
  537.         }
  538.         if(endq == 3)
  539.         {
  540.             qmax[2] = y - y1;
  541.         }
  542.         else
  543.         {
  544.             qmax[2] = ry;
  545.         }
  546.     }
  547.     if(q[3])        /* 4th quadrant                                    */
  548.     {
  549.         if(sq == 4)
  550.         {
  551.             qmax[3] = y - y0;
  552.         }
  553.         else
  554.         {
  555.             qmax[3] = ry;
  556.         }
  557.         if(endq == 4)
  558.         {
  559.             qmin[3] = y - y1;
  560.             ly[3] = y1;
  561.             lx[3] = x1;
  562.         }
  563.         else
  564.         {
  565.             qmin[3] = 0;
  566.             ly[3] = y;
  567.             lx[3] = x + rx;
  568.         }
  569.     }
  570. #ifdef DEBUG
  571.     if(debug & 3)
  572.     {
  573.         printf("sq=%d,endq=%d,ystart=%d,ymax=%d\n",sq,endq,ystart,ymax);
  574.         printf("q\t  min \t  max \t  lx  \t  ly\n");
  575.         for(i=0; i < 4; ++i)
  576.         {
  577.             if(q[i])
  578.                 printf("%d\t%d\t%d\t%d\t%d\n",i+1,qmin[i],qmax[i],lx[i],ly[i]);
  579.         }
  580.     }
  581. #endif DEBUG
  582.     /* finally ready to plot                                        */
  583.     for(i = ystart; i <= ymax; ++i)
  584.     {
  585.         ra = ry ? (double)i / (double)ry: 0;
  586.         theta = asin(ra);
  587.         dx = (double)rx * cos(theta) + 0.5;
  588.         if(q[0] && (i >= qmin[0]) && (i <= qmax[0]))
  589.         {
  590.             nx = x + dx;
  591.             ny = y + i;
  592.             make_line(lx[0],ly[0],nx,ny);
  593.             lx[0] = nx;
  594.             ly[0] = ny;
  595.         }
  596.         if(q[1] && (i >= qmin[1]) && (i <= qmax[1]))
  597.         {
  598.             nx = x - dx;
  599.             ny = y + i;
  600.             make_line(lx[1],ly[1],nx,ny);
  601.             lx[1] = nx;
  602.             ly[1] = ny;
  603.         }
  604.         if(q[2] && (i >= qmin[2]) && (i <= qmax[2]))
  605.         {
  606.             nx = x - dx;
  607.             ny = y - i;
  608.             make_line(lx[2],ly[2],nx,ny);
  609.             lx[2] = nx;
  610.             ly[2] = ny;
  611.         }
  612.         if(q[3] && (i >= qmin[3]) && (i <= qmax[3]))
  613.         {
  614.             nx = x + dx;
  615.             ny = y - i;
  616.             make_line(lx[3],ly[3],nx,ny);
  617.             lx[3] = nx;
  618.             ly[3] = ny;
  619.         }
  620.     }
  621. }
  622.