Back to index

radiance  4R0+20100331
mgraph.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: mgraph.c,v 1.2 2003/11/15 02:13:37 schorsch Exp $";
00003 #endif
00004 /*
00005  *  mgraph.c - routines for plotting graphs from variables.
00006  *
00007  *     6/23/86
00008  *
00009  *     Greg Ward Larson
00010  */
00011 
00012 #include  <stdio.h>
00013 #include  <string.h>
00014 
00015 #include  "meta.h"
00016 #include  "mgvars.h"
00017 #include  "mgraph.h"
00018 
00019 extern char  *progname;                   /* argv[0] */
00020 
00021 extern double  goodstep(), floor(), ceil(), sin(), cos();
00022 
00023 static BOUNDS  xbounds, ybounds;   /* the boundaries for the graph */
00024 
00025 static double  period = DEFPERIOD; /* period for polar plot */
00026 
00027 static double  axbegin, axsize;           /* the mapped x axis boundaries */
00028 static double  aybegin, aysize;           /* the mapped y axis boundaries */
00029 
00030 static int  npltbl[MAXCUR];        /* plottable points per curve */
00031 
00032 static double  lastx, lasty;              /* last curve postion */
00033 static int  nplottable;                   /* number of plottable points */
00034 static int  nplotted;                     /* number of plotted points */
00035 
00036 static void getbounds(void);
00037 static void polaraxis(void);
00038 static void makeaxis(void);
00039 static void plotcurves(void);
00040 static void cartaxis(void);
00041 static void stretchbounds(int  c, double  x, double  y);
00042 static void boxstring(int  xmin, int ymin, int xmax, int ymax,
00043        char  *s, int  d, int width, int color);
00044 static void drawcircle(int  x, int y, int r, int  typ, int wid, int col);
00045 static int rconv(double  r);
00046 static int xconv(double  x);
00047 static int yconv(double  y);
00048 static void csymbol(int  c, double  u, double v);
00049 static int cmline(int  c, int  x, int y);
00050 static void cmsymbol(int  c, int  x, int y);
00051 static int inbounds(double  x, double y);
00052 static void climline(int  c, double  x, double y, double xout, double yout);
00053 static void nextpoint(register int  c, double  x, double  y);
00054 static void cline(int  c, double  u1, double v1, double u2, double v2);
00055 
00056 
00057 void
00058 mgraph(void)                /* plot the current graph */
00059 {
00060                                    /* load the symbol file */
00061        if (gparam[SYMFILE].flags & DEFINED)
00062               minclude(gparam[SYMFILE].v.s);
00063                                    /* check for polar plot */
00064        if (gparam[PERIOD].flags & DEFINED)
00065               period = varvalue(gparam[PERIOD].name);
00066 
00067        getbounds();                /* get the boundaries */
00068        makeaxis();                 /* draw the coordinate axis */
00069        plotcurves();               /* plot the curves */
00070 
00071        mendpage();                 /* advance page */
00072 }
00073 
00074 
00075 void
00076 getbounds(void)                    /* compute the boundaries */
00077 {
00078        int  i;
00079 
00080        xbounds.min = gparam[XMIN].flags & DEFINED ?
00081                       varvalue(gparam[XMIN].name) - FTINY :
00082                       FHUGE ;
00083        xbounds.max = gparam[XMAX].flags & DEFINED ?
00084                       varvalue(gparam[XMAX].name) + FTINY :
00085                       -FHUGE ;
00086        ybounds.min = gparam[YMIN].flags & DEFINED ?
00087                       varvalue(gparam[YMIN].name) - FTINY :
00088                       FHUGE ;
00089        ybounds.max = gparam[YMAX].flags & DEFINED ?
00090                       varvalue(gparam[YMAX].name) + FTINY :
00091                       -FHUGE ;
00092 
00093        nplottable = 0;
00094        for (i = 0; i < MAXCUR; i++) {
00095               npltbl[i] = 0;
00096               mgcurve(i, stretchbounds);
00097               nplottable += npltbl[i];
00098        }
00099        if (nplottable == 0) {
00100               fprintf(stderr, "%s: no plottable data\n", progname);
00101               quit(1);
00102        }
00103 
00104        xbounds.step = gparam[XSTEP].flags & DEFINED ?
00105                        varvalue(gparam[XSTEP].name) :
00106                        period > FTINY ?
00107                             DEFPLSTEP*period :
00108                             goodstep(xbounds.max - xbounds.min) ;
00109        if (!(gparam[XMIN].flags & DEFINED))
00110               xbounds.min = floor(xbounds.min/xbounds.step) *
00111                                    xbounds.step;
00112        if (!(gparam[XMAX].flags & DEFINED))
00113               xbounds.max = ceil(xbounds.max/xbounds.step) *
00114                                    xbounds.step;
00115        ybounds.step = gparam[YSTEP].flags & DEFINED ?
00116                        varvalue(gparam[YSTEP].name) :
00117                        period > FTINY ?
00118                             goodstep((ybounds.max - ybounds.min)*1.75) :
00119                             goodstep(ybounds.max - ybounds.min) ;
00120        if (!(gparam[YMIN].flags & DEFINED))
00121               ybounds.min = floor(ybounds.min/ybounds.step) *
00122                                    ybounds.step;
00123        if (!(gparam[YMAX].flags & DEFINED))
00124               ybounds.max = ceil(ybounds.max/ybounds.step) *
00125                                    ybounds.step;
00126        if (gparam[XMAP].flags & DEFINED) {
00127               axbegin = funvalue(gparam[XMAP].name, 1, &xbounds.min);
00128               axsize = funvalue(gparam[XMAP].name, 1, &xbounds.max);
00129               axsize -= axbegin;
00130        } else {
00131               axbegin = xbounds.min;
00132               axsize = xbounds.max;
00133               axsize -= axbegin;
00134        }
00135        if (gparam[YMAP].flags & DEFINED) {
00136               aybegin = funvalue(gparam[YMAP].name, 1, &ybounds.min);
00137               aysize = funvalue(gparam[YMAP].name, 1, &ybounds.max);
00138               aysize -= aybegin;
00139        } else {
00140               aybegin = ybounds.min;
00141               aysize = ybounds.max;
00142               aysize -= aybegin;
00143        }
00144 }
00145 
00146 
00147 void
00148 makeaxis(void)                            /* draw the coordinate axis */
00149 {
00150        char  stmp[64];
00151 
00152        if (period > FTINY)
00153               polaraxis();
00154        else
00155               cartaxis();
00156                                           /* x axis label */
00157        if (gparam[XLABEL].flags & DEFINED)
00158               boxstring(XL_L,XL_D,XL_R,XL_U,gparam[XLABEL].v.s,'r',0,0);
00159                                           /* x mapping */
00160        if (gparam[XMAP].flags & DEFINED) {
00161               mgtoa(stmp, &gparam[XMAP]);
00162               boxstring(XM_L,XM_D,XM_R,XM_U,stmp,'r',0,0);
00163        }
00164                                           /* y axis label */
00165        if (gparam[YLABEL].flags & DEFINED)
00166               boxstring(YL_L,YL_D,YL_R,YL_U,gparam[YLABEL].v.s,'u',0,0);
00167                                           /* y mapping */
00168        if (gparam[YMAP].flags & DEFINED) {
00169               mgtoa(stmp, &gparam[YMAP]);
00170               boxstring(YM_L,YM_D,YM_R,YM_U,stmp,'u',0,0);
00171        }
00172                                           /* title */
00173        if (gparam[TITLE].flags & DEFINED)
00174               boxstring(TI_L,TI_D,TI_R,TI_U,gparam[TITLE].v.s,'r',2,0);
00175                                           /* subtitle */
00176        if (gparam[SUBTITLE].flags & DEFINED)
00177               boxstring(ST_L,ST_D,ST_R,ST_U,gparam[SUBTITLE].v.s,'r',1,0);
00178                                           /* legend */
00179        if (gparam[LEGEND].flags & DEFINED)
00180               mtext(LT_X, LT_Y, gparam[LEGEND].v.s, CPI, 0);
00181 }
00182 
00183 
00184 void
00185 polaraxis(void)                           /* print polar coordinate axis */
00186 {
00187        int  lw, tstyle, t0, t1;
00188        double  d, d1, ybeg;
00189        char  stmp[64], *fmt, *goodformat();
00190                                           /* get tick style */
00191        if (gparam[TSTYLE].flags & DEFINED)
00192               tstyle = varvalue(gparam[TSTYLE].name) + 0.5;
00193        else
00194               tstyle = DEFTSTYLE;
00195                                           /* start of numbering */
00196        ybeg = ceil(ybounds.min/ybounds.step)*ybounds.step;
00197                                           /* theta (x) numbering */
00198        fmt = goodformat(xbounds.step);
00199        for (d = 0.0; d < period-FTINY; d += xbounds.step) {
00200               sprintf(stmp, fmt, d);
00201               d1 = d*(2*PI)/period;
00202               t0 = TN_X + TN_R*cos(d1) + .5;
00203               if (t0 < TN_X)
00204                      t0 -= strlen(stmp)*CWID;
00205               mtext(t0,(int)(TN_Y+TN_R*sin(d1)+.5),stmp,CPI,0);
00206        }
00207                                           /* radius (y) numbering */
00208        fmt = goodformat(ybounds.step);
00209        lw = PL_R+RN_S;
00210        for (d = ybeg; d <= ybounds.max+FTINY; d += ybounds.step) {
00211               t0 = rconv(d);
00212               if (t0 >= lw+RN_S || t0 <= lw-RN_S) {
00213                      sprintf(stmp, fmt, d);
00214                      mtext(RN_X+t0-strlen(stmp)*(CWID/2),RN_Y,stmp,CPI,0);
00215                      lw = t0;
00216               }
00217        }
00218                                           /* frame */
00219        if (gparam[FTHICK].flags & DEFINED)
00220               lw = varvalue(gparam[FTHICK].name) + 0.5;
00221        else
00222               lw = DEFFTHICK;
00223        if (lw-- > 0) {
00224               drawcircle(PL_X,PL_Y,PL_R,0,lw,0);
00225               switch (tstyle) {
00226               case 1:              /* outside */
00227                      t0 = 0; t1 = TLEN; break;
00228               case 2:              /* inside */
00229                      t0 = TLEN; t1 = 0; break;
00230               case 3:              /* accross */
00231                      t0 = TLEN/2; t1 = TLEN/2; break;
00232               default:      /* none */
00233                      t0 = t1 = 0; break;
00234               }
00235               if (t0 + t1) {
00236                      for (d = 0.0; d < 2*PI-FTINY;
00237                                    d += xbounds.step*(2*PI)/period) {
00238                             mline((int)(PL_X+(PL_R-t0)*cos(d)+.5),
00239                                    (int)(PL_Y+(PL_R-t0)*sin(d)+.5),
00240                                    0, lw, 0);
00241                             mdraw((int)(PL_X+(PL_R+t1)*cos(d)+.5),
00242                                    (int)(PL_Y+(PL_R+t1)*sin(d)+.5));
00243                      }
00244               }
00245        }
00246                                           /* origin */
00247        if (gparam[OTHICK].flags & DEFINED)
00248               lw = varvalue(gparam[OTHICK].name) + 0.5;
00249        else
00250               lw = DEFOTHICK;
00251        if (lw-- > 0) {
00252               mline(PL_X-PL_R,PL_Y,0,lw,0);
00253               mdraw(PL_X+PL_R,PL_Y);
00254               mline(PL_X,PL_Y-PL_R,0,lw,0);
00255               mdraw(PL_X,PL_Y+PL_R);
00256               if (tstyle > 0)
00257                      for (d = ybeg; d <= ybounds.max+FTINY;
00258                                    d += ybounds.step) {
00259                             t0 = rconv(d);
00260                             mline(PL_X+t0,PL_Y-TLEN/2,0,lw,0);
00261                             mdraw(PL_X+t0,PL_Y+TLEN/2);
00262                             mline(PL_X-TLEN/2,PL_Y+t0,0,lw,0);
00263                             mdraw(PL_X+TLEN/2,PL_Y+t0);
00264                             mline(PL_X-t0,PL_Y-TLEN/2,0,lw,0);
00265                             mdraw(PL_X-t0,PL_Y+TLEN/2);
00266                             mline(PL_X-TLEN/2,PL_Y-t0,0,lw,0);
00267                             mdraw(PL_X+TLEN/2,PL_Y-t0);
00268                      }
00269        }
00270                                           /* grid */
00271        if (gparam[GRID].flags & DEFINED)
00272               lw = varvalue(gparam[GRID].name);
00273        else
00274               lw = DEFGRID;
00275        if (lw-- > 0) {
00276               for (d = 0.0; d < PI-FTINY; d += xbounds.step*(2*PI)/period) {
00277                      mline((int)(PL_X+PL_R*cos(d)+.5),
00278                             (int)(PL_Y+PL_R*sin(d)+.5),2,0,0);
00279                      mdraw((int)(PL_X-PL_R*cos(d)+.5),
00280                             (int)(PL_Y-PL_R*sin(d)+.5));
00281               }
00282               for (d = ybeg; d <= ybounds.max + FTINY; d += ybounds.step)
00283                      drawcircle(PL_X,PL_Y,rconv(d),2,0,0);
00284        }
00285 }
00286 
00287 void
00288 cartaxis(void)                            /* print Cartesian coordinate axis */
00289 {
00290        int  lw, t0, t1, tstyle;
00291        double  d, xbeg, ybeg;
00292        char  stmp[64], *fmt, *goodformat();
00293        register int  i;
00294                                           /* get tick style */
00295        if (gparam[TSTYLE].flags & DEFINED)
00296               tstyle = varvalue(gparam[TSTYLE].name) + 0.5;
00297        else
00298               tstyle = DEFTSTYLE;
00299                                           /* start of numbering */
00300        xbeg = ceil(xbounds.min/xbounds.step)*xbounds.step;
00301        ybeg = ceil(ybounds.min/ybounds.step)*ybounds.step;
00302        
00303                                           /* x numbering */
00304        fmt = goodformat(xbounds.step);
00305        lw = 2*AX_L-AX_R;
00306        for (d = xbeg;
00307                      d <= xbounds.max + FTINY;
00308                      d += xbounds.step)
00309               if ((i = xconv(d)) >= lw+XN_S || i <= lw-XN_S) {
00310                      sprintf(stmp, fmt, d);
00311                      mtext(i-strlen(stmp)*(CWID/2)+XN_X,XN_Y,stmp,CPI,0);
00312                      lw = i;
00313               }
00314                                           /* y numbering */
00315        fmt = goodformat(ybounds.step);
00316        lw = 2*AX_D-AX_U;
00317        for (d = ybeg;
00318                      d <= ybounds.max + FTINY;
00319                      d += ybounds.step)
00320               if ((i = yconv(d)) >= lw+YN_S || i <= lw-YN_S) {
00321                      sprintf(stmp, fmt, d);
00322                      mtext(YN_X-strlen(stmp)*CWID,i+YN_Y,stmp,CPI,0);
00323                      lw = i;
00324               }
00325                                           /* frame */
00326        if (gparam[FTHICK].flags & DEFINED)
00327               lw = varvalue(gparam[FTHICK].name) + 0.5;
00328        else
00329               lw = DEFFTHICK;
00330        if (lw-- > 0) {
00331               mline(AX_L,AX_D,0,lw,0);
00332               mdraw(AX_R,AX_D);
00333               mdraw(AX_R,AX_U);
00334               mdraw(AX_L,AX_U);
00335               mdraw(AX_L,AX_D);
00336               switch (tstyle) {
00337               case 1:              /* outside */
00338                      t0 = 0; t1 = TLEN; break;
00339               case 2:              /* inside */
00340                      t0 = TLEN; t1 = 0; break;
00341               case 3:              /* accross */
00342                      t0 = TLEN/2; t1 = TLEN/2; break;
00343               default:      /* none */
00344                      t0 = t1 = 0; break;
00345               }
00346               if (t0 + t1) {
00347                      for (d = xbeg;
00348                                    d <= xbounds.max + FTINY;
00349                                    d += xbounds.step) {
00350                             i = xconv(d);
00351                             mline(i,AX_D+t0,0,lw,0);
00352                             mdraw(i,AX_D-t1);
00353                             mline(i,AX_U-t0,0,lw,0);
00354                             mdraw(i,AX_U+t1);
00355                      }
00356                      for (d = ybeg;
00357                                    d <= ybounds.max + FTINY;
00358                                    d += ybounds.step) {
00359                             i = yconv(d);
00360                             mline(AX_L+t0,i,0,lw,0);
00361                             mdraw(AX_L-t1,i);
00362                             mline(AX_R-t0,i,0,lw,0);
00363                             mdraw(AX_R+t1,i);
00364                      }
00365               }
00366        }
00367                                           /* origin */
00368        if (gparam[OTHICK].flags & DEFINED)
00369               lw = varvalue(gparam[OTHICK].name) + 0.5;
00370        else
00371               lw = DEFOTHICK;
00372        if (lw-- > 0) {
00373               i = yconv(0.0);
00374               if (i >= AX_D && i <= AX_U) {
00375                      mline(AX_L,i,0,lw,0);
00376                      mdraw(AX_R,i);
00377                      if (tstyle > 0)
00378                             for (d = xbeg; d <= xbounds.max+FTINY;
00379                                           d += xbounds.step) {
00380                                    mline(xconv(d),i+TLEN/2,0,lw,0);
00381                                    mdraw(xconv(d),i-TLEN/2);
00382                             }
00383               }
00384               i = xconv(0.0);
00385               if (i >= AX_L && i <= AX_R) {
00386                      mline(i,AX_D,0,lw,0);
00387                      mdraw(i,AX_U);
00388                      if (tstyle > 0)
00389                             for (d = ybeg; d <= ybounds.max+FTINY;
00390                                           d += ybounds.step) {
00391                                    mline(i+TLEN/2,yconv(d),0,lw,0);
00392                                    mdraw(i-TLEN/2,yconv(d));
00393                             }
00394               }
00395        }
00396                                           /* grid */
00397        if (gparam[GRID].flags & DEFINED)
00398               lw = varvalue(gparam[GRID].name);
00399        else
00400               lw = DEFGRID;
00401        if (lw-- > 0) {
00402               for (d = xbeg;
00403                             d <= xbounds.max + FTINY;
00404                             d += xbounds.step) {
00405                      i = xconv(d);
00406                      mline(i,AX_D,2,0,0);
00407                      mdraw(i,AX_U);
00408               }
00409               for (d = ybeg;
00410                             d <= ybounds.max + FTINY;
00411                             d += ybounds.step) {
00412                      i = yconv(d);
00413                      mline(AX_L,i,2,0,0);
00414                      mdraw(AX_R,i);
00415               }
00416        }
00417 }
00418 
00419 void
00420 plotcurves(void)                          /* plot the curves */
00421 {
00422        int  i, j, k;
00423 
00424        for (i = 0; i < MAXCUR; i++) {
00425               nplottable = nplotted = 0;
00426               lastx = FHUGE;
00427               if (mgcurve(i, nextpoint) > 0 &&
00428                             cparam[i][CLABEL].flags & DEFINED) {
00429                      j = (LE_U-LE_D)/MAXCUR;
00430                      k = LE_U - i*j;
00431                      mtext(LE_L+(LE_R-LE_L)/8,k+j/3,
00432                                    cparam[i][CLABEL].v.s,CPI,0);
00433                      cmsymbol(i,LE_L,k);
00434                      if (cmline(i,LE_L,k) == 0)
00435                          mdraw(LE_R-(LE_R-LE_L)/4,k);
00436               }
00437        }
00438 }
00439 
00440 void
00441 nextpoint(                  /* plot the next point for c */
00442        register int  c,
00443        double  x,
00444        double  y
00445 )
00446 {
00447        if (inbounds(x, y)) {
00448 
00449               if (!(cparam[c][CNPOINTS].flags & DEFINED) ||
00450                             nplotted * npltbl[c] <= nplottable *
00451                             (int)varvalue(cparam[c][CNPOINTS].name) ) {
00452                      csymbol(c, x, y);
00453                      nplotted++;
00454               }
00455               nplottable++;
00456               if (lastx != FHUGE)
00457                      climline(c, x, y, lastx, lasty);
00458 
00459        } else if (inbounds(lastx, lasty)) {
00460 
00461               climline(c, lastx, lasty, x, y);
00462 
00463        }
00464        lastx = x;
00465        lasty = y;
00466 }
00467 
00468 
00469 void
00470 stretchbounds(                     /* stretch our boundaries */
00471        int  c,
00472        double  x,
00473        double  y
00474 )
00475 {
00476        if (gparam[XMIN].flags & DEFINED &&
00477                      x < xbounds.min)
00478               return;
00479        if (gparam[XMAX].flags & DEFINED &&
00480                      x > xbounds.max)
00481               return;
00482        if (gparam[YMIN].flags & DEFINED &&
00483                      y < ybounds.min)
00484               return;
00485        if (gparam[YMAX].flags & DEFINED &&
00486                      y > ybounds.max)
00487               return;
00488 
00489        if (x < xbounds.min)
00490               xbounds.min = x;
00491        if (x > xbounds.max)
00492               xbounds.max = x;
00493        if (y < ybounds.min)
00494               ybounds.min = y;
00495        if (y > ybounds.max)
00496               ybounds.max = y;
00497               
00498        npltbl[c]++;
00499 }
00500 
00501 
00502 #define  exp10(x)    exp((x)*2.3025850929940456)
00503 
00504 double
00505 goodstep(            /* determine a good step for the interval */
00506        double  interval
00507 )
00508 {
00509        static int  steps[] = {50, 20, 10, 5, 2, 1};
00510        double  fact, exp(), log10(), floor();
00511        int  i;
00512 
00513        if (interval <= FTINY)
00514               return(1.0);
00515        fact = exp10(floor(log10(interval)))/10;
00516        interval /= fact * MINDIVS;
00517        for (i = 0; interval < steps[i]; i++)
00518               ;
00519        return(steps[i] * fact);
00520 }
00521 
00522 #undef  exp10
00523 
00524 
00525 int
00526 xconv(               /* convert x to meta coords */
00527        double  x
00528 )
00529 {
00530        if (gparam[XMAP].flags & DEFINED)
00531               x = funvalue(gparam[XMAP].name, 1, &x);
00532        x = (x - axbegin)/axsize;
00533        return( AX_L + (int)(x*(AX_R-AX_L)) );
00534 }
00535 
00536 
00537 int
00538 yconv(               /* convert y to meta coords */
00539        double  y
00540 )
00541 {
00542        if (gparam[YMAP].flags & DEFINED)
00543               y = funvalue(gparam[YMAP].name, 1, &y);
00544        y = (y - aybegin)/aysize;
00545        return( AX_D + (int)(y*(AX_U-AX_D)) );
00546 }
00547 
00548 
00549 void
00550 pconv(        /* convert theta and radius to meta coords */
00551        int  *xp,
00552        int  *yp,
00553        double  t,
00554        double  r
00555 )
00556 {
00557        t *= (2.*PI)/period;
00558        r = rconv(r);
00559        *xp = r*cos(t) + (PL_X+.5);
00560        *yp = r*sin(t) + (PL_Y+.5);
00561 }
00562 
00563 
00564 int
00565 rconv(               /* convert radius to meta coords */
00566        double  r
00567 )
00568 {
00569        if (gparam[YMAP].flags & DEFINED)
00570               r = funvalue(gparam[YMAP].name, 1, &r);
00571 
00572        return((r - aybegin)*PL_R/aysize + .5);
00573 }
00574        
00575 
00576 void
00577 boxstring(    /* put string in box */
00578        int  xmin,
00579        int ymin,
00580        int xmax,
00581        int ymax,
00582        char  *s,
00583        int  d,
00584        int width,
00585        int color
00586 )
00587 {
00588        register long  size;
00589 
00590        if (d == 'u' || d == 'd') {        /* up or down */
00591               size = strlen(s)*(xmax-xmin)/ASPECT;
00592               size -= ymax-ymin;
00593               size /= 2;
00594               if (size < 0) {                           /* center */
00595                      ymin -= size;
00596                      ymax += size;
00597               }
00598        } else {                           /* left or right */
00599               size = strlen(s)*(ymax-ymin)/ASPECT;
00600               size -= xmax-xmin;
00601               size /= 2;
00602               if (size < 0) {                           /* center */
00603                      xmin -= size;
00604                      xmax += size;
00605               }
00606        }
00607        mvstr(xmin, ymin, xmax, ymax, s, d, width, color);      /* print */
00608 }
00609 
00610 
00611 char *
00612 goodformat(                 /* return a suitable format string for d */
00613        double  d
00614 )
00615 {
00616        static char  *f[5] = {"%.0f", "%.1f", "%.2f", "%.3f", "%.4f"};
00617        double  floor();
00618        register int  i;
00619 
00620        if (d < 0.0)
00621               d = -d;
00622        if (d > 1e-4 && d < 1e6)
00623               for (i = 0; i < 5; i++) {
00624                      if (d - floor(d+FTINY) <= FTINY)
00625                             return(f[i]);
00626                      d *= 10.0;
00627               }
00628        return("%.1e");
00629 }
00630 
00631 
00632 void
00633 drawcircle(   /* draw a circle */
00634        int  x,
00635        int y,
00636        int r,
00637        int  typ,
00638        int wid,
00639        int col
00640 )
00641 {
00642        double  d;
00643 
00644        if (r <= 0)
00645               return;
00646        mline(x+r, y, typ, wid, col);
00647        for (d = 2*PI*PL_F; d <= 2*PI+FTINY; d += 2*PI*PL_F)
00648               mdraw((int)(x+r*cos(d)+.5), (int)(y+r*sin(d)+.5));
00649 }
00650 
00651 
00652 void
00653 climline(     /* print line from/to out of bounds */
00654        int  c,
00655        double  x,
00656        double y,
00657        double xout,
00658        double yout
00659 )
00660 {
00661        for ( ; ; )
00662               if (xout < xbounds.min) {
00663                      yout = y + (yout - y)*(xbounds.min - x)/(xout - x);
00664                      xout = xbounds.min;
00665               } else if (yout < ybounds.min) {
00666                      xout = x + (xout - x)*(ybounds.min - y)/(yout - y);
00667                      yout = ybounds.min;
00668               } else if (xout > xbounds.max) {
00669                      yout = y + (yout - y)*(xbounds.max - x)/(xout - x);
00670                      xout = xbounds.max;
00671               } else if (yout > ybounds.max) {
00672                      xout = x + (xout - x)*(ybounds.max - y)/(yout - y);
00673                      yout = ybounds.max;
00674               } else {
00675                      cline(c, x, y, xout, yout);
00676                      break;
00677               }        
00678 }
00679 
00680 
00681 void
00682 cline(        /* print a curve line */
00683        int  c,
00684        double  u1,
00685        double v1,
00686        double u2,
00687        double v2
00688 )
00689 {
00690        int  x, y;
00691        double  ustep, vstep;
00692        
00693        if (period > FTINY) {              /* polar */
00694               if (u1 > u2) {
00695                      ustep = u1; u1 = u2; u2 = ustep;
00696                      vstep = v1; v1 = v2; v2 = vstep;
00697               }
00698               pconv(&x, &y, u1, v1);
00699               if (cmline(c, x, y) < 0)
00700                      return;
00701               ustep = period*PL_F;
00702               if (u2-u1 > ustep) {
00703                      vstep = ustep*(v2-v1)/(u2-u1);
00704                      while ((u1 += ustep) < u2) {
00705                             v1 += vstep;
00706                             pconv(&x, &y, u1, v1);
00707                             mdraw(x, y);
00708                      }
00709               }
00710               pconv(&x, &y, u2, v2);
00711               mdraw(x, y);
00712        } else if (cmline(c, xconv(u1), yconv(v1)) == 0)
00713               mdraw(xconv(u2), yconv(v2));
00714 }
00715 
00716 
00717 int
00718 cmline(                     /* start curve line in meta coords */
00719        int  c,
00720        int  x,
00721        int y
00722 )
00723 {
00724        int  lw, lt, col;
00725        register VARIABLE  *cv;
00726 
00727        cv = cparam[c];
00728        if (cv[CLINTYPE].flags & DEFINED)
00729               lt = varvalue(cv[CLINTYPE].name);
00730        else
00731               lt = DEFLINTYPE;
00732        if (lt-- <= 0)
00733               return(-1);
00734        if (cv[CTHICK].flags & DEFINED)
00735               lw = varvalue(cv[CTHICK].name);
00736        else
00737               lw = DEFTHICK;
00738        if (lw-- <= 0)
00739               return(-1);
00740        if (cv[CCOLOR].flags & DEFINED)
00741               col = varvalue(cv[CCOLOR].name);
00742        else
00743               col = DEFCOLOR;
00744        if (col-- <= 0)
00745               return(-1);
00746        mline(x, y, lt, lw, col);
00747        return(0);
00748 }
00749 
00750 
00751 void
00752 csymbol(             /* plot curve symbol */
00753        int  c,
00754        double  u,
00755        double v
00756 )
00757 {
00758        int  x, y;
00759        
00760        if (period > FTINY) {
00761               pconv(&x, &y, u, v);
00762               cmsymbol(c, x, y);
00763        } else
00764               cmsymbol(c, xconv(u), yconv(v));
00765 }
00766 
00767 
00768 void
00769 cmsymbol(            /* print curve symbol in meta coords */
00770        int  c,
00771        int  x,
00772        int y
00773 )
00774 {
00775        int  col, ss;
00776        register VARIABLE  *cv;
00777 
00778        cv = cparam[c];
00779        if (!(cv[CSYMTYPE].flags & DEFINED))
00780               return;
00781        if (cv[CSYMSIZE].flags & DEFINED)
00782               ss = varvalue(cv[CSYMSIZE].name);
00783        else
00784               ss = DEFSYMSIZE;
00785        if (ss <= 0)
00786               return;
00787        if (cv[CCOLOR].flags & DEFINED)
00788               col = varvalue(cv[CCOLOR].name);
00789        else
00790               col = DEFCOLOR;
00791        if (col-- <= 0)
00792               return;
00793        msegment(x-ss,y-ss,x+ss,y+ss,
00794                      cv[CSYMTYPE].v.s,'r',0,col);
00795 }
00796 
00797 
00798 int
00799 inbounds(                   /* determine if x and y are within gbounds */
00800        double  x,
00801        double y
00802 )
00803 {
00804        if (x < xbounds.min || x > xbounds.max)
00805               return(0);
00806        if (y < ybounds.min || y > ybounds.max)
00807               return(0);
00808        return(1);
00809 }