home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / treepar / part01 / plot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-12  |  6.7 KB  |  319 lines

  1. /* plot.c - plotting routines
  2.  *
  3.  * 30.Jul.87  jimmc  Initial definition
  4.  *  1.Aug.87  jimmc  Add PsBox, PText, change args in PInit, add HPGL driver
  5.  * 17.Aug.87  jimmc  Add textsize function
  6.  * 19.Aug.87  jimmc  Make text device primitive work on one line only
  7.  * 26.Aug.87  jimmc  Add PSetWindow
  8.  * 22.Dec.87  jimmc  Add call to PSZSetup
  9.  * 18.Jan.88  jimmc  lint cleanup
  10.  */
  11.  
  12. #include <strings.h>
  13. #include "plot.h"
  14.  
  15. extern char *malloc();
  16. extern char *index();
  17.  
  18. static PDevInfo *infobase;
  19. static PDevInfo *currentinfo;
  20. static char *currentfn;
  21.  
  22. static float Pscale;
  23. static int Poffsetx,Poffsety;
  24. static int Pbasex,Pbasey;
  25. static int TextSizeX, TextSizeY;
  26. #define SCALEONLY(n) (int)(Pscale*((float)(n)))
  27. #define SCALEX(x) (Poffsetx+(int)(Pscale*((float)(x-Pbasex))))
  28. #define SCALEY(y) (Poffsety+(int)(Pscale*((float)(y-Pbasey))))
  29.  
  30. static double wslx=0.0;
  31. static double wshx=1.0;
  32. static double wsly=0.0;
  33. static double wshy=1.0;
  34. int wlx,wly,whx,why;    /* window boundaries */
  35.  
  36. static int
  37. badfunc()
  38. {
  39.     printf("Bad function pointer in plot package\n");
  40. }
  41.  
  42. int            /* 1 if OK */
  43. PSetType(ptype,filename)
  44. char *ptype;        /* plotter type */
  45. char *filename;
  46. {
  47. PDevInfo *p;
  48.  
  49.     for (p=infobase; p; p=p->next)
  50.         if (strcmp(ptype,p->name)==0) break;
  51.     if (!p) {
  52.         printf("no such plot type %s\n", ptype);
  53.         return 0;
  54.     }
  55.     currentinfo = p;
  56.     if (currentfn) free(currentfn);
  57.     currentfn = malloc((unsigned)(strlen(filename)+1));
  58.     if (!currentfn) {
  59.         printf("no memory for filename");
  60.         return 0;
  61.     }
  62.     strcpy(currentfn,filename);
  63.     return 1;
  64. }
  65.  
  66. PSetWindow(lx,ly,hx,hy)    /* normalized window coords (0.0 to 1.0) */
  67. double lx,ly,hx,hy;
  68. {
  69. double t;
  70.  
  71.     if (hx==lx || hy==ly) return;
  72.     if (hx<lx) { t=hx; hx=lx; lx=t; }
  73.     if (hy<ly) { t=hy; hy=ly; ly=t; }
  74.     if (lx<0.0) lx=0.0;
  75.     if (hx>1.0) hx=1.0;
  76.     if (ly<0.0) ly=0.0;
  77.     if (hy>1.0) hy=1.0;
  78.     wslx=lx;
  79.     wshx=hx;
  80.     wsly=ly;
  81.     wshy=hy;
  82. }
  83.  
  84. PInit(lx,ly,hx,hy)
  85. int lx,ly;
  86. int hx,hy;
  87. {
  88. int devlx,devly,devhx,devhy;
  89. int devx,devy;
  90. int vx,vy;
  91. double xr,yr;
  92.  
  93.     wlx = lx + wslx*(hx-lx);    /* do the window scaling */
  94.     whx = lx + wshx*(hx-lx);
  95.     wly = ly + wsly*(hy-ly);
  96.     why = ly + wshy*(hy-ly);
  97.     vx = whx-wlx+1;    /* x dimension of virtual drawing area */
  98.     vy = why-wly+1;
  99.     if (!((*currentinfo->init)(currentfn,&devlx,&devly,&devhx,&devhy))) {
  100.             /* get device size */
  101.         return 0;    /* no init */
  102.     }
  103.     devx = devhx-devlx+1;
  104.     devy = devhy-devly+1;
  105.     xr = ((double)devx)/((double)vx);
  106.     yr = ((double)devy)/((double)vy);
  107.     Pbasex = wlx;
  108.     Pbasey = wly;
  109.     if (xr>=yr) {        /* scale to fix x */
  110.         Pscale = yr*0.95;
  111.         Poffsetx = ((int)(0.025*((double)devx)))+devlx;
  112.         Poffsety = ((int)(0.025*((double)devy)))+devly;
  113.     } else {        /* scale to fit y */
  114.         Pscale = xr*0.95;
  115.         Poffsetx = ((int)(0.025*((double)devx)))+devlx;
  116.         Poffsety = ((int)(0.025*((double)devy)))+devly;
  117.     }
  118.     return 1;
  119. }
  120.  
  121. PDone()
  122. {
  123.     (*currentinfo->done)();
  124. }
  125.  
  126. PTextSize(x,y)
  127. int x,y;        /* width and height of one character */
  128. {
  129.     TextSizeX = x;
  130.     TextSizeY = y;
  131.     (*currentinfo->textsize)(SCALEONLY(x),SCALEONLY(y));
  132. }
  133.  
  134. #define ASCALE 10000
  135. typedef int Alphatype;
  136. #define ALPH(a,l,h) (l+(int)((a*(h-l))/ASCALE))
  137. #define Paline(lx,ly,hx,hy) \
  138.     (*currentinfo->line)(SCALEX(lx),SCALEY(ly),SCALEX(hx),SCALEY(hy));
  139.  
  140. static Alphatype
  141. alpha(l,h,w)
  142. int l,h;
  143. int w;
  144. {
  145. Alphatype a;
  146.     if (l==h) return 0;
  147.     a = (ASCALE*(w-l))/(h-l);
  148.     if (a<0) return 0;
  149.     if (a>ASCALE) return ASCALE;
  150.     return a;
  151. }
  152.  
  153. PLine(lx,ly,hx,hy)
  154. int lx,ly;
  155. int hx,hy;
  156. {
  157. int t;
  158. Alphatype aly,ahy;
  159. Alphatype alx,ahx;
  160. Alphatype al,ah;
  161.  
  162.     if (hx<wlx || lx>whx || hy<wly || ly>why) return;
  163.     if (lx==hx) {    /* vertical line */
  164.         aly = alpha(ly,hy,wly);
  165.         ahy = alpha(ly,hy,why);
  166.         if (aly!=ahy) Paline(lx,ALPH(aly,ly,hy),hx,ALPH(ahy,ly,hy));
  167.     }
  168.     else if (ly==hy) {    /* horizontal line */
  169.         alx = alpha(lx,hx,wlx);
  170.         ahx = alpha(lx,hx,whx);
  171.         if (alx!=ahx) Paline(ALPH(alx,lx,hx),ly,ALPH(ahx,lx,hx),hy);
  172.     }
  173.     else {    /* angled line */
  174. #define ORDER(l,h) { \
  175.     if (l>h) { \
  176.         t = l; \
  177.         l = h; \
  178.         h = t; \
  179.     }}
  180.         aly = alpha(ly,hy,wly);
  181.         ahy = alpha(ly,hy,why);
  182.         alx = alpha(lx,hx,wlx);
  183.         ahx = alpha(lx,hx,whx);
  184.         ORDER(aly,ahy)
  185.         ORDER(alx,ahx)
  186.         al = (alx>aly)?alx:aly;    /* use highest low and lowest high */
  187.         ah = (ahx<ahy)?ahx:ahy;
  188.         if (al!=ah)
  189.             Paline(ALPH(al,lx,hx),ALPH(al,ly,hy),
  190.                    ALPH(ah,lx,hx),ALPH(ah,ly,hy));
  191.     }
  192. }
  193.  
  194. PBox(lx,ly,hx,hy)
  195. int lx,ly;
  196. int hx,hy;
  197. {
  198.     PLine(lx,ly,lx,hy);
  199.     PLine(lx,hy,hx,hy);
  200.     PLine(hx,hy,hx,ly);
  201.     PLine(hx,ly,lx,ly);
  202. }
  203.  
  204. /* Characters are clipped based on the lower left corner point of each char. */
  205. PTextLine(lx,ly,text)
  206. int lx,ly;    /* lower left corner of text line */
  207. char *text;
  208. {
  209. int hx;
  210. int l;
  211. int oldc=0;
  212.  
  213.     if (!text || !*text) return;
  214.     l = strlen(text);
  215.     hx = lx + l*TextSizeX;
  216.     if (hx<wlx || lx>=whx || ly<wly || ly>=why) return;    /* out */
  217.     if (lx<wlx) {    /* hangs out the left, lets clip that part */
  218.         l = (wlx-lx+TextSizeX-1)/TextSizeX;
  219.             /* number of chars to clip */
  220.         text += l;
  221.         lx += l*TextSizeX;
  222.     }
  223.     if (hx>whx) {    /* hangs out the right */
  224.         l = (hx-whx)/TextSizeX;
  225.         l = strlen(text)-l;
  226.         oldc = text[l];
  227.         text[l] = 0;
  228.     }
  229.     (*currentinfo->text)(SCALEX(lx),SCALEY(ly),text);
  230.     if (oldc) text[l]=oldc;    /* restore if we changed it */
  231. }
  232.  
  233. PText(x,y,p,text)
  234. int x,y;
  235. int p;        /* position of (x,y) in text (see plot.h) */
  236. char *text;
  237. {
  238. int sx,sy;    /* size of the text block */
  239. char *t,*e;
  240. int len;
  241.  
  242.     sx = sy = 0;    /* find the size of the text block */
  243.     for (t=text;t;t=e) {
  244.         sy++;    /* count lines */
  245.         e = index(t,'\n');
  246.         if (e) len = (e++)-t;
  247.         else len = strlen(t);
  248.         if (len>sx) sx=len;    /* count characters */
  249.     }
  250.     if (sx==0 || sy==0) return;
  251.     sx *= TextSizeX;
  252.     sy *= TextSizeY;
  253.     switch (p) {    /* convert (x,y) to point to lower left */
  254.     case N:        x -= sx/2; y -= sy; break;
  255.     case S:        x -= sx/2; break;
  256.     case E:        x -= sx; y -= sy/2; break;
  257.     case W:        y -= sy/2; break;
  258.     case NE:    x -= sx; y -= sy; break;
  259.     case NW:    y -= sy; break;
  260.     case SE:    x -= sx; break;
  261.     case SW:    break;    /* this is the default location */
  262.     case C:        x -= sx/2; y -= sy/2; break;
  263.     default:    break;    /* assume default for random stuff */
  264.     }
  265.     y += sy;    /* point to upper left corner */
  266.     while (text) {
  267.         y -= TextSizeY;    /* point to lower left for this line */
  268.         e = index(text,'\n');
  269.         if (e) *e='\000';
  270.         PTextLine(x,y,text);
  271.         if (e) *(e++)='\n';    /* restore */
  272.         text = e;
  273.     }
  274. }
  275.  
  276. PDevInfo *
  277. Pnew()
  278. {
  279. PDevInfo *p;
  280.  
  281.     p = (PDevInfo *)malloc(sizeof(PDevInfo));
  282.     if (!p) {
  283.         printf("no more memory\n");  /*** needs to be more elegant */
  284.         exit(1);
  285.     }
  286.     p->name = "NONAME";
  287.     p->init = badfunc;
  288.     p->done = badfunc;
  289.     p->line = badfunc;
  290.     p->textsize = badfunc;
  291.     p->text = badfunc;
  292.     p->next = infobase;    /* add to list */
  293.     infobase = p;
  294.     return p;
  295. }
  296.  
  297. PNullSetup()
  298. {
  299. PDevInfo *p;
  300.     p = Pnew();
  301.     p->name = "NULL";
  302.         /* leave other stuff as illegal */
  303.     currentinfo = p;
  304. }
  305.  
  306. PSetup()
  307. {
  308.     PNullSetup();    /* set up the non-device */
  309.             /* next, set up each device */
  310. #ifdef X10
  311.     PXSetup();
  312. #endif
  313.     PHPSetup();
  314.     PTSetup();
  315.     PSZSetup();
  316. }
  317.  
  318. /* end */
  319.