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