home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / ln03-plot / order.c < prev   
Encoding:
C/C++ Source or Header  |  1987-10-25  |  16.8 KB  |  608 lines

  1. /* 
  2.  * The following code is designed to be used in conjunction with the UNIX    *
  3.  * plot facilities, but may be used on its own to produce output to any      *
  4.  * sixels printing system.                                                   *
  5.  *                                                                           *
  6.  * If any modification are made to this code, while I am still employed by   *
  7.  * the Columbia University Center for Computing Activities, please notify    *
  8.  * me, nwc@cunixc.columbia.edu.                                              *
  9.  *                                                                           */
  10.  
  11. #include "lno.h"
  12. #include <stdio.h>
  13. #include <math.h>
  14.         
  15. openpl()
  16. /* nothing really needed here                                                */
  17. {
  18. }
  19.  
  20.  
  21. move(x,y)
  22. /* set cx,cy memory of last points, scale them, and clear pattern counter.   */
  23. int x,y;
  24. {
  25.   extern int cx,cy;
  26.  
  27.   newcount();
  28.   ln03scale(&x,&y);
  29.   cx = x;
  30.   cy = y;
  31. }
  32.  
  33.  
  34.  
  35. cont(x,y)
  36. /* scaled coordinates and then pass them to extend                           */
  37. {
  38.      ln03scale(&x,&y);
  39.      ln03extend(x,y);
  40. }
  41.  
  42.  
  43.  
  44. point(x,y)
  45. /* scale coordinates and pass them to spot                                   */
  46. {
  47.      ln03scale(&x,&y);
  48.      ln03spot(x,y);
  49. }
  50.  
  51.  
  52.  
  53. line(x1,y1,x2,y2)
  54. /* mark a starting point and then simply use continue to go to second point  */
  55. int x1,y1,x2,y2;
  56. {
  57.   
  58.   move(x1,y1);
  59.   ln03scale(&x2,&y2);
  60.   ln03extend(x2,y2);
  61. }
  62.  
  63.  
  64.  
  65. label(m)
  66. /* place ascii text or math font in graph page.  This is done by direct      *
  67.  * decipoint location addressing. The escape codes and text if placed in     *
  68.  * the output file before the sixels output.                                 */
  69. char *m;
  70. {
  71.   extern int cy,cx;                     /* coordinates to place label        */
  72.   double xx,yy,tempx,tempy;
  73.  
  74.   tempx = cx;
  75.   tempy = cy;
  76.   
  77. /*next two lines convert unscaled pixel coordinates to scaled decipoints,    *
  78.  *the unit the LN03 positions text by.                                       */
  79.  
  80.   xx =(Xdec * (tempx/Xaxis)) + 0.07 * tempx;      
  81.   yy =Ydec - (Ydec * (tempy/Yaxis) - 0.8 * tempy);
  82.  
  83. /* If a label starts in a "~" then tell the LN03 to use its math font.       *
  84.  * A non math font label can begin with a tilda, just prefix it by a space.  */
  85.  
  86.   if(*m == '~'){
  87.     printf("\033*>\033n\033[2 I\033[11h");
  88.     printf("\033[%d`\033[%dd%s",ln03round(xx),ln03round(yy),++m);
  89.   }
  90.   else printf("\017\033[2 I\033[11h\033[%d`\033[%dd%s",ln03round(xx),ln03round(yy),m);
  91.   
  92.   cx += (strlen(m)*15);
  93. }
  94.  
  95.  
  96.  
  97. arc(x,y,x1,y1,x2,y2)
  98. /* This arc generation routine is pretty bad... I do not use it for          *
  99.  * generating circles for this reason. Much of it depends on floating point  *
  100.  * which, depending on the machine may not be that accurate.                 */
  101. int x,y,x1,y1,x2,y2;
  102. {
  103.   double sqrt(),temp;
  104.   register int dx,dy,radsqr;
  105.   register int plotx,ploty,quad,rad,reps = 0;
  106.  
  107.   ln03scale(&x,&y);
  108.   ln03scale(&x1,&y1);
  109.   ln03scale(&x2,&y2);
  110.   dx = abs(x1-x);
  111.   dy = abs(y1-y);
  112.   radsqr = dx*dx + dy*dy;
  113.   temp = radsqr;
  114.   rad = sqrt(temp);
  115.   plotx = x1-x;                         /* x coord of first point in arc     */
  116.   ploty = y1-y;                         /* y  "     "   "     "    "  "      */
  117.   if(x1 > x+rad/2) quad = 1;            /* what quadrant are we in ?         */
  118.     else if(x1 > x) quad = 2;
  119.       else quad = 3;
  120.   if(y1 < y && quad == 2 ) quad = 4;    /* under horizon of y is 4 not 2     */
  121.   ln03filterP(x1,y1);
  122.   while(ln03aprox(plotx+x,x2,ploty+y,y2) != 1){ /* until final coord hit, go     */
  123.      if(quad == 2){ /* quadrants not standard, my are by the compass.        */
  124.         plotx--;    /* we are in North quadrant so inc x and calculate y     */
  125.         temp = radsqr - plotx*plotx;
  126.         ploty = ln03round(sqrt(temp));
  127.         ln03extend(plotx+x,ploty+y);
  128.         if(plotx+x < x-rad/2){
  129.           quad = 3;
  130.           reps++;
  131.           }
  132.       }
  133.          else if(quad == 3){            /* in west quad, inc y and calc x    */
  134.             ploty--;
  135.             temp = radsqr - ploty*ploty;
  136.             plotx =0-ln03round(sqrt(temp));
  137.             ln03extend(plotx+x,ploty+y);
  138.             if(plotx+x >= x-rad/2){
  139.                quad = 4;
  140.                reps++;
  141.             }
  142.          }
  143.           else if(quad == 4){           /* we are in south quad, mirror north*/
  144.               plotx++;
  145.               temp = radsqr - plotx*plotx;
  146.               ploty =0-ln03round(sqrt(temp));
  147.               ln03extend(plotx+x,ploty+y);
  148.               if(plotx+x > x+rad/2){
  149.                  quad = 1;
  150.                  reps++;
  151.               }
  152.           }
  153.              else{                      /* east quad, mirror west            */
  154.                  ploty++;
  155.                  temp = radsqr - ploty*ploty;
  156.                  plotx = ln03round(sqrt(temp));
  157.                  ln03extend(plotx+x,ploty+y);
  158.                  if(plotx+x <= x+rad/2){
  159.                     quad = 2;
  160.                     reps++;
  161.                  }
  162.               }
  163.   if(reps > 4) /* We have been around the circle more than once...oops!     */
  164.     {
  165.     fprintf(stderr,"Second point is not in arc of center and first point.\n");
  166.     fprintf(stderr,"Bad arc is %d, %d, %d, %d, %d, %d.\n",x,y,x1,y1,x2,y2);
  167.     fprintf(stderr," Converting sparse matrix built to date and exiting.\n");
  168.     ln03conv();
  169.     exit(1);
  170.     }
  171.   }
  172. }
  173.  
  174.  
  175.  
  176. circle(x,y,r)
  177. /* this generates 45 degrees of a circle, passing each point to circpoint    *
  178.  * which distributes the point to all eight 45 degree segments.              */
  179. int x,y,r;
  180. {
  181.   register int xx,yy,d;
  182.   extern int cx,cy;
  183.   extern float xscale,yscale;
  184.   int dummy = 1;
  185.  
  186.   newcount();
  187.  
  188.   ln03scale(&x,&y);
  189.   r = ln03round(r * xscale);
  190.   xx = 0;
  191.   yy = r;
  192.   d  = 3-2*r;
  193.   while( xx < yy){ 
  194.      ln03circpoint(xx,yy,x,y);
  195.      if(d < 0) d = d+4*xx+6;
  196.         else{
  197.            d = d+4*(xx-yy) + 10;
  198.            yy--;
  199.            }
  200.       xx++;
  201.   }
  202.   if(xx == yy) ln03circpoint(xx,yy,x,y);
  203.   cx = xx+x;
  204.   cy = yy+y;
  205. }
  206.  
  207.  
  208.  
  209. erase()
  210. /* Just convert what we have, and start fresh.                               */
  211. {
  212. ln03conv();
  213. }
  214.  
  215.  
  216.  
  217. linemod(s)
  218. /* set varible "mode" to reflect pattern chosen.                             */
  219. char *s;
  220. {
  221.   extern int mode;
  222.  
  223.   switch(s[0]){
  224.         case 'l':       
  225.                 mode = 4;
  226.                 break;
  227.         case 'd':       
  228.                 if(s[3] == 'd') mode = 5;
  229.                 else mode = 2;
  230.                 break;
  231.         case 's':
  232.                 if(s[5] != '\0') mode = 1;
  233.                 else mode = 3;
  234.    }
  235. }
  236.  
  237.  
  238. space(x1,y1,x2,y2)
  239. /* set a scaling factor at users request. scale is defaulted to 1            */
  240. int x1,y1,x2,y2;
  241. {
  242.   extern float xscale,yscale;
  243.   float temp;
  244.   extern int xoffset,yoffset;
  245.  
  246.   if (x1 < 0) xoffset = -x1;
  247.   if (y1 < 0) yoffset = -y1;
  248.  
  249.   temp = (float)Xaxis/(x2-x1);
  250.   xscale = floor(temp * 100.0)/100.0;
  251.   temp = (float)Xaxis/(y2-y1);
  252.   yscale = floor(temp * 100.0) / 100.0;
  253. }
  254.  
  255.  
  256. closepl()
  257. {
  258.   ln03conv();
  259. }
  260.  
  261. /*---------------------------------------------------------------------------*/
  262. /*           BEGIN SUPPORT ROUTINES                                          */
  263. /*---------------------------------------------------------------------------*/
  264.  
  265. ln03extend(x1,y1)
  266. /* Don't ask, I got this from a book, it forms a line by increment to a      *
  267.  * point in the area nearest the line. negative slopes are achived by        *
  268.  * mirroring a positive slope.                                               */
  269. register int x1,y1;
  270. {
  271.   extern   int cx,cy;
  272.   register int dx,dy,yincr1,mid,yincr2,yd,xincr1,xincr2,xd,x,y,xend,yend;
  273.   register int xx,yy;
  274.   register int neg=0;
  275.  
  276.  
  277.   dx     = abs(x1-cx);
  278.   dy     = abs(y1-cy);
  279.   yd     = 2*dy-dx;
  280.   yincr1 = 2*dy;
  281.   yincr2 = 2*(dy-dx);
  282.   xd     = 2*dx-dy;
  283.   xincr1 = 2*dx;
  284.   xincr2 = 2*(dx-dy);
  285.   if (cx > x1){                         /* set up initial variables          */
  286.     x = x1;
  287.     y = y1;
  288.     xend = cx;
  289.     yend = cy;
  290.     if(cy < y1 && cx != x1){            /* BELLS AND WISTLES negative slope  */
  291.       neg = 1;
  292.       mid = y1;
  293.       yend = cy+(2*dy);                 /*set y to its + slope equivalent    */
  294.     }
  295.   }
  296.   else
  297.   {
  298.     x = cx;
  299.     y = cy;
  300.     xend = x1;
  301.     yend = y1;
  302.     if(y1 < cy && cx != x1){            /* BELLS AND WISTLES negative slope  */
  303.       neg = 1;
  304.       mid = cy;
  305.       yend = y1+(2*dy);
  306.     }
  307.   }
  308.   ln03filterP(x,y);
  309.   xx = x;
  310.   yy = y;
  311.   if (x == xend)                        /* we have a totally verticle line.  */
  312.     while (y != yend){
  313.     if (y < yend) y++;
  314.       else y--;
  315.     ln03filterP(x,y);
  316.     }
  317.   while (x < xend){
  318.     if (yd < 0) yd += yincr1;
  319.     else{  
  320.       if (y < yend) y++;
  321.       else if (y > yend) y--;
  322.       yd += yincr2;
  323.     }
  324.     if (xd < 0) xd += xincr1;
  325.     else{
  326.       x++;
  327.       xd += xincr2;
  328.     }
  329.     if (xx != x || yy != y){
  330.     if(neg) ln03filterP(x,2*mid-y);
  331.       else ln03filterP(x,y);
  332.     xx = x;
  333.     yy = y;
  334.     }
  335.   }
  336.   cx = x1;                              /* remember last points              */
  337.   cy = y1;
  338. }
  339.  
  340.  
  341.  
  342. int ln03round(num)
  343. /* float number rounding                                                     */
  344. double num;
  345. {
  346.   int inum;
  347.   double rnum;
  348.  
  349.   inum = num;
  350.   rnum = num - inum;
  351.   return((rnum < .5)?inum:inum+1);
  352. }
  353.  
  354. int ln03power(z)
  355. /* this rountine accepts an integer 0-5 and first takes its five compliment  *
  356.  * then it returns 2 to the power of the result. exmp 3 = (5-3)^2 = 4        */
  357. int z;
  358. {
  359.   register int inc,final = 2;
  360.  
  361.   z = 5-z;
  362.   if(z ==0) final = 1;
  363.         else if(z==1) final = 2;
  364.                 else for(inc = 2;z >= inc; inc++) final *= 2;
  365.   return(final);
  366. }
  367.  
  368.  
  369.  
  370. int ln03aprox(a,b,c,d)
  371. /* check to see if a is aprox equal to b and if c is aprox equal to d        *
  372.  * this is done because I don't trust arc's floating point to generate       *
  373.  * the circumference points exactly.                                         */
  374. int a,b,c,d;
  375. {
  376.   if( a <= b+1 && a >= b-1 && c <= d+1 && c >= d-1) return(1);
  377.      else return(-1);
  378. }
  379.  
  380.  
  381.  
  382. death()
  383. /* Something, some where has created an error, or we are out of RAM,        *
  384.  * convert the graph as it stands.                                          */
  385. {
  386.   fprintf(stderr,"We have ran out of memory for sparse matrix nodes.\n");
  387.   fprintf(stderr,"  We will convert what has been done to date and leave.\n");
  388.   ln03conv();
  389.   exit(1);
  390. }
  391.  
  392.  
  393. ln03spot(x,y)
  394. /* place a point given by coordinates in sparse matrix.                      */
  395. int x,y;
  396. {
  397.   extern struct sixel *vert[MAXVERT];   /* this is the plotting grid         */
  398.   struct sixel *temp,*mark,*malloc();
  399.   extern int cy,cx;            
  400.   register int Vval;        /* verticle coordinate to the nearest sixel      */
  401.   register int Svval;       /* verticle coordinate, pixel remainder of sixels*/
  402.  
  403.   if(x >= 0 && x <= Xaxis && y >= 0 && y <= Yaxis){
  404.      cy = y; cx = x;      
  405.      Vval =(Yaxis-(y-2))/6;             /* div 6 to obtain sixels            */
  406.      Svval = y%6;                       /* modulo to obtain pixels remainder */
  407.      if(vert[Vval] == NULL){            /* this row is new, start it         */
  408.         if((temp = malloc(sizeof(struct sixel)))==NULL) death();
  409.         temp->pixels = 0|(ln03power(Svval));/* calc sixels' pixel value          */
  410.         temp->horiz = x;
  411.         temp->next = NULL;        
  412.         vert[Vval] = temp;
  413.         }
  414.      else{                              /* row already has member(s)         */
  415.           mark = vert[Vval];            /* set a marker to move along list   */
  416.           while(mark->next != NULL && mark->horiz < x) mark = mark->next;
  417.  
  418. /* we are now a) at row's end, b) an equal horiz,                            *
  419.  * c) a greater horiz.                                                       */
  420.  
  421.           if(mark->next == NULL && mark->horiz < x ){ 
  422.  
  423. /* time to add a node because horiz is too big and no next node.             */
  424.  
  425.              if((temp = malloc(sizeof(struct sixel)))==NULL) death();
  426.              temp->pixels = 0|(ln03power(Svval));
  427.              temp->horiz = x;
  428.              temp->next = NULL;         /* Better safe......                 */
  429.              mark->next = temp;         /* Add new node to vert structure.   */
  430.              }
  431.              else if(mark->horiz == x) mark->pixels |= ln03power(Svval);
  432.  
  433.   /* just modify this node                                                   */
  434.  
  435.                   else if(mark->horiz > x){
  436.  
  437.   /* insert new node between two present cause we have passed its spot       */
  438.  
  439.                       if((temp = malloc(sizeof(struct sixel)))==NULL) death();
  440.                         temp->pixels = mark->pixels;
  441.                         temp->horiz = mark->horiz;
  442.                         temp->next = mark->next;
  443.                         mark->pixels = 0|(ln03power(Svval));
  444.                         mark->horiz = x;
  445.                         mark->next = temp;
  446.                       }
  447.           }
  448.     }
  449. }
  450.  
  451.  
  452. ln03conv()
  453. /* This routine coverts a sparce matrix to LN03 format of sixels. The        * 
  454.  * size of the output is minimized by using the LN03's repeat format:        *
  455.  * !10? performs ? (a space) 10 times.                                       */
  456. {
  457. register int count,rep;
  458. register int Hplace;                    /* horizontal displacement           */
  459. register int lastc = 0;                 /* sixel pixel pattern holder        */
  460. int x;
  461. struct sixel *temp;
  462. extern struct sixel *vert[MAXVERT];     /* sparse matrix of sixels           */
  463.  
  464.                                         /* ESC codes to get ln03 sixels mode */
  465. printf("\033[2 I\033[1`\033[1d\033P000;0000;000q\"1;1"); 
  466. for(count = 0; count < MAXVERT; count++)
  467.   if(vert[count] == NULL) printf("?-");   /* LF for a blank row          */
  468.     else{
  469.       temp = vert[count];
  470.       if(temp->horiz>0) printf("!%d?",temp->horiz-1);/*tab to 1st char   */
  471.       printf("%c",temp->pixels+63);
  472.       Hplace = temp->horiz;
  473.       lastc = temp->pixels;
  474.       rep = 0;  
  475.       while(temp->next != NULL){
  476.            temp = temp->next;           /* move one node horizontally        */
  477.            if(temp->horiz == Hplace+1 && temp->pixels == lastc){
  478.                rep++;
  479.                Hplace++;
  480.                }
  481.              else{
  482.                 if(rep > 0) printf("!%d%c",rep,lastc+63);
  483.                 if(temp->horiz != Hplace+1 && temp->horiz <= Xaxis)
  484.                    printf("!%d?",temp->horiz - Hplace - 1);
  485.                 printf("%c",temp->pixels+63);
  486.                 Hplace = temp->horiz;
  487.                 lastc = temp->pixels;
  488.                 rep = 0;
  489.                 }
  490.            }    
  491.       if(rep > 0) printf("!%d%c-",rep,lastc+63);
  492.         else printf("-");
  493.     }
  494. printf("\033\\");                    /* Tell ln03 we are done with sixels */
  495.  
  496. for(x = 0; x < MAXVERT; x++)
  497.   vert[x] = (struct sixel *)NULL;
  498.  
  499. }
  500.  
  501.  
  502. box(x0,y0,x1,y1)
  503. /* box drawing routine                                                       */
  504. int x0,y0,x1,y1;
  505. {
  506.      int xhold,yhold;
  507.      
  508.      xhold = x0;
  509.      yhold = y0;
  510.      
  511.      ln03scale(&x0,&y0);
  512.      ln03scale(&x1,&y1);
  513.      
  514.      move(xhold,yhold);
  515.      ln03extend(x1,y0);
  516.      ln03extend(x1,y1);
  517.  
  518.      move(xhold,yhold);
  519.      ln03extend(x0,y1);
  520.      ln03extend(x1,y1);
  521. }
  522.  
  523.  
  524.  
  525. ln03circpoint(xx,yy,x,y)
  526. /* circle() only calculates 45 degrees of a circle, this distributes the     *
  527.  * coordinates given into an entire circle. The decrementing of count is so  *
  528.  * that the position in a pattern, i.e. point or space in "dot dash" is      *
  529.  * not lost.                                                                 */
  530.  
  531. int xx,yy,x,y;
  532. {
  533.   extern int cx,cy,count;
  534.  
  535.   ln03filterP(xx+x,yy+y);
  536.   count--;
  537.   ln03filterP(yy+x,xx+y);
  538.   count--;
  539.   ln03filterP(yy+x,-xx+y);
  540.   count--;
  541.   ln03filterP(xx+x,-yy+y);
  542.   count--;
  543.   ln03filterP(-xx+x,-yy+y);
  544.   count--;
  545.   ln03filterP(-yy+x,-xx+y);
  546.   count--;
  547.   ln03filterP(-yy+x,xx+y);
  548.   count--;
  549.   ln03filterP(-xx+x,yy+y);
  550. }
  551.  
  552.  
  553. ln03filterP(x,y)
  554. /* filter() acts as a middle man between a caller and spot(), i.e. if our    *
  555.  * position in the line pattern (example: dotted line) is a blank space      *
  556.  * then spot should not be called.                                           */
  557. int x,y;
  558. {
  559.   extern int mode,count;
  560.  
  561.   switch(mode){
  562.     case 1: ln03spot(x,y);                                /* solid line      */
  563.                 break;
  564.     case 2: if(count <= 3 ) ln03spot(x,y);                /* dotted line     */
  565.             if(count == 6) count = 0;
  566.                 break;
  567.     case 3: if(count <= 6 ) ln03spot(x,y);                /* short dash      */
  568.             if(count == 9) count =0;    
  569.                 break;
  570.     case 4: if(count <= 9 ) ln03spot(x,y);                /* long dash       */
  571.             if(count == 12) count =0;
  572.                 break;
  573.                                                           /* dot dash        */
  574.     case 5: if((count <= 6)||((count ==11)||(count==12))) ln03spot(x,y);
  575.             if(count == 17) count = 0;
  576.                 break;
  577.   }
  578.   count++;                              /* increment pattern position.       */
  579. }
  580.  
  581. ln03scale(x,y)
  582. int *x,*y;
  583. {
  584.      extern float xscale,yscale;
  585.      extern int xoffset,yoffset;
  586.      int tempx,tempy;
  587.  
  588.      
  589.      tempx = *x;
  590.      tempy = *y;
  591.  
  592.      tempx += xoffset;
  593.      tempy += yoffset;
  594.  
  595.      tempx = ln03round(tempx*xscale);
  596.      tempy = ln03round(tempy*yscale);
  597.  
  598.      *x = tempx;
  599.      *y = tempy;
  600. }
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607.  
  608.