[comp.sources.unix] v12i024: Plot

rsalz@uunet.UU.NET (Rich Salz) (10/20/87)

Submitted-by: Nick Christopher <nwc@cunixc.columbia.edu>
Posting-number: Volume 12, Issue 24
Archive-name: ln03-plot

[  This program reads output from the plot(3) library and generates
   SIXEL files.  I don't have an LN03 to test this with.  --r$  ]

The following is an ln03 printer library for the UNIX plot system. It has been
tested to a limited degree and the only known problem is that labels are hard
to place, this is because graphics and text are placed by different scaling
methods on the ln03 and I have yet to find an accurate conversion equation.

Please, if bugs are found, report them to me (with fixes?) so that a unified
update can periodically be posted.

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Makefile
#	drive.c
#	lno.h
#	order.c
#	manual.txt
#	ln03.man
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Makefile'" '(351 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
FILES= Makefile drive.c lno.h order.c
OBJECTS= drive.o order.o
LIBS= -lm
CFLAGS= -O

all: lib ln03

lib:  order.o
	ar cr libln03.a order.o

ln03: $(OBJECTS)
	cc $(CFLAGS) $(OBJECTS) $(LIBS) -o ln03plot

order.o: lno.h

clean:
	-rm -f *.o *~

package: $(FILES) manual.txt ln03.man
		shar -cv $(FILES) manual.txt ln03.man > package
print:
	lpr $(FILES)
SHAR_EOF
if test 351 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 351 characters)'
fi
fi
echo shar: "extracting 'drive.c'" '(4076 characters)'
if test -f 'drive.c'
then
	echo shar: "will not over-write existing file 'drive.c'"
else
cat << \SHAR_EOF > 'drive.c'
/* Any problems here? Talk to David Chang.  1986, Nicholas Christopher   */
#include <stdio.h>

main(argc,argv)  char **argv; {
        int std=1;
        FILE *fin;
        int deltx,delty;

        while(argc-- > 1) {
                if(*argv[1] == '-')
                        switch(argv[1][1]) {
                                case 'l':
                                        deltx = atoi(&argv[1][2]) - 1;
                                        break;
                                case 'w':
                                        delty = atoi(&argv[1][2]) - 1;
                                        break;
                                }

                else {
                        std = 0;
                        if ((fin = fopen(argv[1], "r")) == NULL) {
                                fprintf(stderr, "can't open %s\n", argv[1]);
                                exit(1);
                                }
                        fplt(fin);
                        }
                argv++;
                }
        if (std)
                fplt( stdin );
        exit(0);
        }


fplt(fin)  FILE *fin; {
        int c;
        char s[256];
        int xi,yi,x0,y0,x1,y1,r,dx,n,i;
        int pat[256];

        openpl(); 
        while((c=getc(fin)) != EOF){
                switch(c){
                case 'm':
                        xi = getsi(fin);
                        yi = getsi(fin);
                        move(xi,yi);
                        break;
                case 'l':
                        x0 = getsi(fin);
                        y0 = getsi(fin);
                        x1 = getsi(fin);
                        y1 = getsi(fin);
                        line(x0,y0,x1,y1);
                        break;
                case 't':
                        mygets(s,fin);
                        label(s);
                        break;
                case 'e':
                        erase();
                        break;
                case 'p':
                        xi = getsi(fin);
                        yi = getsi(fin);
                        point(xi,yi);
                        break;
                case 'n':
                        xi = getsi(fin);
                        yi = getsi(fin);
                        cont(xi,yi);
                        break;
                case 's':
                        x0 = getsi(fin);
                        y0 = getsi(fin);
                        x1 = getsi(fin);
                        y1 = getsi(fin);
                        space(x0,y0,x1,y1);
                        break;
                case 'b':
                        x0 = getsi(fin);
                        y0 = getsi(fin);
                        x1 = getsi(fin);
                        y1 = getsi(fin);
                        box(x0,y0,x1,y1);
                        break;
                case 'a':
                        xi = getsi(fin);
                        yi = getsi(fin);
                        x0 = getsi(fin);
                        y0 = getsi(fin);
                        x1 = getsi(fin);
                        y1 = getsi(fin);
                        arc(xi,yi,x0,y0,x1,y1);
                        break;
                case 'c':
                        xi = getsi(fin);
                        yi = getsi(fin);
                        r = getsi(fin);
                        circle(xi,yi,r);
                        break;
                case 'f':
                        mygets(s,fin);
                        linemod(s);
                        break;
                        }
                }
        closepl();
        }

getsi(fin)  FILE *fin; {        /* get an integer stored in 2 ascii bytes. */
        short a, b;
        if((b = getc(fin)) == EOF)
                return(EOF);
        if((a = getc(fin)) == EOF)
                return(EOF);
        a = a<<8;
        return(a|b);
}

mygets(s,fin)  char *s;  FILE *fin; {
        for( ; *s = getc(fin); s++)
                if(*s == '\n')
                        break;
        *s = '\0';
        return;
}
SHAR_EOF
if test 4076 -ne "`wc -c < 'drive.c'`"
then
	echo shar: "error transmitting 'drive.c'" '(should have been 4076 characters)'
fi
fi
echo shar: "extracting 'lno.h'" '(1527 characters)'
if test -f 'lno.h'
then
	echo shar: "will not over-write existing file 'lno.h'"
else
cat << \SHAR_EOF > 'lno.h'
/* (C) Copyright 1986 Nicholas Christopher. 
 *
 *				lno.h
 * This .h file accompanies my code, order.c, to produce graphics on sixel 
 * systems. If any modification are made to this code, while I am still 
 * employed by the Columbia University Center for Computing Activities, 
 * please notify me.
 *
 */

#include <stdio.h>
#define MAXVERT 243       /* verticle axis (1455) div sixels (6)   */
#define Xaxis 1185        /* horizontal pixel resolution           */
#define Yaxis 1455        /* vertical pixzel resolution            */
#define Xdec 5665         /* horizantal decipoint resolution       */
#define Ydec 7235         /* vertical decipoint resolution         */
#define abs(x) ((x>=0) ? (x) :-(x))   /* absolut value             */
#define newcount() (count = 1)        /* reset pattern count       */
int cx     = 0;           /* memory value of x coordinate          */
int cy     = 0;           /* memory value of y coordinate          */
float xscale = 1.0;       /* x axis scaling factor                 */
float yscale = 1.0;       /* y axis scaling factor                 */
int xoffset = 0;
int yoffset = 0;
int mode   = 1;           /* flag of patern dot, solid, long, etc. */
int count  = 1;           /* pattern position count, dot or space? */

struct sixel {
  unsigned int pixels :6;         /* bit vector of the six pixels  */
  int horiz;                      /* horiz coord in sparse matrix  */
  struct sixel *next;
};

struct sixel *vert[MAXVERT];      /* vert spine of sparse matrix   */

SHAR_EOF
if test 1527 -ne "`wc -c < 'lno.h'`"
then
	echo shar: "error transmitting 'lno.h'" '(should have been 1527 characters)'
fi
fi
echo shar: "extracting 'order.c'" '(17190 characters)'
if test -f 'order.c'
then
	echo shar: "will not over-write existing file 'order.c'"
else
cat << \SHAR_EOF > 'order.c'
/* 
 * The following code is designed to be used in conjunction with the UNIX    *
 * plot facilities, but may be used on its own to produce output to any      *
 * sixels printing system.                                                   *
 *                                                                           *
 * If any modification are made to this code, while I am still employed by   *
 * the Columbia University Center for Computing Activities, please notify    *
 * me, nwc@cunixc.columbia.edu.                                              *
 *                                                                           */

#include "lno.h"
#include <stdio.h>
#include <math.h>
        
openpl()
/* nothing really needed here                                                */
{
}
 

move(x,y)
/* set cx,cy memory of last points, scale them, and clear pattern counter.   */
int x,y;
{
  extern int cx,cy;

  newcount();
  ln03scale(&x,&y);
  cx = x;
  cy = y;
}



cont(x,y)
/* scaled coordinates and then pass them to extend                           */
{
     ln03scale(&x,&y);
     ln03extend(x,y);
}



point(x,y)
/* scale coordinates and pass them to spot                                   */
{
     ln03scale(&x,&y);
     ln03spot(x,y);
}



line(x1,y1,x2,y2)
/* mark a starting point and then simply use continue to go to second point  */
int x1,y1,x2,y2;
{
  
  move(x1,y1);
  ln03scale(&x2,&y2);
  ln03extend(x2,y2);
}



label(m)
/* place ascii text or math font in graph page.  This is done by direct      *
 * decipoint location addressing. The escape codes and text if placed in     *
 * the output file before the sixels output.                                 */
char *m;
{
  extern int cy,cx;                     /* coordinates to place label        */
  double xx,yy,tempx,tempy;

  tempx = cx;
  tempy = cy;
  
/*next two lines convert unscaled pixel coordinates to scaled decipoints,    *
 *the unit the LN03 positions text by.                                       */

  xx =(Xdec * (tempx/Xaxis)) + 0.07 * tempx;      
  yy =Ydec - (Ydec * (tempy/Yaxis) - 0.8 * tempy);

/* If a label starts in a "~" then tell the LN03 to use its math font.       *
 * A non math font label can begin with a tilda, just prefix it by a space.  */

  if(*m == '~'){
    printf("\033*>\033n\033[2 I\033[11h");
    printf("\033[%d`\033[%dd%s",ln03round(xx),ln03round(yy),++m);
  }
  else printf("\017\033[2 I\033[11h\033[%d`\033[%dd%s",ln03round(xx),ln03round(yy),m);
  
  cx += (strlen(m)*15);
}



arc(x,y,x1,y1,x2,y2)
/* This arc generation routine is pretty bad... I do not use it for          *
 * generating circles for this reason. Much of it depends on floating point  *
 * which, depending on the machine may not be that accurate.                 */
int x,y,x1,y1,x2,y2;
{
  double sqrt(),temp;
  register int dx,dy,radsqr;
  register int plotx,ploty,quad,rad,reps = 0;

  ln03scale(&x,&y);
  ln03scale(&x1,&y1);
  ln03scale(&x2,&y2);
  dx = abs(x1-x);
  dy = abs(y1-y);
  radsqr = dx*dx + dy*dy;
  temp = radsqr;
  rad = sqrt(temp);
  plotx = x1-x;                         /* x coord of first point in arc     */
  ploty = y1-y;                         /* y  "     "   "     "    "  "      */
  if(x1 > x+rad/2) quad = 1;            /* what quadrant are we in ?         */
    else if(x1 > x) quad = 2;
      else quad = 3;
  if(y1 < y && quad == 2 ) quad = 4;    /* under horizon of y is 4 not 2     */
  ln03filterP(x1,y1);
  while(ln03aprox(plotx+x,x2,ploty+y,y2) != 1){ /* until final coord hit, go     */
     if(quad == 2){ /* quadrants not standard, my are by the compass.        */
        plotx--;    /* we are in North quadrant so inc x and calculate y     */
        temp = radsqr - plotx*plotx;
        ploty = ln03round(sqrt(temp));
        ln03extend(plotx+x,ploty+y);
        if(plotx+x < x-rad/2){
          quad = 3;
          reps++;
          }
      }
         else if(quad == 3){            /* in west quad, inc y and calc x    */
            ploty--;
            temp = radsqr - ploty*ploty;
            plotx =0-ln03round(sqrt(temp));
            ln03extend(plotx+x,ploty+y);
            if(plotx+x >= x-rad/2){
               quad = 4;
               reps++;
            }
         }
          else if(quad == 4){           /* we are in south quad, mirror north*/
              plotx++;
              temp = radsqr - plotx*plotx;
              ploty =0-ln03round(sqrt(temp));
              ln03extend(plotx+x,ploty+y);
              if(plotx+x > x+rad/2){
                 quad = 1;
                 reps++;
              }
          }
             else{                      /* east quad, mirror west            */
                 ploty++;
                 temp = radsqr - ploty*ploty;
                 plotx = ln03round(sqrt(temp));
                 ln03extend(plotx+x,ploty+y);
                 if(plotx+x <= x+rad/2){
                    quad = 2;
                    reps++;
                 }
              }
  if(reps > 4) /* We have been around the circle more than once...oops!     */
    {
    fprintf(stderr,"Second point is not in arc of center and first point.\n");
    fprintf(stderr,"Bad arc is %d, %d, %d, %d, %d, %d.\n",x,y,x1,y1,x2,y2);
    fprintf(stderr," Converting sparse matrix built to date and exiting.\n");
    ln03conv();
    exit(1);
    }
  }
}



circle(x,y,r)
/* this generates 45 degrees of a circle, passing each point to circpoint    *
 * which distributes the point to all eight 45 degree segments.              */
int x,y,r;
{
  register int xx,yy,d;
  extern int cx,cy;
  extern float xscale,yscale;
  int dummy = 1;

  newcount();

  ln03scale(&x,&y);
  r = ln03round(r * xscale);
  xx = 0;
  yy = r;
  d  = 3-2*r;
  while( xx < yy){ 
     ln03circpoint(xx,yy,x,y);
     if(d < 0) d = d+4*xx+6;
        else{
           d = d+4*(xx-yy) + 10;
           yy--;
           }
      xx++;
  }
  if(xx == yy) ln03circpoint(xx,yy,x,y);
  cx = xx+x;
  cy = yy+y;
}



erase()
/* Just convert what we have, and start fresh.                               */
{
ln03conv();
}



linemod(s)
/* set varible "mode" to reflect pattern chosen.                             */
char *s;
{
  extern int mode;

  switch(s[0]){
        case 'l':       
                mode = 4;
                break;
        case 'd':       
                if(s[3] == 'd') mode = 5;
                else mode = 2;
                break;
        case 's':
                if(s[5] != '\0') mode = 1;
                else mode = 3;
   }
}


space(x1,y1,x2,y2)
/* set a scaling factor at users request. scale is defaulted to 1            */
int x1,y1,x2,y2;
{
  extern float xscale,yscale;
  float temp;
  extern int xoffset,yoffset;

  if (x1 < 0) xoffset = -x1;
  if (y1 < 0) yoffset = -y1;

  temp = (float)Xaxis/(x2-x1);
  xscale = floor(temp * 100.0)/100.0;
  temp = (float)Xaxis/(y2-y1);
  yscale = floor(temp * 100.0) / 100.0;
}


closepl()
{
  ln03conv();
}

/*---------------------------------------------------------------------------*/
/*           BEGIN SUPPORT ROUTINES                                          */
/*---------------------------------------------------------------------------*/

ln03extend(x1,y1)
/* Don't ask, I got this from a book, it forms a line by increment to a      *
 * point in the area nearest the line. negative slopes are achived by        *
 * mirroring a positive slope.                                               */
register int x1,y1;
{
  extern   int cx,cy;
  register int dx,dy,yincr1,mid,yincr2,yd,xincr1,xincr2,xd,x,y,xend,yend;
  register int xx,yy;
  register int neg=0;


  dx     = abs(x1-cx);
  dy     = abs(y1-cy);
  yd     = 2*dy-dx;
  yincr1 = 2*dy;
  yincr2 = 2*(dy-dx);
  xd     = 2*dx-dy;
  xincr1 = 2*dx;
  xincr2 = 2*(dx-dy);
  if (cx > x1){                         /* set up initial variables          */
    x = x1;
    y = y1;
    xend = cx;
    yend = cy;
    if(cy < y1 && cx != x1){            /* BELLS AND WISTLES negative slope  */
      neg = 1;
      mid = y1;
      yend = cy+(2*dy);                 /*set y to its + slope equivalent    */
    }
  }
  else
  {
    x = cx;
    y = cy;
    xend = x1;
    yend = y1;
    if(y1 < cy && cx != x1){            /* BELLS AND WISTLES negative slope  */
      neg = 1;
      mid = cy;
      yend = y1+(2*dy);
    }
  }
  ln03filterP(x,y);
  xx = x;
  yy = y;
  if (x == xend)                        /* we have a totally verticle line.  */
    while (y != yend){
    if (y < yend) y++;
      else y--;
    ln03filterP(x,y);
    }
  while (x < xend){
    if (yd < 0) yd += yincr1;
    else{  
      if (y < yend) y++;
      else if (y > yend) y--;
      yd += yincr2;
    }
    if (xd < 0) xd += xincr1;
    else{
      x++;
      xd += xincr2;
    }
    if (xx != x || yy != y){
    if(neg) ln03filterP(x,2*mid-y);
      else ln03filterP(x,y);
    xx = x;
    yy = y;
    }
  }
  cx = x1;                              /* remember last points              */
  cy = y1;
}



int ln03round(num)
/* float number rounding                                                     */
double num;
{
  int inum;
  double rnum;

  inum = num;
  rnum = num - inum;
  return((rnum < .5)?inum:inum+1);
}

int ln03power(z)
/* this rountine accepts an integer 0-5 and first takes its five compliment  *
 * then it returns 2 to the power of the result. exmp 3 = (5-3)^2 = 4        */
int z;
{
  register int inc,final = 2;

  z = 5-z;
  if(z ==0) final = 1;
        else if(z==1) final = 2;
                else for(inc = 2;z >= inc; inc++) final *= 2;
  return(final);
}



int ln03aprox(a,b,c,d)
/* check to see if a is aprox equal to b and if c is aprox equal to d        *
 * this is done because I don't trust arc's floating point to generate       *
 * the circumference points exactly.                                         */
int a,b,c,d;
{
  if( a <= b+1 && a >= b-1 && c <= d+1 && c >= d-1) return(1);
     else return(-1);
}



death()
/* Something, some where has created an error, or we are out of RAM,        *
 * convert the graph as it stands.                                          */
{
  fprintf(stderr,"We have ran out of memory for sparse matrix nodes.\n");
  fprintf(stderr,"  We will convert what has been done to date and leave.\n");
  ln03conv();
  exit(1);
}


ln03spot(x,y)
/* place a point given by coordinates in sparse matrix.                      */
int x,y;
{
  extern struct sixel *vert[MAXVERT];   /* this is the plotting grid         */
  struct sixel *temp,*mark,*malloc();
  extern int cy,cx;            
  register int Vval;        /* verticle coordinate to the nearest sixel      */
  register int Svval;       /* verticle coordinate, pixel remainder of sixels*/

  if(x >= 0 && x <= Xaxis && y >= 0 && y <= Yaxis){
     cy = y; cx = x;      
     Vval =(Yaxis-(y-2))/6;             /* div 6 to obtain sixels            */
     Svval = y%6;                       /* modulo to obtain pixels remainder */
     if(vert[Vval] == NULL){            /* this row is new, start it         */
        if((temp = malloc(sizeof(struct sixel)))==NULL) death();
        temp->pixels = 0|(ln03power(Svval));/* calc sixels' pixel value          */
        temp->horiz = x;
        temp->next = NULL;        
        vert[Vval] = temp;
        }
     else{                              /* row already has member(s)         */
          mark = vert[Vval];            /* set a marker to move along list   */
          while(mark->next != NULL && mark->horiz < x) mark = mark->next;

/* we are now a) at row's end, b) an equal horiz,                            *
 * c) a greater horiz.                                                       */

          if(mark->next == NULL && mark->horiz < x ){ 

/* time to add a node because horiz is too big and no next node.             */

             if((temp = malloc(sizeof(struct sixel)))==NULL) death();
             temp->pixels = 0|(ln03power(Svval));
             temp->horiz = x;
             temp->next = NULL;         /* Better safe......                 */
             mark->next = temp;         /* Add new node to vert structure.   */
             }
             else if(mark->horiz == x) mark->pixels |= ln03power(Svval);

  /* just modify this node                                                   */

                  else if(mark->horiz > x){

  /* insert new node between two present cause we have passed its spot       */

                      if((temp = malloc(sizeof(struct sixel)))==NULL) death();
                        temp->pixels = mark->pixels;
                        temp->horiz = mark->horiz;
                        temp->next = mark->next;
                        mark->pixels = 0|(ln03power(Svval));
                        mark->horiz = x;
                        mark->next = temp;
                      }
          }
    }
}


ln03conv()
/* This routine coverts a sparce matrix to LN03 format of sixels. The        * 
 * size of the output is minimized by using the LN03's repeat format:        *
 * !10? performs ? (a space) 10 times.                                       */
{
register int count,rep;
register int Hplace;                    /* horizontal displacement           */
register int lastc = 0;                 /* sixel pixel pattern holder        */
int x;
struct sixel *temp;
extern struct sixel *vert[MAXVERT];     /* sparse matrix of sixels           */
 
                                        /* ESC codes to get ln03 sixels mode */
printf("\033[2 I\033[1`\033[1d\033P000;0000;000q\"1;1"); 
for(count = 0; count < MAXVERT; count++)
  if(vert[count] == NULL) printf("?-");   /* LF for a blank row          */
    else{
      temp = vert[count];
      if(temp->horiz>0) printf("!%d?",temp->horiz-1);/*tab to 1st char   */
      printf("%c",temp->pixels+63);
      Hplace = temp->horiz;
      lastc = temp->pixels;
      rep = 0;  
      while(temp->next != NULL){
           temp = temp->next;           /* move one node horizontally        */
           if(temp->horiz == Hplace+1 && temp->pixels == lastc){
               rep++;
               Hplace++;
               }
             else{
                if(rep > 0) printf("!%d%c",rep,lastc+63);
                if(temp->horiz != Hplace+1 && temp->horiz <= Xaxis)
                   printf("!%d?",temp->horiz - Hplace - 1);
                printf("%c",temp->pixels+63);
                Hplace = temp->horiz;
                lastc = temp->pixels;
                rep = 0;
                }
           }    
      if(rep > 0) printf("!%d%c-",rep,lastc+63);
        else printf("-");
    }
printf("\033\\");                    /* Tell ln03 we are done with sixels */

for(x = 0; x < MAXVERT; x++)
  vert[x] = (struct sixel *)NULL;

}


box(x0,y0,x1,y1)
/* box drawing routine                                                       */
int x0,y0,x1,y1;
{
     int xhold,yhold;
     
     xhold = x0;
     yhold = y0;
     
     ln03scale(&x0,&y0);
     ln03scale(&x1,&y1);
     
     move(xhold,yhold);
     ln03extend(x1,y0);
     ln03extend(x1,y1);

     move(xhold,yhold);
     ln03extend(x0,y1);
     ln03extend(x1,y1);
}



ln03circpoint(xx,yy,x,y)
/* circle() only calculates 45 degrees of a circle, this distributes the     *
 * coordinates given into an entire circle. The decrementing of count is so  *
 * that the position in a pattern, i.e. point or space in "dot dash" is      *
 * not lost.                                                                 */

int xx,yy,x,y;
{
  extern int cx,cy,count;

  ln03filterP(xx+x,yy+y);
  count--;
  ln03filterP(yy+x,xx+y);
  count--;
  ln03filterP(yy+x,-xx+y);
  count--;
  ln03filterP(xx+x,-yy+y);
  count--;
  ln03filterP(-xx+x,-yy+y);
  count--;
  ln03filterP(-yy+x,-xx+y);
  count--;
  ln03filterP(-yy+x,xx+y);
  count--;
  ln03filterP(-xx+x,yy+y);
}


ln03filterP(x,y)
/* filter() acts as a middle man between a caller and spot(), i.e. if our    *
 * position in the line pattern (example: dotted line) is a blank space      *
 * then spot should not be called.                                           */
int x,y;
{
  extern int mode,count;

  switch(mode){
    case 1: ln03spot(x,y);                                /* solid line      */
                break;
    case 2: if(count <= 3 ) ln03spot(x,y);                /* dotted line     */
            if(count == 6) count = 0;
                break;
    case 3: if(count <= 6 ) ln03spot(x,y);                /* short dash      */
            if(count == 9) count =0;    
                break;
    case 4: if(count <= 9 ) ln03spot(x,y);                /* long dash       */
            if(count == 12) count =0;
                break;
                                                          /* dot dash        */
    case 5: if((count <= 6)||((count ==11)||(count==12))) ln03spot(x,y);
            if(count == 17) count = 0;
                break;
  }
  count++;                              /* increment pattern position.       */
}

ln03scale(x,y)
int *x,*y;
{
     extern float xscale,yscale;
     extern int xoffset,yoffset;
     int tempx,tempy;

     
     tempx = *x;
     tempy = *y;

     tempx += xoffset;
     tempy += yoffset;

     tempx = ln03round(tempx*xscale);
     tempy = ln03round(tempy*yscale);

     *x = tempx;
     *y = tempy;
}







SHAR_EOF
if test 17190 -ne "`wc -c < 'order.c'`"
then
	echo shar: "error transmitting 'order.c'" '(should have been 17190 characters)'
fi
fi
echo shar: "extracting 'manual.txt'" '(6901 characters)'
if test -f 'manual.txt'
then
	echo shar: "will not over-write existing file 'manual.txt'"
else
cat << \SHAR_EOF > 'manual.txt'












                                  USERS GUIDE
                                      FOR
                                 PLOT FILTERS

















                                  David Chang

                             Nicholas Christopher

                                 16 June 1987



1. INTRODUCTION TO PLOT FILTERS
 The UNIX operating system has, as one of its standard libraries, a library
which produces graphics output in a device-independent manner.  This output
can then be used as input for any compatible device-specific plot filter.
The plot filter generates commands, that when redirected to its
corresponding graphics device, will generate the desired graphics output.

The graphics library should be linked to your C program by using the -lplot
compiler switch.



2. COMMANDS
The subroutines that are included in the standard UNIX Plot library
are as follows:

   - openpl() 
     Prepares the output device for taking 
     commands.  It should always be called 
     before calling any other plot subroutines.

   - erase() 
     Reinitializes the output device. 

   - label(s) char[s]; 
     Places text in the output at the current 
     point. It takes a string variable or a string 
     in quotes as its argument.  The argument is 
     null-terminated and does not contain newlines.  
     A local modification of the command allows the 
     LN03 to use its technical font. To use the LN03 
     technical font begin the label with a tilde 
     character ("~"). A space-tilde, " ~", will 
     allow a label in the regular font to begin 
     with a tilde.

   - line(x1,y1,x2,y2)
     Produces a line that starts at the point 
     designated by the first two arguments that are 
     passed to the subroutine and terminates at the 
     point designated by the final two arguments.

   - circle(x,y,r) 
     Produces a circle whose center is given by the 
     first two arguments and whose radius is given 
     by the final argument.

   - arc(x,y,x1,y1,x2,y2) 
     Produces an arc whose center is determined by 
     the first two arguments. The starting 
     point is given by the third and fourth 
     arguments and the end point is given by the 
     final two arguments.  The arc is drawn 
     counter-clockwise.

   - move(x,y) 
     Changes the current point to the point given 
     by the two arguments.

   - cont(x,y) 
     Draws a point from the current point to the 
     point given by the two arguments.

   - point(x,y) 
     Draws a single point at the given coordinates.

   - linemod(s) char[s]; 
     Changes the line style to the given style.  
     the styles that are available are `dotted', 
     `longdashed', `shortdashed', and `dotdashed'.

   - space(x1,y1,x2,y2) 
     Changes the plot area, using the first two 
     coordinates as the upper right hand corner of 
     the plotting area and the final two arguments 
     as the lower left hand corner of the plotting 
     area.  The plot will be reduced or magnified 
     to fit the device as closely as possible.

   - closepl() 
     Closes the output device.  This should always 
     be called at the end of your program.

There are two subroutines that have been added to the standard Plot
library here at Columbia.  They are as follows:

   - box(x1,y1,x2,y2)
     Draws a box using the two points that are 
     passed as arguments as two corners.  This 
     available on all the devices.

   - color(n) 
     Changes the pen on a multicolor pen plotter 
     to the pen number designated by the argument.  
     This is only available on the pen plotters and 
     ink-jet printer.



     This  graphics  package  can be used on the Hewlett-Packard 7470A, the DEC

LVP16, the DEC LN03 laser printer, and the DEC  LCP01  color  ink-jet  printer.

The HP 7470A is a two pen plotter.  The DEC LVP16 is a six pen plotter.

     Columbia has several pen plotters available at 251 Engineering Terrace and

LN03s at both the Engineering Terrace and SIA terminal room.  The  use  of  the

plotters  requires your own plotter pens, which can be obtained in the Business

Office, and your own 8.5" by 11" or 11" by 17" paper.



3. SAMPLE SESSION

     Below is an example program in the language C to put  a  round  peg  in  a

square  hole.  If you are not familiar with the C language you should be warned

that it is case sensitive and so if you  plan  to  try  running  the  following

program maintain the capitalization exactly.
                                             /* This is a comment           */
main()                                       /* Start of program            */
{
     openpl();                               /* Initialize plot routines    */

     move(10,10);                            /* Position cursor             */
     label("Demo.");                         /* Text starts at cursor       */

     box(100,100,500,500);                   /* Draw a square hole          */
     circle(300,300,200);                    /* Put the round peg in        */

     move(10,600);                           /* Position cursor             */
     label("Done!");                         /* Some more text              */

     closepl();                              /* Close the plot routines     */
}



     Note  that  the only C in the entire program was "main() { }" the rest was

entirely plot commands. C code could have been present, to calculate a sin wave

by points for example, but knowledge of C is not required to use plot.

     The  above code must be compiled before it will run. Assume that the above

C program is in a file named peg.c. The command to compile C  code  which  uses

plot commands is as follows:


	cc -o peg peg.c -lplot


     The  above  command  generates  the  program  peg  can be run at any time,

however it is still not producing output  for  any  specific  printing  device.

Suppose  that  you  were sitting at a Tektronics terminal and wanted to see the

demonstration right on the screen. The command to give would be:


	peg | tek


     The above command takes the generalized output from peg and  feeds  it  to

the  program  tek  which knows how to display graphics on a Tektronics terminal

(the "|" character is called a pipe in UNIX and must be  included).    The  tek

program then produces the graphics on your screen. The command:


	peg | ln03 | lpr -Pmuddl1


     Would  take the same generalized output from peg feed it to ln03 a program

which creates output for the DEC LN03 printer. Then ln03  program  would  feeds

its  output to the print command, lpr -Pmuddl1, which actually prints the given

output on the LN03 printer located in 251 Engineering Terrace.

     For further documentation look in sections 1,3 and 5 of  the  UNIX  manual

under  the  title  plot. On a UNIX machine these manual sections can be read by

saying:
man 1 plot
man 3 plot
man 5 plot
SHAR_EOF
if test 6901 -ne "`wc -c < 'manual.txt'`"
then
	echo shar: "error transmitting 'manual.txt'" '(should have been 6901 characters)'
fi
fi
echo shar: "extracting 'ln03.man'" '(661 characters)'
if test -f 'ln03.man'
then
	echo shar: "will not over-write existing file 'ln03.man'"
else
cat << \SHAR_EOF > 'ln03.man'
.TH LNO3PLOT cucca
.ds SI S\s-2IX\s+2\s-2ELS\s+2
.SH NAME
ln03plot \- convert plot(5) files to S\s-2IX\s+2\s-2ELS\s+2 format
.SH SYNOPSIS
.B ln03plot
[
.I file
]
.SH DESCRIPTION
.I ln03plot
reads a
.I file
in
.IR plot (5)
format and converts it to \*(SI format on the 
standard output.  The \*(SI format is used by the LN03 printer as well as
other printers.  If no
.I file
is specified, the standard input is used.
.SH "SEE ALSO"
graph(1), ideal(1), plot(1), plot(3), plot(5), lpr(1).
.br
.SH BUGS
The LN03's printing resolution is considerably smaller than that of many
printing devices. Some input, if scaled to much larger devices may produce
poor results.
SHAR_EOF
if test 661 -ne "`wc -c < 'ln03.man'`"
then
	echo shar: "error transmitting 'ln03.man'" '(should have been 661 characters)'
fi
fi
exit 0
#	End of shell archive
-- 
		"I am the Lorvax. I speak for the machines."
______________________________________________________________________________
nwc%cunixc@columbia, columbia!cunixc!nwc  BITNET: nwcus@cuvma 
            USENET: topaz!columbia!cunixc!nwcw