home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume8 / gnuplot1.10A / part02 / graphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-09  |  8.8 KB  |  384 lines

  1. /*
  2.  *
  3.  *    G N U P L O T  --  graphics.c
  4.  *
  5.  *  Copyright (C) 1986, 1987  Thomas Williams, Colin Kelley
  6.  *
  7.  *  You may use this code as you wish if credit is given and this message
  8.  *  is retained.
  9.  *
  10.  *  Please e-mail any useful additions to vu-vlsi!plot so they may be
  11.  *  included in later releases.
  12.  *
  13.  *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include "plot.h"
  19.  
  20. char *strcpy(),*strncpy(),*strcat();
  21.  
  22. extern BOOLEAN polar;
  23. extern BOOLEAN autoscale;
  24. extern FILE *outfile;
  25. extern BOOLEAN log_x, log_y;
  26. extern int term;
  27.  
  28. extern BOOLEAN screen_ok;
  29. extern BOOLEAN term_init;
  30.  
  31. extern double loff,roff,toff,boff;
  32. extern double zero;
  33.  
  34. extern struct termentry term_tbl[];
  35.  
  36.  
  37. #ifndef max        /* Lattice C has max() in math.h, but shouldn't! */
  38. #define max(a,b) ((a > b) ? a : b)
  39. #endif
  40.  
  41. /* maps floating point x (and y) to screen */ 
  42. #define map_x(x) (int)((x-xmin)*xscale) 
  43. #define map_y(y) (int)((y-ymin)*yscale)
  44.  
  45.  
  46. double raise(x,y)
  47. double x;
  48. int y;
  49. {
  50. register int i;
  51. double val;
  52.  
  53.     val = 1.0;
  54.     for (i=0; i < abs(y); i++)
  55.         val *= x;
  56.     if (y < 0 ) return (1.0/val);
  57.     return(val);
  58. }
  59.  
  60.  
  61. double make_tics(tmin,tmax,logscale)
  62. double tmin,tmax;
  63. BOOLEAN logscale;
  64. {
  65. register double xr,xnorm,tics,tic,l10;
  66.  
  67.     xr = fabs(tmin-tmax);
  68.     
  69.     l10 = log10(xr);
  70.     if (logscale) {
  71.         tic = raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
  72.         if (tic < 1.0)
  73.             tic = 1.0;
  74.     } else {
  75.         xnorm = pow(10.0,l10-(double)((l10 >= 0.0 ) ? (int)l10 : ((int)l10-1)));
  76.         if (xnorm <= 2)
  77.             tics = 0.2;
  78.         else if (xnorm <= 5)
  79.             tics = 0.5;
  80.         else tics = 1.0;    
  81.         tic = tics * raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
  82.     }
  83.     return(tic);
  84. }
  85.  
  86. char *idx(a,b)
  87. char *a,b;
  88. {
  89.     do {
  90.         if (*a == b)
  91.             return(a);
  92.     } while (*a++);
  93.     return(0);
  94. }
  95.  
  96.  
  97. num2str(num,str)
  98. double num;
  99. char str[];
  100. {
  101. static char temp[80];
  102. register double d;
  103. register char *a,*b;
  104.  
  105.      if ((d = fabs(num)) > 9999.0 || d < 0.001 && d != 0.0) 
  106.         (void) sprintf(temp,"%-.3e",num);    
  107.     else
  108.         (void) sprintf(temp,"%-.3g",num);
  109.     if (b = idx(temp,'e')) {
  110.         a = b;
  111.         while ( *(--a) == '0') /* trailing zeros */
  112.             ;    
  113.         if ( *a == '.') 
  114.             a--;
  115.         (void) strncpy(str,temp,(int)(a-temp)+1);
  116.         str[(int)(a-temp)+1] = '\0';
  117.         a = b+1;    /* point to 1 after 'e' */
  118.         (void) strcat(str,"e");
  119.         if ( *a == '-') 
  120.             (void) strcat(str,"-");
  121.         a++;                         /* advance a past '+' or '-' */
  122.         while ( *a == '0' && *(a+1) != '\0') /* leading zeroes */
  123.             a++;
  124.         (void) strcat(str,a); /* copy rest of string */
  125.     }
  126.     else
  127.         (void) strcpy(str,temp);    
  128. }
  129.  
  130.  
  131. do_plot(plots, pcount, xmin, xmax, ymin, ymax)
  132. struct curve_points *plots;
  133. int pcount;            /* count of plots in linked list */
  134. double xmin, xmax;
  135. double ymin, ymax;
  136. {
  137. register int i, x;
  138. register struct termentry *t = &term_tbl[term];
  139. register BOOLEAN prev_undef;
  140. register int curve, xaxis_y, yaxis_x, dpcount;
  141. register struct curve_points *this_plot;
  142. register enum PLOT_TYPE p_type;
  143. register double xscale, yscale;
  144. register double ytic, xtic, least, most, ticplace;
  145. register int mms,mts;
  146.             /* only a Pyramid would have this many registers! */
  147. static char xns[20],xms[20],yns[20],yms[20],xts[20],yts[20];
  148. static char label[80];
  149.  
  150.     if (polar)
  151.         polar_xform (plots, pcount, &xmin, &xmax, &ymin, &ymax);
  152.  
  153.     if (ymin == HUGE || ymax == -HUGE)
  154.         int_error("all points undefined!", NO_CARET);
  155.  
  156. /*    This used be xmax == xmin, but that caused an infinite loop once. */
  157.     if (fabs(xmax - xmin) < zero)
  158.         int_error("xmin should not equal xmax!",NO_CARET);
  159.     if (fabs(ymax - ymin) < zero)
  160.         int_error("ymin should not equal ymax!",NO_CARET);
  161.  
  162. /*    Apply the desired viewport offsets. */
  163.     xmin -= loff;
  164.     xmax += roff;
  165.     ymin -= boff;
  166.     ymax += toff;
  167.     
  168.     ytic = make_tics(ymin,ymax,log_y);
  169.     xtic = make_tics(xmin,xmax,log_x);
  170.     dpcount = 0;
  171.     
  172.     if (ymin < ymax ) {
  173.         ymin = ytic * floor(ymin/ytic);    
  174.         ymax = ytic * ceil(ymax/ytic);
  175.     }
  176.     else {
  177.         ymin = ytic * ceil(ymin/ytic);
  178.         ymax = ytic * floor(ymax/ytic);
  179.     }
  180.  
  181.     yscale = (t->ymax - 2)/(ymax - ymin);
  182.     xscale = (t->xmax - 2)/(xmax - xmin);
  183.     
  184.     if (!term_init) {
  185.         (*t->init)();
  186.         term_init = TRUE;
  187.     }
  188.     screen_ok = FALSE;
  189.     (*t->graphics)();
  190.     (*t->linetype)(-2); /* border linetype */
  191.  
  192.     /* draw plot border */
  193.     (*t->move)(0,0);    
  194.     (*t->vector)(t->xmax-1,0);    
  195.     (*t->vector)(t->xmax-1,t->ymax-1);    
  196.     (*t->vector)(0,t->ymax-1);    
  197.     (*t->vector)(0,0);
  198.  
  199.     least = (ymin < ymax) ? ymin : ymax;
  200.     most = (ymin < ymax) ? ymax : ymin;
  201.  
  202.     for (ticplace = ytic + least; ticplace < most ; ticplace += ytic) { 
  203.         (*t->move)(0,map_y(ticplace));
  204.         (*t->vector)(t->h_tic,map_y(ticplace));
  205.         (*t->move)(t->xmax-1,map_y(ticplace));
  206.                    (*t->vector)(t->xmax-1-t->h_tic,map_y(ticplace));
  207.     }
  208.  
  209.     if (xmin < xmax ) {
  210.         least = xtic * floor(xmin/xtic);    
  211.         most = xtic * ceil(xmax/xtic);
  212.     }
  213.     else {
  214.         least = xtic * ceil(xmin/xtic);
  215.         most = xtic * floor(xmax/xtic);
  216.     }
  217.  
  218.     for (ticplace = xtic + least; ticplace < most ; ticplace += xtic) { 
  219.         (*t->move)(map_x(ticplace),0);
  220.         (*t->vector)(map_x(ticplace),t->v_tic);
  221.         (*t->move)(map_x(ticplace),t->ymax-1);
  222.                    (*t->vector)(map_x(ticplace),t->ymax-1-t->v_tic);
  223.     }
  224.  
  225.     if (log_x) {
  226.         num2str(pow(10.0,xmin),xns);
  227.         num2str(pow(10.0,xmax),xms);
  228.         num2str(pow(10.0,xtic),xts);
  229.     }
  230.     else {
  231.         num2str(xmin,xns);
  232.         num2str(xmax,xms);
  233.         num2str(xtic,xts);
  234.     }
  235.     if (log_y) {
  236.         num2str(pow(10.0,ymin),yns);
  237.         num2str(pow(10.0,ymax),yms);
  238.         num2str(pow(10.0,ytic),yts);
  239.     } else {
  240.         num2str(ymin,yns);
  241.         num2str(ymax,yms);
  242.         num2str(ytic,yts);
  243.     }
  244.     mms = max(strlen(xms),strlen(yms));
  245.     mts = max(strlen(xts),strlen(yts));
  246.  
  247.     (void) sprintf(label,"%s < y < %-*s  inc = %-*s",yns,mms,yms,mts,yts);
  248.     (*t->lrput_text)(0, label);
  249.     (void) sprintf(label,"%s < x < %-*s  inc = %-*s",xns,mms,xms,mts,xts);
  250.     (*t->lrput_text)(1, label);
  251.  
  252.  
  253. /* DRAW AXES */
  254.     (*t->linetype)(-1);    /* axis line type */
  255.     xaxis_y = map_y(0.0);
  256.     yaxis_x = map_x(0.0); 
  257.  
  258.     if (xaxis_y < 0)
  259.         xaxis_y = 0;                /* save for impulse plotting */
  260.     else if (xaxis_y >= t->ymax)
  261.         xaxis_y = t->ymax - 1;
  262.     else if (!log_y) {
  263.         (*t->move)(0,xaxis_y);
  264.         (*t->vector)((t->xmax-1),xaxis_y);
  265.     }
  266.  
  267.     if (!log_x && yaxis_x >= 0 && yaxis_x < t->xmax) {
  268.         (*t->move)(yaxis_x,0);
  269.         (*t->vector)(yaxis_x,(t->ymax-1));
  270.     }
  271.  
  272. /* DRAW CURVES */
  273.     this_plot = plots;
  274.     for (curve = 0; curve < pcount; this_plot = this_plot->next_cp, curve++) {
  275.         (*t->linetype)(curve);
  276.         (*t->ulput_text)(curve, this_plot->title);
  277.         (*t->linetype)(curve);
  278.  
  279.         p_type = this_plot->plot_type;
  280.         switch(this_plot->plot_style) {
  281.             case IMPULSES:
  282.                 for (i = 0; i < this_plot->p_count; i++) {
  283.                     if (!this_plot->points[i].undefined) {
  284.                         x = map_x(this_plot->points[i].x);
  285.                         (*t->move)(x,xaxis_y);
  286.                         (*t->vector)(x,map_y(this_plot->points[i].y));
  287.                     }
  288.                 }
  289.                 break;
  290.             case LINES:
  291.                 prev_undef = TRUE;
  292.                 for (i = 0; i < this_plot->p_count; i++) {
  293.                     if (!this_plot->points[i].undefined) {
  294.                         x = map_x(this_plot->points[i].x);
  295.                         if (prev_undef)
  296.                             (*t->move)(x,
  297.                             map_y(this_plot->points[i].y));
  298.                         (*t->vector)(x,
  299.                             map_y(this_plot->points[i].y));
  300.                     }
  301.                     prev_undef = this_plot->points[i].undefined;
  302.                 }
  303.                 break;
  304.             case POINTS:
  305.                 for (i = 0; i < this_plot->p_count; i++) {
  306.                     if (!this_plot->points[i].undefined) {
  307.                         x = map_x(this_plot->points[i].x);
  308.                         (*t->point)(x,map_y(this_plot->points[i].y),dpcount);
  309.                     }
  310.                 }
  311.                 dpcount++;
  312.                 break;
  313.         }
  314.     }
  315.     (*t->text)();
  316.     (void) fflush(outfile);
  317. }
  318.  
  319.  
  320. polar_xform (plots, pcount, xminp, xmaxp, yminp, ymaxp)
  321. struct curve_points *plots;
  322. int pcount;            /* count of plots in linked list */
  323. double *xminp, *xmaxp;
  324. double *yminp, *ymaxp;
  325. {
  326. register int i, p_cnt;
  327. register struct termentry *t = &term_tbl[term];
  328. register struct curve_points *this_plot;
  329. enum PLOT_TYPE p_type;
  330. struct coordinate *pnts;
  331. int curve, xaxis_y, yaxis_x, dpcount;
  332. double xmin, xmax, ymin, ymax, x, y;
  333.  
  334. /*
  335.     Cycle through all the plots converting polar to rectangular and adjust
  336.     max and mins.
  337. */
  338.     xmin = HUGE;
  339.     ymin = HUGE;
  340.     xmax = -HUGE;
  341.     ymax = -HUGE;
  342.     
  343.     this_plot = plots;
  344.     for (curve = 0; curve < pcount; this_plot = this_plot->next_cp, curve++) {
  345.         p_cnt = this_plot->p_count;
  346.         pnts = this_plot->points;
  347.  
  348.     /*    Convert to cartesian all points in this curve. */
  349.         for (i = 0; i < p_cnt; i++) {
  350.             if (!pnts[i].undefined) {
  351.                 x = pnts[i].y*cos(pnts[i].x);
  352.                 y = pnts[i].y*sin(pnts[i].x);
  353.                 pnts[i].x = x;
  354.                 pnts[i].y = y;
  355.                 if (xmin > x) xmin = x;
  356.                 if (xmax < x) xmax = x;
  357.             /*  Can't worry about autoscale (assume true). */
  358.                 if (ymin > y) ymin = y;
  359.                 if (ymax < y) ymax = y;
  360.             }
  361.         }    
  362.     }
  363.     if (xmin < xmax) {  /* All points might be undefined... */
  364.         if (xmax - xmin < zero) {
  365.         /* This happens at least for the plot of 1/cos(x) (verticle line). */
  366.             xmin -= 3.14159;
  367.             xmax += 3.14159;
  368.         }
  369.     }
  370.     if (ymin < ymax) {  /* Only if there were defined points... */
  371.         if (ymax - ymin < zero) {
  372.         /* This happens at least for the plot of 1/sin(x) (horizontal line). */
  373.             ymin -= 1;
  374.             ymax += 1;
  375.         }
  376.     }
  377.  
  378. /* Return the new maximums and minimums */
  379.     *xminp = xmin;
  380.     *xmaxp = xmax;
  381.     *yminp = ymin;
  382.     *ymaxp = ymax;
  383. }
  384.