Back to index

plt-scheme  4.2.1
plbox.c
Go to the documentation of this file.
00001 /* $Id: plbox.c,v 1.2 2005/03/17 21:39:21 eli Exp $
00002 
00003        Routines for drawing axes & box around the current viewport.
00004 */
00005 
00006 #include "plplotP.h"
00007 
00008 static PLFLT xlog[8] =
00009 {
00010     0.301030, 0.477121, 0.602060, 0.698970,
00011     0.778151, 0.845098, 0.903090, 0.954243
00012 };
00013 
00014 /* Static function prototypes */
00015 
00016 static void
00017 plxybx(const char *opt, const char *label, PLFLT wx1, PLFLT wy1,
00018        PLFLT wx2, PLFLT wy2, PLFLT vmin, PLFLT vmax,
00019        PLFLT tick, PLINT nsub, PLINT nolast, PLINT *digits);
00020 
00021 static void
00022 plzbx(const char *opt, const char *label, PLINT right, PLFLT dx, PLFLT dy,
00023       PLFLT wx, PLFLT wy1, PLFLT wy2, PLFLT vmin, PLFLT vmax,
00024       PLFLT tick, PLINT nsub, PLINT *digits);
00025 
00026 static void
00027 plxytx(PLFLT wx1, PLFLT wy1, PLFLT wx2, PLFLT wy2,
00028        PLFLT disp, PLFLT pos, PLFLT just, const char *text);
00029 
00030 static void
00031 plztx(const char *opt, PLFLT dx, PLFLT dy, PLFLT wx, PLFLT wy1,
00032       PLFLT wy2, PLFLT disp, PLFLT pos, PLFLT just, const char *text);
00033 
00034 static void
00035 plform(PLFLT value, PLINT scale, PLINT prec, char *result, PLINT ll, PLINT lf);
00036 
00037 static void
00038 grid_box(const char *xopt, PLFLT xtick1, PLINT nxsub1,
00039         const char *yopt, PLFLT ytick1, PLINT nysub1);
00040 
00041 static void
00042 label_box(const char *xopt, PLFLT xtick1, const char *yopt, PLFLT ytick1);
00043 
00044 /*--------------------------------------------------------------------------*\
00045  * void plbox()
00046  *
00047  * This draws a box around the current viewport, complete with axes, ticks,
00048  * numeric labels, and grids, according to input specification.  Just a
00049  * front-end to plaxes(), which allows arbitrary placement of coordinate
00050  * axes when plotted (here the origin is at 0,0).  See the documentation for
00051  * plaxes() for more info.
00052 \*--------------------------------------------------------------------------*/
00053 
00054 void
00055 c_plbox(const char *xopt, PLFLT xtick, PLINT nxsub,
00056        const char *yopt, PLFLT ytick, PLINT nysub)
00057 {
00058     c_plaxes(0.0, 0.0, xopt, xtick, nxsub, yopt, ytick, nysub);
00059 }
00060 
00061 /*--------------------------------------------------------------------------*\
00062  * void plaxes()
00063  *
00064  * This draws a box around the current viewport, complete with axes,
00065  * ticks, numeric labels, and grids, according to input specification.
00066  *
00067  * x0 and y0 specify the origin of the axes.
00068  *
00069  * xopt and yopt are character strings which define the box as follows:
00070  *
00071  * a: Draw axis (X is horizontal line Y=0, Y is vertical line X=0)
00072  * b: Draw bottom (X) or left (Y) edge of frame
00073  * c: Draw top (X) or right (Y) edge of frame
00074  * f: Always use fixed point numeric labels
00075  * g: Draws a grid at the major tick interval
00076  * h: Draws a grid at the minor tick interval
00077  * i: Inverts tick marks
00078  * l: Logarithmic axes, major ticks at decades, minor ticks at units
00079  * n: Write numeric label at conventional location
00080  * m: Write numeric label at unconventional location
00081  * t: Draw major tick marks
00082  * s: Draw minor tick marks
00083  * v: (for Y only) Label vertically
00084  *
00085  * xtick, ytick are the major tick intervals required, zero for
00086  * automatic selection
00087  *
00088  * nxsub, nysub are the number of subtick intervals in a major tick
00089  * interval
00090 \*--------------------------------------------------------------------------*/
00091 
00092 void
00093 c_plaxes(PLFLT x0, PLFLT y0,
00094         const char *xopt, PLFLT xtick, PLINT nxsub,
00095         const char *yopt, PLFLT ytick, PLINT nysub)
00096 {
00097     PLINT lax, lbx, lcx, lgx, lix, llx, lsx, ltx;
00098     PLINT lay, lby, lcy, lgy, liy, lly, lsy, lty;
00099     PLINT xmajor, xminor, ymajor, yminor;
00100     PLINT i, i1x, i2x, i3x, i4x, i1y, i2y, i3y, i4y;
00101     PLINT nxsub1, nysub1;
00102     PLINT lxmin, lxmax, lymin, lymax;
00103     PLINT pxmin, pxmax, pymin, pymax;
00104     PLINT vppxmi, vppxma, vppymi, vppyma;
00105     PLFLT xtick1, ytick1, vpwxmi, vpwxma, vpwymi, vpwyma;
00106     PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax;
00107     PLFLT xp0, yp0, tn, tp, temp;
00108 
00109     if (plsc->level < 3) {
00110        plabort("plbox: Please set up window first");
00111        return;
00112     }
00113 
00114 /* Open the clip limits to the subpage limits */
00115 
00116     plP_gclp(&lxmin, &lxmax, &lymin, &lymax);
00117     plP_gphy(&pxmin, &pxmax, &pymin, &pymax);
00118     plP_sclp(pxmin, pxmax, pymin, pymax);
00119 
00120     vppxmi = plsc->vppxmi;
00121     vppxma = plsc->vppxma;
00122     vppymi = plsc->vppymi;
00123     vppyma = plsc->vppyma;
00124 
00125 /* Convert world coordinates to physical */
00126 
00127     xp0 = plP_wcpcx(x0);
00128     yp0 = plP_wcpcy(y0);
00129 
00130 /* Set plot options from input */
00131 
00132     lax = plP_stsearch(xopt, 'a');
00133     lbx = plP_stsearch(xopt, 'b');
00134     lcx = plP_stsearch(xopt, 'c');
00135     lgx = plP_stsearch(xopt, 'g');
00136     lix = plP_stsearch(xopt, 'i');
00137     llx = plP_stsearch(xopt, 'l');
00138     lsx = plP_stsearch(xopt, 's');
00139     ltx = plP_stsearch(xopt, 't');
00140 
00141     lay = plP_stsearch(yopt, 'a');
00142     lby = plP_stsearch(yopt, 'b');
00143     lcy = plP_stsearch(yopt, 'c');
00144     lgy = plP_stsearch(yopt, 'g');
00145     liy = plP_stsearch(yopt, 'i');
00146     lly = plP_stsearch(yopt, 'l');
00147     lsy = plP_stsearch(yopt, 's');
00148     lty = plP_stsearch(yopt, 't');
00149 
00150 /* Tick and subtick sizes in device coords */
00151 
00152     xmajor = MAX(ROUND(plsc->majht * plsc->ypmm), 1);
00153     ymajor = MAX(ROUND(plsc->majht * plsc->xpmm), 1);
00154     xminor = MAX(ROUND(plsc->minht * plsc->ypmm), 1);
00155     yminor = MAX(ROUND(plsc->minht * plsc->xpmm), 1);
00156 
00157     nxsub1 = nxsub;
00158     nysub1 = nysub;
00159     xtick1 = llx ? 1.0 : xtick;
00160     ytick1 = lly ? 1.0 : ytick;
00161 
00162     plgvpw(&vpwxmin, &vpwxmax, &vpwymin, &vpwymax);
00163 /* n.b. large change; vpwxmi always numerically less than vpwxma, and
00164  * similarly for vpwymi */
00165     vpwxmi = (vpwxmax > vpwxmin) ? vpwxmin : vpwxmax;
00166     vpwxma = (vpwxmax > vpwxmin) ? vpwxmax : vpwxmin;
00167     vpwymi = (vpwymax > vpwymin) ? vpwymin : vpwymax;
00168     vpwyma = (vpwymax > vpwymin) ? vpwymax : vpwymin;
00169 
00170     lax = lax && vpwymi < y0 && y0 < vpwyma ;
00171     lay = lay && vpwxmi < x0 && x0 < vpwxma ;
00172 
00173 /* Calculate tick spacing */
00174 
00175     if (ltx || lgx) 
00176        pldtik(vpwxmi, vpwxma, &xtick1, &nxsub1);
00177 
00178     if (lty || lgy) 
00179        pldtik(vpwymi, vpwyma, &ytick1, &nysub1);
00180 /* n.b. large change; xtick1, nxsub1, ytick1, nysub1 always positive. */
00181 
00182 /* Set up tick variables */
00183 
00184     if (lix) {
00185        i1x = xminor;
00186        i2x = 0;
00187        i3x = xmajor;
00188        i4x = 0;
00189     }
00190     else {
00191        i1x = 0;
00192        i2x = xminor;
00193        i3x = 0;
00194        i4x = xmajor;
00195     }
00196 
00197     if (liy) {
00198        i1y = yminor;
00199        i2y = 0;
00200        i3y = ymajor;
00201        i4y = 0;
00202     }
00203     else {
00204        i1y = 0;
00205        i2y = yminor;
00206        i3y = 0;
00207        i4y = ymajor;
00208     }
00209 
00210 /* Draw the bottom edge of the box */
00211 
00212     if (lbx) {
00213        plP_movphy(vppxmi, vppymi);
00214        if (ltx) {
00215            tp = xtick1 * floor(vpwxmi / xtick1);
00216            for (;;) {
00217               tn = tp + xtick1;
00218               if (lsx) {
00219                   if (llx) {
00220                      for (i = 0; i <= 7; i++) {
00221                          temp = tp + xlog[i];
00222                          if (BETW(temp, vpwxmi, vpwxma))
00223                             plxtik(plP_wcpcx(temp), vppymi, i1x, i2x);
00224                      }
00225                   }
00226                   else {
00227                      for (i = 1; i <= nxsub1 - 1; i++) {
00228                          temp = tp + i * xtick1 / nxsub1;
00229                          if (BETW(temp, vpwxmi, vpwxma))
00230                             plxtik(plP_wcpcx(temp), vppymi, i1x, i2x);
00231                      }
00232                   }
00233               }
00234               if (!BETW(tn, vpwxmi, vpwxma))
00235                   break;
00236               plxtik(plP_wcpcx(tn), vppymi, i3x, i4x);
00237               tp = tn;
00238            }
00239        }
00240        plP_draphy(vppxma, vppymi);
00241     }
00242 
00243 /* Draw right-hand edge of box */
00244 
00245     if (lcy) {
00246        plP_movphy(vppxma, vppymi);
00247        if (lty) {
00248            tp = ytick1 * floor(vpwymi / ytick1);
00249            for (;;) {
00250               tn = tp + ytick1;
00251               if (lsy) {
00252                   if (lly) {
00253                      for (i = 0; i <= 7; i++) {
00254                          temp = tp + xlog[i];
00255                          if (BETW(temp, vpwymi, vpwyma))
00256                             plytik(vppxma, plP_wcpcy(temp), i2y, i1y);
00257                      }
00258                   }
00259                   else {
00260                      for (i = 1; i <= nysub1 - 1; i++) {
00261                          temp = tp + i * ytick1 / nysub1;
00262                          if (BETW(temp, vpwymi, vpwyma))
00263                             plytik(vppxma, plP_wcpcy(temp), i2y, i1y);
00264                      }
00265                   }
00266               }
00267               if (!BETW(tn, vpwymi, vpwyma))
00268                   break;
00269               plytik(vppxma, plP_wcpcy(tn), i4y, i3y);
00270               tp = tn;
00271            }
00272        }
00273        plP_draphy(vppxma, vppyma);
00274     }
00275 
00276 /* Draw the top edge of the box */
00277 
00278     if (lcx) {
00279        plP_movphy(vppxma, vppyma);
00280        if (ltx) {
00281            tp = xtick1 * (floor(vpwxma / xtick1) + 1);
00282            for (;;) {
00283               tn = tp - xtick1;
00284               if (lsx) {
00285                   if (llx) {
00286                      for (i = 7; i >= 0; i--) {
00287                          temp = tn + xlog[i];
00288                          if (BETW(temp, vpwxmi, vpwxma))
00289                             plxtik(plP_wcpcx(temp), vppyma, i2x, i1x);
00290                      }
00291                   }
00292                   else {
00293                      for (i = nxsub1 - 1; i >= 1; i--) {
00294                          temp = tn + i * xtick1 / nxsub1;
00295                          if (BETW(temp, vpwxmi, vpwxma))
00296                             plxtik(plP_wcpcx(temp), vppyma, i2x, i1x);
00297                      }
00298                   }
00299               }
00300               if (!BETW(tn, vpwxmi, vpwxma))
00301                   break;
00302               plxtik(plP_wcpcx(tn), vppyma, i4x, i3x);
00303               tp = tn;
00304            }
00305        }
00306        plP_draphy(vppxmi, vppyma);
00307     }
00308 
00309 /* Draw left-hand edge of box */
00310 
00311     if (lby) {
00312        plP_movphy(vppxmi, vppyma);
00313        if (lty) {
00314            tp = ytick1 * (floor(vpwyma / ytick1) + 1);
00315            for (;;) {
00316               tn = tp - ytick1;
00317               if (lsy) {
00318                   if (lly) {
00319                      for (i = 7; i >= 0; i--) {
00320                          temp = tn + xlog[i];
00321                          if (BETW(temp, vpwymi, vpwyma))
00322                             plytik(vppxmi, plP_wcpcy(temp), i1y, i2y);
00323                      }
00324                   }
00325                   else {
00326                      for (i = nysub1 - 1; i >= 1; i--) {
00327                          temp = tn + i * ytick1 / nysub1;
00328                          if (BETW(temp, vpwymi, vpwyma))
00329                             plytik(vppxmi, plP_wcpcy(temp), i1y, i2y);
00330                      }
00331                   }
00332               }
00333               if (!BETW(tn, vpwymi, vpwyma))
00334                   break;
00335               plytik(vppxmi, plP_wcpcy(tn), i3y, i4y);
00336               tp = tn;
00337            }
00338        }
00339        plP_draphy(vppxmi, vppymi);
00340     }
00341 
00342 /* Draw the horizontal axis */
00343 
00344     if (lax) {
00345        plP_movphy(vppxmi, yp0);
00346        if (ltx) {
00347            tp = xtick1 * floor(vpwxmi / xtick1);
00348            for (;;) {
00349               tn = tp + xtick1;
00350               if (lsx) {
00351                   if (llx) {
00352                      for (i = 0; i <= 7; i++) {
00353                          temp = tp + xlog[i];
00354                          if (BETW(temp, vpwxmi, vpwxma))
00355                             plxtik(plP_wcpcx(temp), yp0, xminor, xminor);
00356                      }
00357                   }
00358                   else {
00359                      for (i = 1; i <= nxsub1 - 1; i++) {
00360                          temp = tp + i * xtick1 / nxsub1;
00361                          if (BETW(temp, vpwxmi, vpwxma))
00362                             plxtik(plP_wcpcx(temp), yp0, xminor, xminor);
00363                      }
00364                   }
00365               }
00366               if (!BETW(tn, vpwxmi, vpwxma))
00367                   break;
00368               plxtik(plP_wcpcx(tn), yp0, xmajor, xmajor);
00369               tp = tn;
00370            }
00371        }
00372        plP_draphy(vppxma, yp0);
00373     }
00374 
00375 /* Draw the vertical axis */
00376 
00377     if (lay) {
00378        plP_movphy(xp0, vppymi);
00379        if (lty) {
00380            tp = ytick1 * floor(vpwymi / ytick1);
00381            for (;;) {
00382               tn = tp + ytick1;
00383               if (lsy) {
00384                   if (lly) {
00385                      for (i = 0; i <= 7; i++) {
00386                          temp = tp + xlog[i];
00387                          if (BETW(temp, vpwymi, vpwyma))
00388                             plytik(xp0, plP_wcpcy(temp), yminor, yminor);
00389                      }
00390                   }
00391                   else {
00392                      for (i = 1; i <= nysub1 - 1; i++) {
00393                          temp = tp + i * ytick1 / nysub1;
00394                          if (BETW(temp, vpwymi, vpwyma))
00395                             plytik(xp0, plP_wcpcy(temp), yminor, yminor);
00396                      }
00397                   }
00398               }
00399               if (!BETW(tn, vpwymi, vpwyma))
00400                   break;
00401               plytik(xp0, plP_wcpcy(tn), ymajor, ymajor);
00402               tp = tn;
00403            }
00404        }
00405        plP_draphy(xp0, vppyma);
00406     }
00407 
00408 /* Draw grids */
00409 
00410     grid_box(xopt, xtick1, nxsub1, yopt, ytick1, nysub1);
00411 
00412 /* Write labels */
00413 
00414     label_box(xopt, xtick1, yopt, ytick1);
00415 
00416 /* Restore the clip limits to viewport edge */
00417 
00418     plP_sclp(lxmin, lxmax, lymin, lymax);
00419 }
00420 
00421 /*--------------------------------------------------------------------------*\
00422  * void plbox3()
00423  *
00424  * This is the 3-d analogue of plbox().
00425 \*--------------------------------------------------------------------------*/
00426 
00427 MZ_DLLEXPORT
00428 void
00429 c_plbox3(const char *xopt, const char *xlabel, PLFLT xtick, PLINT nsubx,
00430         const char *yopt, const char *ylabel, PLFLT ytick, PLINT nsuby,
00431         const char *zopt, const char *zlabel, PLFLT ztick, PLINT nsubz)
00432 {
00433     PLFLT dx, dy, tx, ty, ux, uy;
00434     PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
00435     PLFLT cxx, cxy, cyx, cyy, cyz;
00436     PLINT ln;
00437     PLINT *zbflg, *zbcol;
00438     PLFLT *zbtck;
00439     PLINT xdigmax, xdigits;
00440     PLINT ydigmax, ydigits;
00441     PLINT zdigmax, zdigits;
00442 
00443     if (plsc->level < 3) {
00444        plabort("plbox3: Please set up window first");
00445        return;
00446     }
00447 
00448     plP_gw3wc(&cxx, &cxy, &cyx, &cyy, &cyz);
00449     plP_gdom(&xmin, &xmax, &ymin, &ymax);
00450     plP_grange(&zscale, &zmin, &zmax);
00451 
00452     plgxax(&xdigmax, &xdigits);
00453     plgyax(&ydigmax, &ydigits);
00454     plgzax(&zdigmax, &zdigits);
00455 
00456     xdigits = xdigmax;
00457     ydigits = ydigmax;
00458     zdigits = zdigmax;
00459 
00460 /* We have to wait until after the plot is drawn to draw back */
00461 /* grid so store this stuff. */
00462 
00463     plP_gzback(&zbflg, &zbcol, &zbtck);
00464     *zbflg = plP_stsearch(zopt, 'd');
00465     if (*zbflg) {
00466        *zbtck = ztick;             /* save tick spacing */
00467        *zbcol = plsc->icol0;       /* and color */
00468     }
00469 
00470     if (cxx >= 0.0 && cxy <= 0.0) {
00471        ln = plP_stsearch(xopt, 'n');
00472        tx = plP_w3wcx(xmin, ymin, zmin);
00473        ty = plP_w3wcy(xmin, ymin, zmin);
00474        ux = plP_w3wcx(xmax, ymin, zmin);
00475        uy = plP_w3wcy(xmax, ymin, zmin);
00476        plxybx(xopt, xlabel, tx, ty, ux, uy,
00477               xmin, xmax, xtick, nsubx, 0, &xdigits);
00478 
00479        dx = ux - tx;
00480        dy = uy - ty;
00481        plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
00482              plP_w3wcy(xmax, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00483 
00484        tx = plP_w3wcx(xmin, ymax, zmin);
00485        ty = plP_w3wcy(xmin, ymax, zmin);
00486        ux = plP_w3wcx(xmin, ymin, zmin);
00487        uy = plP_w3wcy(xmin, ymin, zmin);
00488        plxybx(yopt, ylabel, tx, ty, ux, uy,
00489               ymax, ymin, ytick, nsuby, ln, &ydigits);
00490 
00491        dx = ux - tx;
00492        dy = uy - ty;
00493 /* restore zdigits to initial value for second call */
00494         zdigits = zdigmax;     
00495        plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
00496              plP_w3wcy(xmin, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00497     }
00498     else if (cxx <= 0.0 && cxy <= 0.0) {
00499        ln = plP_stsearch(yopt, 'n');
00500        tx = plP_w3wcx(xmin, ymax, zmin);
00501        ty = plP_w3wcy(xmin, ymax, zmin);
00502        ux = plP_w3wcx(xmin, ymin, zmin);
00503        uy = plP_w3wcy(xmin, ymin, zmin);
00504        plxybx(yopt, ylabel, tx, ty, ux, uy,
00505               ymax, ymin, ytick, nsuby, 0, &ydigits);
00506 
00507        dx = ux - tx;
00508        dy = uy - ty;
00509        plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
00510              plP_w3wcy(xmin, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00511 
00512        tx = plP_w3wcx(xmax, ymax, zmin);
00513        ty = plP_w3wcy(xmax, ymax, zmin);
00514        ux = plP_w3wcx(xmin, ymax, zmin);
00515        uy = plP_w3wcy(xmin, ymax, zmin);
00516        plxybx(xopt, xlabel, tx, ty, ux, uy,
00517               xmax, xmin, xtick, nsubx, ln, &xdigits);
00518 
00519        dx = ux - tx;
00520        dy = uy - ty;
00521 /* restore zdigits to initial value for second call */
00522         zdigits = zdigmax;     
00523        plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
00524              plP_w3wcy(xmax, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00525     }
00526     else if (cxx <= 0.0 && cxy >= 0.0) {
00527        ln = plP_stsearch(xopt, 'n');
00528        tx = plP_w3wcx(xmax, ymax, zmin);
00529        ty = plP_w3wcy(xmax, ymax, zmin);
00530        ux = plP_w3wcx(xmin, ymax, zmin);
00531        uy = plP_w3wcy(xmin, ymax, zmin);
00532        plxybx(xopt, xlabel, tx, ty, ux, uy,
00533               xmax, xmin, xtick, nsubx, 0, &xdigits);
00534 
00535        dx = ux - tx;
00536        dy = uy - ty;
00537        plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
00538              plP_w3wcy(xmin, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00539 
00540        tx = plP_w3wcx(xmax, ymin, zmin);
00541        ty = plP_w3wcy(xmax, ymin, zmin);
00542        ux = plP_w3wcx(xmax, ymax, zmin);
00543        uy = plP_w3wcy(xmax, ymax, zmin);
00544        plxybx(yopt, ylabel, tx, ty, ux, uy,
00545               ymin, ymax, ytick, nsuby, ln, &ydigits);
00546 
00547        dx = ux - tx;
00548        dy = uy - ty;
00549 /* restore zdigits to initial value for second call */
00550         zdigits = zdigmax;     
00551        plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
00552              plP_w3wcy(xmax, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00553     }
00554     else if (cxx >= 0.0 && cxy >= 0.0) {
00555        ln = plP_stsearch(yopt, 'n');
00556        tx = plP_w3wcx(xmax, ymin, zmin);
00557        ty = plP_w3wcy(xmax, ymin, zmin);
00558        ux = plP_w3wcx(xmax, ymax, zmin);
00559        uy = plP_w3wcy(xmax, ymax, zmin);
00560        plxybx(yopt, ylabel, tx, ty, ux, uy,
00561               ymin, ymax, ytick, nsuby, 0, &ydigits);
00562 
00563        dx = ux - tx;
00564        dy = uy - ty;
00565        plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
00566              plP_w3wcy(xmax, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00567 
00568        tx = plP_w3wcx(xmin, ymin, zmin);
00569        ty = plP_w3wcy(xmin, ymin, zmin);
00570        ux = plP_w3wcx(xmax, ymin, zmin);
00571        uy = plP_w3wcy(xmax, ymin, zmin);
00572        plxybx(xopt, xlabel, tx, ty, ux, uy,
00573               xmin, xmax, xtick, nsubx, ln, &xdigits);
00574 
00575        dx = ux - tx;
00576        dy = uy - ty;
00577 /* restore zdigits to initial value for second call */
00578         zdigits = zdigmax;     
00579        plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
00580              plP_w3wcy(xmin, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
00581     }
00582     plsxax(xdigmax, xdigits);
00583     plsyax(ydigmax, ydigits);
00584     plszax(zdigmax, zdigits);
00585 }
00586 
00587 /*--------------------------------------------------------------------------*\
00588  * Support routines for 3d box draw.
00589 \*--------------------------------------------------------------------------*/
00590 
00591 /*--------------------------------------------------------------------------*\
00592  * void plxybx()
00593  *
00594  * This draws a sloping line from (wx1,wy1) to (wx2,wy2) which represents an
00595  * axis of a 3-d graph with data values from "vmin" to "vmax". Depending on
00596  * "opt", vertical ticks and/or subticks are placed on the line at major tick
00597  * interval "tick" with "nsub" subticks between major ticks. If "tick" and/or
00598  * "nsub" is zero, automatic tick positions are computed
00599  *
00600  * b: Draw box boundary
00601  * f: Always use fixed point numeric labels
00602  * i: Inverts tick marks (i.e. drawn downwards)
00603  * l: Logarithmic axes, major ticks at decades, minor ticks at units
00604  * n: Write numeric label
00605  * t: Draw major tick marks
00606  * s: Draw minor tick marks
00607  * u: Write label on line
00608 \*--------------------------------------------------------------------------*/
00609 
00610 static void
00611 plxybx(const char *opt, const char *label, PLFLT wx1, PLFLT wy1,
00612        PLFLT wx2, PLFLT wy2, PLFLT vmin_in, PLFLT vmax_in,
00613        PLFLT tick, PLINT nsub, PLINT nolast, PLINT *digits)
00614 {
00615     static char string[40];
00616     PLINT lb, lf, li, ll, ln, ls, lt, lu;
00617     PLINT major, minor, mode, prec, scale;
00618     PLINT i, i1, i2, i3, i4;
00619     PLINT nsub1;
00620     PLFLT pos, tn, tp, temp, height, tick1, vmin, vmax;
00621 /* Note that 'tspace' is the minimim distance away (in fractional number
00622  * of ticks) from the boundary that an X or Y numerical label can be drawn. */
00623     PLFLT dwx, dwy, lambda, tcrit, tspace = 0.1;
00624    
00625     vmin = (vmax_in > vmin_in) ? vmin_in : vmax_in;
00626     vmax = (vmax_in > vmin_in) ? vmax_in : vmin_in;
00627 
00628     dwx = wx2 - wx1;
00629     dwy = wy2 - wy1;
00630 
00631 /* Tick and subtick sizes in device coords */
00632 
00633     major = MAX(ROUND(plsc->majht * plsc->ypmm), 1);
00634     minor = MAX(ROUND(plsc->minht * plsc->ypmm), 1);
00635 
00636     tick1 = tick;
00637     nsub1 = nsub;
00638 
00639     lb = plP_stsearch(opt, 'b');
00640     lf = plP_stsearch(opt, 'f');
00641     li = plP_stsearch(opt, 'i');
00642     ll = plP_stsearch(opt, 'l');
00643     ln = plP_stsearch(opt, 'n');
00644     ls = plP_stsearch(opt, 's');
00645     lt = plP_stsearch(opt, 't');
00646     lu = plP_stsearch(opt, 'u');
00647 
00648     if (lu)
00649        plxytx(wx1, wy1, wx2, wy2, 3.2, 0.5, 0.5, label);
00650     if (!lb)
00651        return;
00652 
00653     if (ll)
00654        tick1 = (vmax > vmin) ? 1.0 : -1.0 ;
00655     if (lt)
00656        pldtik(vmin, vmax, &tick1, &nsub1);
00657 
00658     if (li) {
00659        i1 = minor;
00660        i2 = 0;
00661        i3 = major;
00662        i4 = 0;
00663     }
00664     else {
00665        i1 = 0;
00666        i2 = minor;
00667        i3 = 0;
00668        i4 = major;
00669     }
00670 
00671 /* Draw the line */
00672 
00673     plP_movwor(wx1, wy1);
00674     if (lt) {
00675        tp = tick1 * floor(vmin / tick1);
00676        for (;;) {
00677            tn = tp + tick1;
00678            if (ls) {
00679               if (ll) {
00680                   for (i = 0; i <= 7; i++) {
00681                      temp = tp + xlog[i];
00682                      if (BETW(temp, vmin, vmax)) {
00683                          lambda = (vmax_in > vmin_in)? 
00684                             (temp - vmin) / (vmax - vmin):
00685                             (vmax - temp) / (vmax - vmin);
00686                          plxtik(plP_wcpcx((PLFLT) (wx1 + lambda * dwx)),
00687                                plP_wcpcy((PLFLT) (wy1 + lambda * dwy)),
00688                                i1, i2);
00689                      }
00690                   }
00691               }
00692               else {
00693                   for (i = 1; i <= nsub1 - 1; i++) {
00694                      temp = tp + i * (tn - tp) / nsub1;
00695                      if (BETW(temp, vmin, vmax)) {
00696                          lambda = (vmax_in > vmin_in)? 
00697                             (temp - vmin) / (vmax - vmin):
00698                             (vmax - temp) / (vmax - vmin);
00699                          plxtik(plP_wcpcx((PLFLT) (wx1 + lambda * dwx)),
00700                                plP_wcpcy((PLFLT) (wy1 + lambda * dwy)),
00701                                i1, i2);
00702                      }
00703                   }
00704               }
00705            }
00706            temp = tn;
00707            if (!BETW(temp, vmin, vmax))
00708               break;
00709 
00710            lambda = (vmax_in > vmin_in)? 
00711               (temp - vmin) / (vmax - vmin):
00712               (vmax - temp) / (vmax - vmin);
00713            plxtik(plP_wcpcx((PLFLT) (wx1 + lambda * dwx)),
00714                  plP_wcpcy((PLFLT) (wy1 + lambda * dwy)), i3, i4);
00715            tp = tn;
00716        }
00717     }
00718 
00719     plP_drawor(wx2, wy2);
00720 
00721 /* Label the line */
00722 
00723     if (ln && lt) {
00724        pldprec(vmin, vmax, tick1, lf, &mode, &prec, *digits, &scale);
00725        pos = 1.0;
00726        height = 3.2;
00727         tcrit = tspace*tick1;
00728        tp = tick1 * (1. + floor(vmin / tick1));
00729        for (tn = tp; BETW(tn, vmin, vmax); tn += tick1) {
00730           if(BETW(tn, vmin+tcrit, vmax-tcrit)) {
00731            plform(tn, scale, prec, string, ll, lf);
00732            pos = (vmax_in > vmin_in)? 
00733               (tn - vmin) / (vmax - vmin):
00734               (vmax - tn) / (vmax - vmin);
00735            plxytx(wx1, wy1, wx2, wy2, 1.5, pos, 0.5, string);
00736           }
00737        }
00738        *digits = 2;
00739        if (!ll && mode) {
00740            sprintf(string, "(x10#u%d#d)", (int) scale);
00741            plxytx(wx1, wy1, wx2, wy2, height, 1.0, 0.5, string);
00742        }
00743     }
00744 }
00745 
00746 /*--------------------------------------------------------------------------*\
00747  * void plxytx()
00748  *
00749  * Prints out text along a sloping axis joining world coordinates
00750  * (wx1,wy1) to (wx2,wy2). Parameters are as for plmtext.
00751 \*--------------------------------------------------------------------------*/
00752 
00753 static void
00754 plxytx(PLFLT wx1, PLFLT wy1, PLFLT wx2, PLFLT wy2,
00755        PLFLT disp, PLFLT pos, PLFLT just, const char *text)
00756 {
00757     PLINT x, y, refx, refy;
00758     PLFLT shift, cc, ss, wx, wy;
00759     PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, xform[4], diag;
00760     PLFLT dispx, dispy;
00761     PLFLT chrdef, chrht;
00762 
00763     cc = plsc->wmxscl * (wx2 - wx1);
00764     ss = plsc->wmyscl * (wy2 - wy1);
00765     diag = sqrt(cc * cc + ss * ss);
00766     cc /= diag;
00767     ss /= diag;
00768     wx = wx1 + pos * (wx2 - wx1);
00769     wy = wy1 + pos * (wy2 - wy1);
00770 
00771     xform[0] = cc;
00772     xform[1] = 0.0;
00773     xform[2] = ss;
00774     xform[3] = 1.0;
00775 
00776     xdv = plP_wcdcx(wx);
00777     ydv = plP_wcdcy(wy);
00778 
00779     dispx = 0.;
00780     dispy = -disp;
00781 
00782     plgchr(&chrdef, &chrht);
00783     shift = (just == 0.0) ? 0.0 : plstrl(text) * just;
00784 
00785     xmm = plP_dcmmx(xdv) + dispx * chrht;
00786     ymm = plP_dcmmy(ydv) + dispy * chrht;
00787     refxmm = xmm - shift * xform[0];
00788     refymm = ymm - shift * xform[2];
00789 
00790     x = plP_mmpcx(xmm);
00791     y = plP_mmpcy(ymm);
00792     refx = plP_mmpcx(refxmm);
00793     refy = plP_mmpcy(refymm);
00794 
00795     plP_text(0, just, xform, x, y, refx, refy, text);
00796 }
00797 
00798 /*--------------------------------------------------------------------------*\
00799  * void plzbx()
00800  *
00801  * This draws a vertical line from (wx,wy1) to (wx,wy2) which represents the
00802  * vertical axis of a 3-d graph with data values from "vmin" to "vmax".
00803  * Depending on "opt", ticks and/or subticks are placed on the line at major
00804  * tick interval "tick" with "nsub" subticks between major ticks. If "tick"
00805  * and/or "nsub" is zero, automatic tick positions are computed
00806  *
00807  * b: Draws left-hand axis
00808  * c: Draws right-hand axis
00809  * f: Always use fixed point numeric labels
00810  * i: Inverts tick marks (i.e. drawn to the left)
00811  * l: Logarithmic axes, major ticks at decades, minor ticks at units
00812  * m: Write numeric label on right axis
00813  * n: Write numeric label on left axis
00814  * s: Draw minor tick marks
00815  * t: Draw major tick marks
00816  * u: Writes left-hand label
00817  * v: Writes right-hand label
00818 \*--------------------------------------------------------------------------*/
00819 
00820 static void
00821 plzbx(const char *opt, const char *label, PLINT right, PLFLT dx, PLFLT dy,
00822       PLFLT wx, PLFLT wy1, PLFLT wy2, PLFLT vmin_in, PLFLT vmax_in,
00823       PLFLT tick, PLINT nsub, PLINT *digits)
00824 {
00825     static char string[40];
00826     PLINT lb, lc, lf, li, ll, lm, ln, ls, lt, lu, lv;
00827     PLINT i, mode, prec, scale;
00828     PLINT nsub1, lstring;
00829     PLFLT pos, tn, tp, temp, height, tick1;
00830     PLFLT dwy, lambda, diag, major, minor, xmajor, xminor;
00831     PLFLT ymajor, yminor, dxm, dym, vmin, vmax;
00832 
00833     vmin = (vmax_in > vmin_in) ? vmin_in : vmax_in;
00834     vmax = (vmax_in > vmin_in) ? vmax_in : vmin_in;
00835    
00836     dwy = wy2 - wy1;
00837 
00838 /* Tick and subtick sizes in device coords */
00839 
00840     major = plsc->majht;
00841     minor = plsc->minht;
00842 
00843     tick1 = tick;
00844     nsub1 = nsub;
00845 
00846     lb = plP_stsearch(opt, 'b');
00847     lc = plP_stsearch(opt, 'c');
00848     lf = plP_stsearch(opt, 'f');
00849     li = plP_stsearch(opt, 'i');
00850     ll = plP_stsearch(opt, 'l');
00851     lm = plP_stsearch(opt, 'm');
00852     ln = plP_stsearch(opt, 'n');
00853     ls = plP_stsearch(opt, 's');
00854     lt = plP_stsearch(opt, 't');
00855     lu = plP_stsearch(opt, 'u');
00856     lv = plP_stsearch(opt, 'v');
00857 
00858     if (lu && !right)
00859        plztx("h", dx, dy, wx, wy1, wy2, 5.0, 0.5, 0.5, label);
00860 
00861     if (lv && right)
00862        plztx("h", dx, dy, wx, wy1, wy2, -5.0, 0.5, 0.5, label);
00863     
00864     if (right && !lc)
00865        return;
00866 
00867     if (!right && !lb)
00868        return;
00869     
00870     if (ll)
00871        tick1 = 1.0;
00872 
00873     if (lt)
00874        pldtik(vmin, vmax, &tick1, &nsub1);
00875 
00876     if ((li && !right) || (!li && right)) {
00877        minor = -minor;
00878        major = -major;
00879     }
00880 
00881     dxm = dx * plsc->wmxscl;
00882     dym = dy * plsc->wmyscl;
00883     diag = sqrt(dxm * dxm + dym * dym);
00884 
00885     xminor = minor * dxm / diag;
00886     xmajor = major * dxm / diag;
00887     yminor = minor * dym / diag;
00888     ymajor = major * dym / diag;
00889 
00890 /* Draw the line */
00891 
00892     plP_movwor(wx, wy1);
00893     if (lt) {
00894        tp = tick1 * floor(vmin / tick1);
00895        for (;;) {
00896            tn = tp + tick1;
00897            if (ls) {
00898               if (ll) {
00899                   for (i = 0; i <= 7; i++) {
00900                      temp = tp + xlog[i];
00901                      if (BETW(temp, vmin, vmax)) {
00902                          lambda = (vmax_in > vmin_in)? 
00903                             (temp - vmin) / (vmax - vmin):
00904                             (vmax - temp) / (vmax - vmin);
00905                          plstik(plP_wcmmx(wx),
00906                                plP_wcmmy((PLFLT) (wy1 + lambda * dwy)),
00907                                xminor, yminor);
00908                      }
00909                   }
00910               }
00911               else {
00912                   for (i = 1; i <= nsub1 - 1; i++) {
00913                      temp = tp + i * tick1 / nsub1;
00914                      if (BETW(temp, vmin, vmax)) {
00915                          lambda = (vmax_in > vmin_in)? 
00916                             (temp - vmin) / (vmax - vmin):
00917                             (vmax - temp) / (vmax - vmin);
00918                          plstik(plP_wcmmx(wx),
00919                                plP_wcmmy((PLFLT) (wy1 + lambda * dwy)),
00920                                xminor, yminor);
00921                      }
00922                   }
00923               }
00924            }
00925            temp = tn;
00926            if (!BETW(temp, vmin, vmax))
00927               break;
00928            lambda = (vmax_in > vmin_in)? 
00929                (temp - vmin) / (vmax - vmin):
00930                (vmax - temp) / (vmax - vmin);
00931            plstik(plP_wcmmx(wx), plP_wcmmy((PLFLT) (wy1 + lambda * dwy)),
00932                  xmajor, ymajor);
00933            tp = tn;
00934        }
00935     }
00936 
00937     plP_drawor(wx, wy2);
00938 
00939 /* Label the line */
00940 
00941     if ((ln || lm) && lt) {
00942        pldprec(vmin, vmax, tick1, lf, &mode, &prec, *digits, &scale);
00943        *digits = 0;
00944        tp = tick1 * floor(vmin / tick1);
00945        for (tn = tp + tick1; BETW(tn, vmin, vmax); tn += tick1) {
00946            plform(tn, scale, prec, string, ll, lf);
00947            pos = (vmax_in > vmin_in)? 
00948                (tn - vmin) / (vmax - vmin):
00949                (vmax - tn) / (vmax - vmin);
00950            if (ln && !right)
00951               plztx("v", dx, dy, wx, wy1, wy2, 0.5, pos, 1.0, string);
00952 
00953            if (lm && right)
00954               plztx("v", dx, dy, wx, wy1, wy2, -0.5, pos, 0.0, string);
00955 
00956            lstring = strlen(string);
00957            *digits = MAX(*digits, lstring);
00958        }
00959        if (!ll && mode) {
00960            sprintf(string, "(x10#u%d#d)", (int) scale);
00961            pos = 1.15;
00962            height = 0.5;
00963            if (ln && !right) {
00964               plztx("v", dx, dy, wx, wy1, wy2, height, pos, 0.5, string);
00965            }
00966            if (lm && right) {
00967               plztx("v", dx, dy, wx, wy1, wy2,
00968                     (PLFLT) -height, pos, 0.5, string);
00969            }
00970        }
00971     }
00972 }
00973 
00974 /*--------------------------------------------------------------------------*\
00975  * void plztx()
00976  *
00977  * Prints out text along a vertical axis for a 3d plot joining
00978  * world coordinates (wx,wy1) to (wx,wy2).
00979 \*--------------------------------------------------------------------------*/
00980 
00981 static void
00982 plztx(const char *opt, PLFLT dx, PLFLT dy, PLFLT wx, PLFLT wy1,
00983       PLFLT wy2, PLFLT disp, PLFLT pos, PLFLT just, const char *text)
00984 {
00985     PLINT refx = 0, refy = 0, x = 0, y = 0, vert = 0;
00986     PLFLT shift, cc, ss, wy;
00987     PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, xform[4], diag;
00988     PLFLT dispx, dispy;
00989     PLFLT chrdef, chrht;
00990 
00991     cc = plsc->wmxscl * dx;
00992     ss = plsc->wmyscl * dy;
00993     diag = sqrt(cc * cc + ss * ss);
00994     cc /= diag;
00995     ss /= diag;
00996     wy = wy1 + pos * (wy2 - wy1);
00997 
00998     if (plP_stsearch(opt, 'v'))
00999        vert = 0;
01000     else if (plP_stsearch(opt, 'h'))
01001        vert = 1;
01002 
01003     if (vert) {
01004        xform[0] = 0.0;
01005        xform[1] = -cc;
01006        xform[2] = 1.0;
01007        xform[3] = -ss;
01008     } else {
01009        xform[0] = cc;
01010        xform[1] = 0.0;
01011        xform[2] = ss;
01012        xform[3] = 1.0;
01013     }
01014 
01015     xdv = plP_wcdcx(wx);
01016     ydv = plP_wcdcy(wy);
01017 
01018     dispx = -disp * cc;
01019     dispy = -disp * ss;
01020 
01021     plgchr(&chrdef, &chrht);
01022     shift = (just == 0.0) ? 0.0 : plstrl(text) * just;
01023 
01024     xmm = plP_dcmmx(xdv) + dispx * chrht;
01025     ymm = plP_dcmmy(ydv) + dispy * chrht;
01026     refxmm = xmm - shift * xform[0];
01027     refymm = ymm - shift * xform[2];
01028 
01029     x = plP_mmpcx(xmm);
01030     y = plP_mmpcy(ymm);
01031     refx = plP_mmpcx(refxmm);
01032     refy = plP_mmpcy(refymm);
01033 
01034     plP_text(0, just, xform, x, y, refx, refy, text);
01035 }
01036 
01037 /*--------------------------------------------------------------------------*\
01038  * void grid_box()
01039  *
01040  * Draws grids at tick locations (major and/or minor).
01041  *
01042  * Note that 'tspace' is the minimim distance away (in fractional number
01043  * of ticks or subticks) from the boundary a grid line can be drawn.  If
01044  * you are too close, it looks bad.
01045 \*--------------------------------------------------------------------------*/
01046 
01047 static void
01048 grid_box(const char *xopt, PLFLT xtick1, PLINT nxsub1,
01049         const char *yopt, PLFLT ytick1, PLINT nysub1)
01050 {
01051     PLINT lgx, lhx, llx;
01052     PLINT lgy, lhy, lly;
01053     PLFLT vpwxmi, vpwxma, vpwymi, vpwyma;
01054     PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax;
01055     PLFLT tn, temp, tcrit, tspace = 0.1;
01056     PLINT i;
01057 
01058 /* Set plot options from input */
01059 
01060     lgx = plP_stsearch(xopt, 'g');
01061     lhx = plP_stsearch(xopt, 'h');
01062     llx = plP_stsearch(xopt, 'l');
01063 
01064     lgy = plP_stsearch(yopt, 'g');
01065     lhy = plP_stsearch(yopt, 'h');
01066     lly = plP_stsearch(yopt, 'l');
01067 
01068     plgvpw(&vpwxmin, &vpwxmax, &vpwymin, &vpwymax);
01069 /* n.b. large change; vpwxmi always numerically less than vpwxma, and
01070  * similarly for vpwymi */
01071     vpwxmi = (vpwxmax > vpwxmin) ? vpwxmin : vpwxmax;
01072     vpwxma = (vpwxmax > vpwxmin) ? vpwxmax : vpwxmin;
01073     vpwymi = (vpwymax > vpwymin) ? vpwymin : vpwymax;
01074     vpwyma = (vpwymax > vpwymin) ? vpwymax : vpwymin;
01075 
01076 /* Draw grid in x direction. */
01077 
01078     if (lgx) {
01079        for (tn = xtick1 * floor(vpwxmi/xtick1);
01080             tn <= vpwxma; tn += xtick1) {
01081            if (lhx) {
01082               if (llx) {
01083                   PLFLT otemp = tn;
01084                   for (i = 0; i <= 7; i++) {
01085                      temp = tn + xlog[i];
01086                      tcrit = (temp - otemp)*tspace;
01087                      otemp = temp;
01088                      if (BETW(temp, vpwxmi+tcrit, vpwxma-tcrit))
01089                          pljoin(temp, vpwymi, temp, vpwyma);
01090                   }
01091               }
01092               else {
01093                   for (i = 1; i <= nxsub1 - 1; i++) {
01094                      temp = tn + i * xtick1 / nxsub1;
01095                      tcrit = xtick1 / nxsub1 * tspace;
01096                      if (BETW(temp, vpwxmi+tcrit, vpwxma-tcrit))
01097                          pljoin(temp, vpwymi, temp, vpwyma);
01098                   }
01099               }
01100            }
01101            tcrit = xtick1*tspace;
01102            if (BETW(tn, vpwxmi+tcrit, vpwxma-tcrit))
01103                pljoin(tn, vpwymi, tn, vpwyma);
01104        }
01105     }
01106 
01107 /* Draw grid in y direction */
01108 
01109     if (lgy) {
01110        tn = ytick1 * floor(vpwymi / ytick1 + tspace);
01111        for (tn = ytick1 * floor(vpwymi/ytick1);
01112             tn <= vpwyma; tn += ytick1) {
01113            if (lhy) {
01114               if (lly) {
01115                   PLFLT otemp = tn;
01116                   for (i = 0; i <= 7; i++) {
01117                      temp = tn + xlog[i];
01118                      tcrit = (temp - otemp)*tspace;
01119                      otemp = temp;
01120                      if (BETW(temp, vpwymi+tcrit, vpwyma-tcrit))
01121                          pljoin(vpwxmi, temp, vpwxma, temp);
01122                   }
01123               }
01124               else {
01125                   for (i = 1; i <= nysub1 - 1; i++) {
01126                      temp = tn + i * ytick1 / nysub1;
01127                      tcrit = ytick1 / nysub1 * tspace;
01128                      if (BETW(temp, vpwymi+tcrit, vpwyma-tcrit))
01129                          pljoin(vpwxmi, temp, vpwxma, temp);
01130                   }
01131               }
01132            }
01133            tcrit = ytick1*tspace;
01134            if (BETW(tn, vpwymi+tcrit, vpwyma-tcrit))
01135            pljoin(vpwxmi, tn, vpwxma, tn);
01136        }
01137     }
01138 }
01139 
01140 /*--------------------------------------------------------------------------*\
01141  * void label_box()
01142  *
01143  * Writes numeric labels on side(s) of box.
01144 \*--------------------------------------------------------------------------*/
01145 
01146 static void
01147 label_box(const char *xopt, PLFLT xtick1, const char *yopt, PLFLT ytick1)
01148 {
01149     static char string[40];
01150     PLINT lfx, lix, llx, lmx, lnx, ltx;
01151     PLINT lfy, liy, lly, lmy, lny, lty, lvy;
01152     PLFLT vpwxmi, vpwxma, vpwymi, vpwyma;
01153     PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax;
01154     PLFLT pos, tn, tp, offset, height;
01155 
01156 /* Set plot options from input */
01157 
01158     lfx = plP_stsearch(xopt, 'f');
01159     lix = plP_stsearch(xopt, 'i');
01160     llx = plP_stsearch(xopt, 'l');
01161     lmx = plP_stsearch(xopt, 'm');
01162     lnx = plP_stsearch(xopt, 'n');
01163     ltx = plP_stsearch(xopt, 't');
01164 
01165     lfy = plP_stsearch(yopt, 'f');
01166     liy = plP_stsearch(yopt, 'i');
01167     lly = plP_stsearch(yopt, 'l');
01168     lmy = plP_stsearch(yopt, 'm');
01169     lny = plP_stsearch(yopt, 'n');
01170     lty = plP_stsearch(yopt, 't');
01171     lvy = plP_stsearch(yopt, 'v');
01172 
01173     plgvpw(&vpwxmin, &vpwxmax, &vpwymin, &vpwymax);
01174 /* n.b. large change; vpwxmi always numerically less than vpwxma, and
01175  * similarly for vpwymi */
01176     vpwxmi = (vpwxmax > vpwxmin) ? vpwxmin : vpwxmax;
01177     vpwxma = (vpwxmax > vpwxmin) ? vpwxmax : vpwxmin;
01178     vpwymi = (vpwymax > vpwymin) ? vpwymin : vpwymax;
01179     vpwyma = (vpwymax > vpwymin) ? vpwymax : vpwymin;
01180 
01181 /* Write horizontal label(s) */
01182 
01183     if ((lmx || lnx) && ltx) {
01184        PLINT xmode, xprec, xdigmax, xdigits, xscale;
01185 
01186        plgxax(&xdigmax, &xdigits);
01187        pldprec(vpwxmi, vpwxma, xtick1, lfx, &xmode, &xprec, xdigmax, &xscale);
01188 
01189        tp = xtick1 * (1. + floor(vpwxmi / xtick1));
01190        for (tn = tp; BETW(tn, vpwxmi, vpwxma); tn += xtick1) {
01191            plform(tn, xscale, xprec, string, llx, lfx);
01192            height = lix ? 1.75 : 1.5;
01193            pos = (vpwxmax > vpwxmin)? 
01194                (tn - vpwxmi) / (vpwxma - vpwxmi):
01195                (vpwxma - tn) / (vpwxma - vpwxmi);
01196            if (lnx)
01197               plmtex("b", height, pos, 0.5, string);
01198            if (lmx)
01199               plmtex("t", height, pos, 0.5, string);
01200        }
01201        xdigits = 2;
01202        plsxax(xdigmax, xdigits);
01203 
01204     /* Write separate exponential label if mode = 1. */
01205 
01206        if (!llx && xmode) {
01207            pos = 1.0;
01208            height = 3.2;
01209            sprintf(string, "(x10#u%d#d)", (int) xscale);
01210            if (lnx)
01211               plmtex("b", height, pos, 0.5, string);
01212            if (lmx)
01213               plmtex("t", height, pos, 0.5, string);
01214        }
01215     }
01216 
01217 /* Write vertical label(s) */
01218 
01219     if ((lmy || lny) && lty) {
01220        PLINT ymode, yprec, ydigmax, ydigits, yscale;
01221 
01222        plgyax(&ydigmax, &ydigits);
01223        pldprec(vpwymi, vpwyma, ytick1, lfy, &ymode, &yprec, ydigmax, &yscale);
01224 
01225        ydigits = 0;
01226        tp = ytick1 * (1. + floor(vpwymi / ytick1));
01227        for (tn = tp; BETW(tn, vpwymi, vpwyma); tn += ytick1) {
01228            plform(tn, yscale, yprec, string, lly, lfy);
01229            pos = (vpwymax > vpwymin)? 
01230                (tn - vpwymi) / (vpwyma - vpwymi):
01231                (vpwyma - tn) / (vpwyma - vpwymi);
01232            if (lny) {
01233               if (lvy) {
01234                   height = liy ? 1.0 : 0.5;
01235                   plmtex("lv", height, pos, 1.0, string);
01236               } else {
01237                   height = liy ? 1.75 : 1.5;
01238                   plmtex("l", height, pos, 0.5, string);
01239               }
01240            }
01241            if (lmy) {
01242               if (lvy) {
01243                   height = liy ? 1.0 : 0.5;
01244                   plmtex("rv", height, pos, 0.0, string);
01245               } else {
01246                   height = liy ? 1.75 : 1.5;
01247                   plmtex("r", height, pos, 0.5, string);
01248               }
01249            }
01250            ydigits = MAX(ydigits, strlen(string));
01251        }
01252        if (!lvy)
01253            ydigits = 2;
01254 
01255        plsyax(ydigmax, ydigits);
01256 
01257     /* Write separate exponential label if mode = 1. */
01258 
01259        if (!lly && ymode) {
01260            sprintf(string, "(x10#u%d#d)", (int) yscale);
01261            offset = 0.02;
01262            height = 2.0;
01263            if (lny) {
01264               pos = 0.0 - offset;
01265               plmtex("t", height, pos, 1.0, string);
01266            }
01267            if (lmy) {
01268               pos = 1.0 + offset;
01269               plmtex("t", height, pos, 0.0, string);
01270            }
01271        }
01272     }
01273 }
01274 
01275 /*--------------------------------------------------------------------------*\
01276  * void plform()
01277  *
01278  * Formats a PLFLT value in one of the following formats.
01279  *
01280  * If ll (logarithmic), then:
01281  *
01282  *    -       If lf (fixed), then used fixed point notation, i.e. .1, 1, 10, etc,
01283  *     with unnecessary trailing .'s or 0's removed.
01284  *
01285  *    -       If !lf (default), then use exponential notation, i.e. 10^-1, etc.
01286  *
01287  * If !ll (linear), then:
01288  *
01289  *    - If scale == 0, use fixed point format with "prec" places after the
01290  *     decimal point.
01291  *
01292  *    -       If scale == 1, use scientific notation with one place before the
01293  *     decimal point and "prec" places after.  In this case, the value
01294  *     must be divided by 10^scale.
01295 \*--------------------------------------------------------------------------*/
01296 
01297 static void
01298 plform(PLFLT value, PLINT scale, PLINT prec, char *string, PLINT ll, PLINT lf)
01299 {
01300     if (ll) {
01301 
01302     /* Logarithmic */
01303 
01304        if (lf) {
01305 
01306        /* Fixed point, i.e. .1, 1, 10, etc */
01307 
01308            int exponent = ROUND(value);
01309 
01310            value = pow(10.0, exponent);
01311            if (exponent < 0) {
01312               char form[10];
01313               sprintf(form, "%%.%df", ABS(exponent));
01314               sprintf(string, form, value);
01315            }
01316            else {
01317               sprintf(string, "%d", (int) value);
01318            }
01319        }
01320        else {
01321 
01322        /* Exponential, i.e. 10^-1, 10^0, 10^1, etc */
01323 
01324            sprintf(string, "10#u%d", (int) ROUND(value));
01325        }
01326     }
01327     else {
01328 
01329     /* Linear */
01330 
01331        PLINT setpre, precis;
01332        char form[10], temp[30];
01333        double scale2;
01334 
01335        plP_gprec(&setpre, &precis);
01336 
01337        if (setpre)
01338            prec = precis;
01339 
01340        if (scale)
01341            value /= pow(10.,(double)scale);
01342 
01343     /* This is necessary to prevent labels like "-0.0" on some systems */
01344 
01345        scale2 = pow(10., prec);
01346        value = floor((value * scale2) + .5) / scale2;
01347 
01348        sprintf(form, "%%.%df", (int) prec);
01349        sprintf(temp, form, value);
01350        strcpy(string, temp);
01351     }
01352 }