1 /* $Id: plbox.c,v 1.3 2007/05/08 09:09:37 rice Exp $
2
3 Routines for drawing axes & box around the current viewport.
4
5 Copyright (C) 2004 Joao Cardoso
6 Copyright (C) 2004 Alan W. Irwin
7
8 This file is part of PLplot.
9
10 PLplot is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Library Public License as published
12 by the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 PLplot is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public License
21 along with PLplot; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "plplotP.h"
26
27 static PLFLT xlog[8] =
28 {
29 0.301030, 0.477121, 0.602060, 0.698970,
30 0.778151, 0.845098, 0.903090, 0.954243
31 };
32
33 /* Static function prototypes */
34
35 static void
36 plxybx(const char *opt, const char *label, PLFLT wx1, PLFLT wy1,
37 PLFLT wx2, PLFLT wy2, PLFLT vmin, PLFLT vmax,
38 PLFLT tick, PLINT nsub, PLINT nolast, PLINT *digits);
39
40 static void
41 plzbx(const char *opt, const char *label, PLINT right, PLFLT dx, PLFLT dy,
42 PLFLT wx, PLFLT wy1, PLFLT wy2, PLFLT vmin, PLFLT vmax,
43 PLFLT tick, PLINT nsub, PLINT *digits);
44
45 static void
46 plxytx(PLFLT wx1, PLFLT wy1, PLFLT wx2, PLFLT wy2,
47 PLFLT disp, PLFLT pos, PLFLT just, const char *text);
48
49 static void
50 plztx(const char *opt, PLFLT dx, PLFLT dy, PLFLT wx, PLFLT wy1,
51 PLFLT wy2, PLFLT disp, PLFLT pos, PLFLT just, const char *text);
52
53 static void
54 plform(PLFLT value, PLINT scale, PLINT prec, char *result, PLINT ll, PLINT lf);
55
56 static void
57 grid_box(const char *xopt, PLFLT xtick1, PLINT nxsub1,
58 const char *yopt, PLFLT ytick1, PLINT nysub1);
59
60 static void
61 label_box(const char *xopt, PLFLT xtick1, const char *yopt, PLFLT ytick1);
62
63 /*--------------------------------------------------------------------------*\
64 * void plbox()
65 *
66 * This draws a box around the current viewport, complete with axes, ticks,
67 * numeric labels, and grids, according to input specification. Just a
68 * front-end to plaxes(), which allows arbitrary placement of coordinate
69 * axes when plotted (here the origin is at 0,0). See the documentation for
70 * plaxes() for more info.
71 \*--------------------------------------------------------------------------*/
72
73 void
c_plbox(const char * xopt,PLFLT xtick,PLINT nxsub,const char * yopt,PLFLT ytick,PLINT nysub)74 c_plbox(const char *xopt, PLFLT xtick, PLINT nxsub,
75 const char *yopt, PLFLT ytick, PLINT nysub)
76 {
77 c_plaxes(0.0, 0.0, xopt, xtick, nxsub, yopt, ytick, nysub);
78 }
79
80 /*--------------------------------------------------------------------------*\
81 * void plaxes()
82 *
83 * This draws a box around the current viewport, complete with axes,
84 * ticks, numeric labels, and grids, according to input specification.
85 *
86 * xx0 and yy0 specify the origin of the axes.
87 *
88 * xopt and yopt are character strings which define the box as follows:
89 *
90 * a: Draw axis (X is horizontal line Y=0, Y is vertical line X=0)
91 * b: Draw bottom (X) or left (Y) edge of frame
92 * c: Draw top (X) or right (Y) edge of frame
93 * f: Always use fixed point numeric labels
94 * g: Draws a grid at the major tick interval
95 * h: Draws a grid at the minor tick interval
96 * i: Inverts tick marks
97 * l: Logarithmic axes, major ticks at decades, minor ticks at units
98 * n: Write numeric label at conventional location
99 * m: Write numeric label at unconventional location
100 * t: Draw major tick marks
101 * s: Draw minor tick marks
102 * v: (for Y only) Label vertically
103 *
104 * xtick, ytick are the major tick intervals required, zero for
105 * automatic selection
106 *
107 * nxsub, nysub are the number of subtick intervals in a major tick
108 * interval
109 \*--------------------------------------------------------------------------*/
110
111 void
c_plaxes(PLFLT xx0,PLFLT yy0,const char * xopt,PLFLT xtick,PLINT nxsub,const char * yopt,PLFLT ytick,PLINT nysub)112 c_plaxes(PLFLT xx0, PLFLT yy0,
113 const char *xopt, PLFLT xtick, PLINT nxsub,
114 const char *yopt, PLFLT ytick, PLINT nysub)
115 {
116 PLINT lax, lbx, lcx, lgx, lix, llx, lsx, ltx;
117 PLINT lay, lby, lcy, lgy, liy, lly, lsy, lty;
118 PLINT xmajor, xminor, ymajor, yminor;
119 PLINT i, i1x, i2x, i3x, i4x, i1y, i2y, i3y, i4y;
120 PLINT nxsub1, nysub1;
121 PLINT lxmin, lxmax, lymin, lymax;
122 PLINT pxmin, pxmax, pymin, pymax;
123 PLINT vppxmi, vppxma, vppymi, vppyma;
124 PLFLT xtick1, ytick1, vpwxmi, vpwxma, vpwymi, vpwyma;
125 PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax;
126 PLFLT xp0, yp0, tn, tp, temp;
127
128 if (plsc->level < 3) {
129 plabort("plbox: Please set up window first");
130 return;
131 }
132
133 /* Open the clip limits to the subpage limits */
134
135 plP_gclp(&lxmin, &lxmax, &lymin, &lymax);
136 plP_gphy(&pxmin, &pxmax, &pymin, &pymax);
137 plP_sclp(pxmin, pxmax, pymin, pymax);
138
139 vppxmi = plsc->vppxmi;
140 vppxma = plsc->vppxma;
141 vppymi = plsc->vppymi;
142 vppyma = plsc->vppyma;
143
144 /* Convert world coordinates to physical */
145
146 xp0 = plP_wcpcx(xx0);
147 yp0 = plP_wcpcy(yy0);
148
149 /* Set plot options from input */
150
151 lax = plP_stsearch(xopt, 'a');
152 lbx = plP_stsearch(xopt, 'b');
153 lcx = plP_stsearch(xopt, 'c');
154 lgx = plP_stsearch(xopt, 'g');
155 lix = plP_stsearch(xopt, 'i');
156 llx = plP_stsearch(xopt, 'l');
157 lsx = plP_stsearch(xopt, 's');
158 ltx = plP_stsearch(xopt, 't');
159
160 lay = plP_stsearch(yopt, 'a');
161 lby = plP_stsearch(yopt, 'b');
162 lcy = plP_stsearch(yopt, 'c');
163 lgy = plP_stsearch(yopt, 'g');
164 liy = plP_stsearch(yopt, 'i');
165 lly = plP_stsearch(yopt, 'l');
166 lsy = plP_stsearch(yopt, 's');
167 lty = plP_stsearch(yopt, 't');
168
169 /* Tick and subtick sizes in device coords */
170
171 xmajor = MAX(ROUND(plsc->majht * plsc->ypmm), 1);
172 ymajor = MAX(ROUND(plsc->majht * plsc->xpmm), 1);
173 xminor = MAX(ROUND(plsc->minht * plsc->ypmm), 1);
174 yminor = MAX(ROUND(plsc->minht * plsc->xpmm), 1);
175
176 nxsub1 = nxsub;
177 nysub1 = nysub;
178 xtick1 = llx ? 1.0 : xtick;
179 ytick1 = lly ? 1.0 : ytick;
180
181 plgvpw(&vpwxmin, &vpwxmax, &vpwymin, &vpwymax);
182 /* n.b. large change; vpwxmi always numerically less than vpwxma, and
183 * similarly for vpwymi */
184 vpwxmi = (vpwxmax > vpwxmin) ? vpwxmin : vpwxmax;
185 vpwxma = (vpwxmax > vpwxmin) ? vpwxmax : vpwxmin;
186 vpwymi = (vpwymax > vpwymin) ? vpwymin : vpwymax;
187 vpwyma = (vpwymax > vpwymin) ? vpwymax : vpwymin;
188
189 lax = lax && vpwymi < yy0 && yy0 < vpwyma ;
190 lay = lay && vpwxmi < xx0 && xx0 < vpwxma ;
191
192 /* Calculate tick spacing */
193
194 if (ltx || lgx)
195 pldtik(vpwxmi, vpwxma, &xtick1, &nxsub1);
196
197 if (lty || lgy)
198 pldtik(vpwymi, vpwyma, &ytick1, &nysub1);
199 /* n.b. large change; xtick1, nxsub1, ytick1, nysub1 always positive. */
200
201 /* Set up tick variables */
202
203 if (lix) {
204 i1x = xminor;
205 i2x = 0;
206 i3x = xmajor;
207 i4x = 0;
208 }
209 else {
210 i1x = 0;
211 i2x = xminor;
212 i3x = 0;
213 i4x = xmajor;
214 }
215
216 if (liy) {
217 i1y = yminor;
218 i2y = 0;
219 i3y = ymajor;
220 i4y = 0;
221 }
222 else {
223 i1y = 0;
224 i2y = yminor;
225 i3y = 0;
226 i4y = ymajor;
227 }
228
229 /* Draw the bottom edge of the box */
230
231 if (lbx) {
232 plP_movphy(vppxmi, vppymi);
233 if (ltx) {
234 tp = xtick1 * floor(vpwxmi / xtick1);
235 for (;;) {
236 tn = tp + xtick1;
237 if (lsx) {
238 if (llx) {
239 for (i = 0; i <= 7; i++) {
240 temp = tp + xlog[i];
241 if (BETW(temp, vpwxmi, vpwxma))
242 plxtik(plP_wcpcx(temp), vppymi, i1x, i2x);
243 }
244 }
245 else {
246 for (i = 1; i <= nxsub1 - 1; i++) {
247 temp = tp + i * xtick1 / nxsub1;
248 if (BETW(temp, vpwxmi, vpwxma))
249 plxtik(plP_wcpcx(temp), vppymi, i1x, i2x);
250 }
251 }
252 }
253 if (!BETW(tn, vpwxmi, vpwxma))
254 break;
255 plxtik(plP_wcpcx(tn), vppymi, i3x, i4x);
256 tp = tn;
257 }
258 }
259 plP_draphy(vppxma, vppymi);
260 }
261
262 /* Draw right-hand edge of box */
263
264 if (lcy) {
265 plP_movphy(vppxma, vppymi);
266 if (lty) {
267 tp = ytick1 * floor(vpwymi / ytick1);
268 for (;;) {
269 tn = tp + ytick1;
270 if (lsy) {
271 if (lly) {
272 for (i = 0; i <= 7; i++) {
273 temp = tp + xlog[i];
274 if (BETW(temp, vpwymi, vpwyma))
275 plytik(vppxma, plP_wcpcy(temp), i2y, i1y);
276 }
277 }
278 else {
279 for (i = 1; i <= nysub1 - 1; i++) {
280 temp = tp + i * ytick1 / nysub1;
281 if (BETW(temp, vpwymi, vpwyma))
282 plytik(vppxma, plP_wcpcy(temp), i2y, i1y);
283 }
284 }
285 }
286 if (!BETW(tn, vpwymi, vpwyma))
287 break;
288 plytik(vppxma, plP_wcpcy(tn), i4y, i3y);
289 tp = tn;
290 }
291 }
292 plP_draphy(vppxma, vppyma);
293 }
294
295 /* Draw the top edge of the box */
296
297 if (lcx) {
298 plP_movphy(vppxma, vppyma);
299 if (ltx) {
300 tp = xtick1 * (floor(vpwxma / xtick1) + 1);
301 for (;;) {
302 tn = tp - xtick1;
303 if (lsx) {
304 if (llx) {
305 for (i = 7; i >= 0; i--) {
306 temp = tn + xlog[i];
307 if (BETW(temp, vpwxmi, vpwxma))
308 plxtik(plP_wcpcx(temp), vppyma, i2x, i1x);
309 }
310 }
311 else {
312 for (i = nxsub1 - 1; i >= 1; i--) {
313 temp = tn + i * xtick1 / nxsub1;
314 if (BETW(temp, vpwxmi, vpwxma))
315 plxtik(plP_wcpcx(temp), vppyma, i2x, i1x);
316 }
317 }
318 }
319 if (!BETW(tn, vpwxmi, vpwxma))
320 break;
321 plxtik(plP_wcpcx(tn), vppyma, i4x, i3x);
322 tp = tn;
323 }
324 }
325 plP_draphy(vppxmi, vppyma);
326 }
327
328 /* Draw left-hand edge of box */
329
330 if (lby) {
331 plP_movphy(vppxmi, vppyma);
332 if (lty) {
333 tp = ytick1 * (floor(vpwyma / ytick1) + 1);
334 for (;;) {
335 tn = tp - ytick1;
336 if (lsy) {
337 if (lly) {
338 for (i = 7; i >= 0; i--) {
339 temp = tn + xlog[i];
340 if (BETW(temp, vpwymi, vpwyma))
341 plytik(vppxmi, plP_wcpcy(temp), i1y, i2y);
342 }
343 }
344 else {
345 for (i = nysub1 - 1; i >= 1; i--) {
346 temp = tn + i * ytick1 / nysub1;
347 if (BETW(temp, vpwymi, vpwyma))
348 plytik(vppxmi, plP_wcpcy(temp), i1y, i2y);
349 }
350 }
351 }
352 if (!BETW(tn, vpwymi, vpwyma))
353 break;
354 plytik(vppxmi, plP_wcpcy(tn), i3y, i4y);
355 tp = tn;
356 }
357 }
358 plP_draphy(vppxmi, vppymi);
359 }
360
361 /* Draw the horizontal axis */
362
363 if (lax) {
364 plP_movphy(vppxmi, yp0);
365 if (ltx) {
366 tp = xtick1 * floor(vpwxmi / xtick1);
367 for (;;) {
368 tn = tp + xtick1;
369 if (lsx) {
370 if (llx) {
371 for (i = 0; i <= 7; i++) {
372 temp = tp + xlog[i];
373 if (BETW(temp, vpwxmi, vpwxma))
374 plxtik(plP_wcpcx(temp), yp0, xminor, xminor);
375 }
376 }
377 else {
378 for (i = 1; i <= nxsub1 - 1; i++) {
379 temp = tp + i * xtick1 / nxsub1;
380 if (BETW(temp, vpwxmi, vpwxma))
381 plxtik(plP_wcpcx(temp), yp0, xminor, xminor);
382 }
383 }
384 }
385 if (!BETW(tn, vpwxmi, vpwxma))
386 break;
387 plxtik(plP_wcpcx(tn), yp0, xmajor, xmajor);
388 tp = tn;
389 }
390 }
391 plP_draphy(vppxma, yp0);
392 }
393
394 /* Draw the vertical axis */
395
396 if (lay) {
397 plP_movphy(xp0, vppymi);
398 if (lty) {
399 tp = ytick1 * floor(vpwymi / ytick1);
400 for (;;) {
401 tn = tp + ytick1;
402 if (lsy) {
403 if (lly) {
404 for (i = 0; i <= 7; i++) {
405 temp = tp + xlog[i];
406 if (BETW(temp, vpwymi, vpwyma))
407 plytik(xp0, plP_wcpcy(temp), yminor, yminor);
408 }
409 }
410 else {
411 for (i = 1; i <= nysub1 - 1; i++) {
412 temp = tp + i * ytick1 / nysub1;
413 if (BETW(temp, vpwymi, vpwyma))
414 plytik(xp0, plP_wcpcy(temp), yminor, yminor);
415 }
416 }
417 }
418 if (!BETW(tn, vpwymi, vpwyma))
419 break;
420 plytik(xp0, plP_wcpcy(tn), ymajor, ymajor);
421 tp = tn;
422 }
423 }
424 plP_draphy(xp0, vppyma);
425 }
426
427 /* Draw grids */
428
429 grid_box(xopt, xtick1, nxsub1, yopt, ytick1, nysub1);
430
431 /* Write labels */
432
433 label_box(xopt, xtick1, yopt, ytick1);
434
435 /* Restore the clip limits to viewport edge */
436
437 plP_sclp(lxmin, lxmax, lymin, lymax);
438 }
439
440 /*--------------------------------------------------------------------------*\
441 * void plbox3()
442 *
443 * This is the 3-d analogue of plbox().
444 \*--------------------------------------------------------------------------*/
445
446 void
c_plbox3(const char * xopt,const char * xlabel,PLFLT xtick,PLINT nsubx,const char * yopt,const char * ylabel,PLFLT ytick,PLINT nsuby,const char * zopt,const char * zlabel,PLFLT ztick,PLINT nsubz)447 c_plbox3(const char *xopt, const char *xlabel, PLFLT xtick, PLINT nsubx,
448 const char *yopt, const char *ylabel, PLFLT ytick, PLINT nsuby,
449 const char *zopt, const char *zlabel, PLFLT ztick, PLINT nsubz)
450 {
451 PLFLT dx, dy, tx, ty, ux, uy;
452 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
453 PLFLT cxx, cxy, cyx, cyy, cyz;
454 PLINT ln;
455 PLINT *zbflg, *zbcol, *zbwidth;
456 PLFLT *zbtck;
457 PLINT xdigmax, xdigits;
458 PLINT ydigmax, ydigits;
459 PLINT zdigmax, zdigits;
460
461 if (plsc->level < 3) {
462 plabort("plbox3: Please set up window first");
463 return;
464 }
465
466 plP_gw3wc(&cxx, &cxy, &cyx, &cyy, &cyz);
467 plP_gdom(&xmin, &xmax, &ymin, &ymax);
468 plP_grange(&zscale, &zmin, &zmax);
469
470 plgxax(&xdigmax, &xdigits);
471 plgyax(&ydigmax, &ydigits);
472 plgzax(&zdigmax, &zdigits);
473
474 xdigits = xdigmax;
475 ydigits = ydigmax;
476 zdigits = zdigmax;
477
478 /* We have to wait until after the plot is drawn to draw back */
479 /* grid so store this stuff. */
480
481 plP_gzback(&zbflg, &zbcol, &zbtck, &zbwidth);
482 *zbflg = plP_stsearch(zopt, 'd');
483 if (*zbflg) {
484 *zbtck = ztick; /* save tick spacing */
485 *zbcol = plsc->icol0; /* and color */
486 *zbwidth = plsc->width; /* and line width */
487 }
488
489 if (cxx >= 0.0 && cxy <= 0.0) {
490 ln = plP_stsearch(xopt, 'n');
491 tx = plP_w3wcx(xmin, ymin, zmin);
492 ty = plP_w3wcy(xmin, ymin, zmin);
493 ux = plP_w3wcx(xmax, ymin, zmin);
494 uy = plP_w3wcy(xmax, ymin, zmin);
495 plxybx(xopt, xlabel, tx, ty, ux, uy,
496 xmin, xmax, xtick, nsubx, 0, &xdigits);
497
498 dx = ux - tx;
499 dy = uy - ty;
500 plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
501 plP_w3wcy(xmax, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
502
503 tx = plP_w3wcx(xmin, ymax, zmin);
504 ty = plP_w3wcy(xmin, ymax, zmin);
505 ux = plP_w3wcx(xmin, ymin, zmin);
506 uy = plP_w3wcy(xmin, ymin, zmin);
507 plxybx(yopt, ylabel, tx, ty, ux, uy,
508 ymax, ymin, ytick, nsuby, ln, &ydigits);
509
510 dx = ux - tx;
511 dy = uy - ty;
512 /* restore zdigits to initial value for second call */
513 zdigits = zdigmax;
514 plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
515 plP_w3wcy(xmin, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
516 }
517 else if (cxx <= 0.0 && cxy <= 0.0) {
518 ln = plP_stsearch(yopt, 'n');
519 tx = plP_w3wcx(xmin, ymax, zmin);
520 ty = plP_w3wcy(xmin, ymax, zmin);
521 ux = plP_w3wcx(xmin, ymin, zmin);
522 uy = plP_w3wcy(xmin, ymin, zmin);
523 plxybx(yopt, ylabel, tx, ty, ux, uy,
524 ymax, ymin, ytick, nsuby, 0, &ydigits);
525
526 dx = ux - tx;
527 dy = uy - ty;
528 plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
529 plP_w3wcy(xmin, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
530
531 tx = plP_w3wcx(xmax, ymax, zmin);
532 ty = plP_w3wcy(xmax, ymax, zmin);
533 ux = plP_w3wcx(xmin, ymax, zmin);
534 uy = plP_w3wcy(xmin, ymax, zmin);
535 plxybx(xopt, xlabel, tx, ty, ux, uy,
536 xmax, xmin, xtick, nsubx, ln, &xdigits);
537
538 dx = ux - tx;
539 dy = uy - ty;
540 /* restore zdigits to initial value for second call */
541 zdigits = zdigmax;
542 plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
543 plP_w3wcy(xmax, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
544 }
545 else if (cxx <= 0.0 && cxy >= 0.0) {
546 ln = plP_stsearch(xopt, 'n');
547 tx = plP_w3wcx(xmax, ymax, zmin);
548 ty = plP_w3wcy(xmax, ymax, zmin);
549 ux = plP_w3wcx(xmin, ymax, zmin);
550 uy = plP_w3wcy(xmin, ymax, zmin);
551 plxybx(xopt, xlabel, tx, ty, ux, uy,
552 xmax, xmin, xtick, nsubx, 0, &xdigits);
553
554 dx = ux - tx;
555 dy = uy - ty;
556 plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
557 plP_w3wcy(xmin, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
558
559 tx = plP_w3wcx(xmax, ymin, zmin);
560 ty = plP_w3wcy(xmax, ymin, zmin);
561 ux = plP_w3wcx(xmax, ymax, zmin);
562 uy = plP_w3wcy(xmax, ymax, zmin);
563 plxybx(yopt, ylabel, tx, ty, ux, uy,
564 ymin, ymax, ytick, nsuby, ln, &ydigits);
565
566 dx = ux - tx;
567 dy = uy - ty;
568 /* restore zdigits to initial value for second call */
569 zdigits = zdigmax;
570 plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
571 plP_w3wcy(xmax, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
572 }
573 else if (cxx >= 0.0 && cxy >= 0.0) {
574 ln = plP_stsearch(yopt, 'n');
575 tx = plP_w3wcx(xmax, ymin, zmin);
576 ty = plP_w3wcy(xmax, ymin, zmin);
577 ux = plP_w3wcx(xmax, ymax, zmin);
578 uy = plP_w3wcy(xmax, ymax, zmin);
579 plxybx(yopt, ylabel, tx, ty, ux, uy,
580 ymin, ymax, ytick, nsuby, 0, &ydigits);
581
582 dx = ux - tx;
583 dy = uy - ty;
584 plzbx(zopt, zlabel, 1, dx, dy, ux, uy,
585 plP_w3wcy(xmax, ymax, zmax), zmin, zmax, ztick, nsubz, &zdigits);
586
587 tx = plP_w3wcx(xmin, ymin, zmin);
588 ty = plP_w3wcy(xmin, ymin, zmin);
589 ux = plP_w3wcx(xmax, ymin, zmin);
590 uy = plP_w3wcy(xmax, ymin, zmin);
591 plxybx(xopt, xlabel, tx, ty, ux, uy,
592 xmin, xmax, xtick, nsubx, ln, &xdigits);
593
594 dx = ux - tx;
595 dy = uy - ty;
596 /* restore zdigits to initial value for second call */
597 zdigits = zdigmax;
598 plzbx(zopt, zlabel, 0, dx, dy, tx, ty,
599 plP_w3wcy(xmin, ymin, zmax), zmin, zmax, ztick, nsubz, &zdigits);
600 }
601 plsxax(xdigmax, xdigits);
602 plsyax(ydigmax, ydigits);
603 plszax(zdigmax, zdigits);
604 }
605
606 /*--------------------------------------------------------------------------*\
607 * Support routines for 3d box draw.
608 \*--------------------------------------------------------------------------*/
609
610 /*--------------------------------------------------------------------------*\
611 * void plxybx()
612 *
613 * This draws a sloping line from (wx1,wy1) to (wx2,wy2) which represents an
614 * axis of a 3-d graph with data values from "vmin" to "vmax". Depending on
615 * "opt", vertical ticks and/or subticks are placed on the line at major tick
616 * interval "tick" with "nsub" subticks between major ticks. If "tick" and/or
617 * "nsub" is zero, automatic tick positions are computed
618 *
619 * b: Draw box boundary
620 * f: Always use fixed point numeric labels
621 * i: Inverts tick marks (i.e. drawn downwards)
622 * l: Logarithmic axes, major ticks at decades, minor ticks at units
623 * n: Write numeric label
624 * t: Draw major tick marks
625 * s: Draw minor tick marks
626 * u: Write label on line
627 \*--------------------------------------------------------------------------*/
628
629 static void
plxybx(const char * opt,const char * label,PLFLT wx1,PLFLT wy1,PLFLT wx2,PLFLT wy2,PLFLT vmin_in,PLFLT vmax_in,PLFLT tick,PLINT nsub,PLINT nolast,PLINT * digits)630 plxybx(const char *opt, const char *label, PLFLT wx1, PLFLT wy1,
631 PLFLT wx2, PLFLT wy2, PLFLT vmin_in, PLFLT vmax_in,
632 PLFLT tick, PLINT nsub, PLINT nolast, PLINT *digits)
633 {
634 static char string[40];
635 PLINT lb, lf, li, ll, ln, ls, lt, lu;
636 PLINT major, minor, mode, prec, scale;
637 PLINT i, i1, i2, i3, i4;
638 PLINT nsub1;
639 PLFLT pos, tn, tp, temp, height, tick1, vmin, vmax;
640 /* Note that 'tspace' is the minimim distance away (in fractional number
641 * of ticks) from the boundary that an X or Y numerical label can be drawn. */
642 PLFLT dwx, dwy, lambda, tcrit, tspace = 0.1;
643
644 (void) nolast; /* pmr: make it used */
645
646 vmin = (vmax_in > vmin_in) ? vmin_in : vmax_in;
647 vmax = (vmax_in > vmin_in) ? vmax_in : vmin_in;
648
649 dwx = wx2 - wx1;
650 dwy = wy2 - wy1;
651
652 /* Tick and subtick sizes in device coords */
653
654 major = MAX(ROUND(plsc->majht * plsc->ypmm), 1);
655 minor = MAX(ROUND(plsc->minht * plsc->ypmm), 1);
656
657 tick1 = tick;
658 nsub1 = nsub;
659
660 lb = plP_stsearch(opt, 'b');
661 lf = plP_stsearch(opt, 'f');
662 li = plP_stsearch(opt, 'i');
663 ll = plP_stsearch(opt, 'l');
664 ln = plP_stsearch(opt, 'n');
665 ls = plP_stsearch(opt, 's');
666 lt = plP_stsearch(opt, 't');
667 lu = plP_stsearch(opt, 'u');
668
669 if (lu)
670 plxytx(wx1, wy1, wx2, wy2, 3.2, 0.5, 0.5, label);
671 if (!lb)
672 return;
673
674 if (ll)
675 tick1 = (vmax > vmin) ? 1.0 : -1.0 ;
676 if (lt)
677 pldtik(vmin, vmax, &tick1, &nsub1);
678
679 if (li) {
680 i1 = minor;
681 i2 = 0;
682 i3 = major;
683 i4 = 0;
684 }
685 else {
686 i1 = 0;
687 i2 = minor;
688 i3 = 0;
689 i4 = major;
690 }
691
692 /* Draw the line */
693
694 plP_movwor(wx1, wy1);
695 if (lt) {
696 tp = tick1 * floor(vmin / tick1);
697 for (;;) {
698 tn = tp + tick1;
699 if (ls) {
700 if (ll) {
701 for (i = 0; i <= 7; i++) {
702 temp = tp + xlog[i];
703 if (BETW(temp, vmin, vmax)) {
704 lambda = (vmax_in > vmin_in)?
705 (temp - vmin) / (vmax - vmin):
706 (vmax - temp) / (vmax - vmin);
707 plxtik(plP_wcpcx((PLFLT) (wx1 + lambda * dwx)),
708 plP_wcpcy((PLFLT) (wy1 + lambda * dwy)),
709 i1, i2);
710 }
711 }
712 }
713 else {
714 for (i = 1; i <= nsub1 - 1; i++) {
715 temp = tp + i * (tn - tp) / nsub1;
716 if (BETW(temp, vmin, vmax)) {
717 lambda = (vmax_in > vmin_in)?
718 (temp - vmin) / (vmax - vmin):
719 (vmax - temp) / (vmax - vmin);
720 plxtik(plP_wcpcx((PLFLT) (wx1 + lambda * dwx)),
721 plP_wcpcy((PLFLT) (wy1 + lambda * dwy)),
722 i1, i2);
723 }
724 }
725 }
726 }
727 temp = tn;
728 if (!BETW(temp, vmin, vmax))
729 break;
730
731 lambda = (vmax_in > vmin_in)?
732 (temp - vmin) / (vmax - vmin):
733 (vmax - temp) / (vmax - vmin);
734 plxtik(plP_wcpcx((PLFLT) (wx1 + lambda * dwx)),
735 plP_wcpcy((PLFLT) (wy1 + lambda * dwy)), i3, i4);
736 tp = tn;
737 }
738 }
739
740 plP_drawor(wx2, wy2);
741
742 /* Label the line */
743
744 if (ln && lt) {
745 pldprec(vmin, vmax, tick1, lf, &mode, &prec, *digits, &scale);
746 pos = 1.0;
747 height = 3.2;
748 tcrit = tspace*tick1;
749 tp = tick1 * (1. + floor(vmin / tick1));
750 for (tn = tp; BETW(tn, vmin, vmax); tn += tick1) {
751 if(BETW(tn, vmin+tcrit, vmax-tcrit)) {
752 plform(tn, scale, prec, string, ll, lf);
753 pos = (vmax_in > vmin_in)?
754 (tn - vmin) / (vmax - vmin):
755 (vmax - tn) / (vmax - vmin);
756 plxytx(wx1, wy1, wx2, wy2, 1.5, pos, 0.5, string);
757 }
758 }
759 *digits = 2;
760 if (!ll && mode) {
761 sprintf(string, "(x10#u%d#d)", (int) scale);
762 plxytx(wx1, wy1, wx2, wy2, height, 1.0, 0.5, string);
763 }
764 }
765 }
766
767 /*--------------------------------------------------------------------------*\
768 * void plxytx()
769 *
770 * Prints out text along a sloping axis joining world coordinates
771 * (wx1,wy1) to (wx2,wy2). Parameters are as for plmtext.
772 \*--------------------------------------------------------------------------*/
773
774 static void
plxytx(PLFLT wx1,PLFLT wy1,PLFLT wx2,PLFLT wy2,PLFLT disp,PLFLT pos,PLFLT just,const char * text)775 plxytx(PLFLT wx1, PLFLT wy1, PLFLT wx2, PLFLT wy2,
776 PLFLT disp, PLFLT pos, PLFLT just, const char *text)
777 {
778 PLINT x, y, refx, refy;
779 PLFLT shift, cc, ss, wx, wy;
780 PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, xform[4], diag;
781 PLFLT dispx, dispy;
782 PLFLT chrdef, chrht;
783
784 cc = plsc->wmxscl * (wx2 - wx1);
785 ss = plsc->wmyscl * (wy2 - wy1);
786 diag = sqrt(cc * cc + ss * ss);
787 cc /= diag;
788 ss /= diag;
789 wx = wx1 + pos * (wx2 - wx1);
790 wy = wy1 + pos * (wy2 - wy1);
791
792 xform[0] = cc;
793 xform[1] = 0.0;
794 xform[2] = ss;
795 xform[3] = 1.0;
796
797 xdv = plP_wcdcx(wx);
798 ydv = plP_wcdcy(wy);
799
800 dispx = 0.;
801 dispy = -disp;
802
803 plgchr(&chrdef, &chrht);
804 shift = (just == 0.0) ? 0.0 : plstrl(text) * just;
805
806 xmm = plP_dcmmx(xdv) + dispx * chrht;
807 ymm = plP_dcmmy(ydv) + dispy * chrht;
808 refxmm = xmm - shift * xform[0];
809 refymm = ymm - shift * xform[2];
810
811 x = plP_mmpcx(xmm);
812 y = plP_mmpcy(ymm);
813 refx = plP_mmpcx(refxmm);
814 refy = plP_mmpcy(refymm);
815
816 plP_text(0, just, xform, x, y, refx, refy, text);
817 }
818
819 /*--------------------------------------------------------------------------*\
820 * void plzbx()
821 *
822 * This draws a vertical line from (wx,wy1) to (wx,wy2) which represents the
823 * vertical axis of a 3-d graph with data values from "vmin" to "vmax".
824 * Depending on "opt", ticks and/or subticks are placed on the line at major
825 * tick interval "tick" with "nsub" subticks between major ticks. If "tick"
826 * and/or "nsub" is zero, automatic tick positions are computed
827 *
828 * b: Draws left-hand axis
829 * c: Draws right-hand axis
830 * f: Always use fixed point numeric labels
831 * i: Inverts tick marks (i.e. drawn to the left)
832 * l: Logarithmic axes, major ticks at decades, minor ticks at units
833 * m: Write numeric label on right axis
834 * n: Write numeric label on left axis
835 * s: Draw minor tick marks
836 * t: Draw major tick marks
837 * u: Writes left-hand label
838 * v: Writes right-hand label
839 \*--------------------------------------------------------------------------*/
840
841 static void
plzbx(const char * opt,const char * label,PLINT right,PLFLT dx,PLFLT dy,PLFLT wx,PLFLT wy1,PLFLT wy2,PLFLT vmin_in,PLFLT vmax_in,PLFLT tick,PLINT nsub,PLINT * digits)842 plzbx(const char *opt, const char *label, PLINT right, PLFLT dx, PLFLT dy,
843 PLFLT wx, PLFLT wy1, PLFLT wy2, PLFLT vmin_in, PLFLT vmax_in,
844 PLFLT tick, PLINT nsub, PLINT *digits)
845 {
846 static char string[40];
847 PLINT lb, lc, lf, li, ll, lm, ln, ls, lt, lu, lv;
848 PLINT i, mode, prec, scale;
849 PLINT nsub1, lstring;
850 PLFLT pos, tn, tp, temp, height, tick1;
851 PLFLT dwy, lambda, diag, major, minor, xmajor, xminor;
852 PLFLT ymajor, yminor, dxm, dym, vmin, vmax;
853
854 vmin = (vmax_in > vmin_in) ? vmin_in : vmax_in;
855 vmax = (vmax_in > vmin_in) ? vmax_in : vmin_in;
856
857 dwy = wy2 - wy1;
858
859 /* Tick and subtick sizes in device coords */
860
861 major = plsc->majht;
862 minor = plsc->minht;
863
864 tick1 = tick;
865 nsub1 = nsub;
866
867 lb = plP_stsearch(opt, 'b');
868 lc = plP_stsearch(opt, 'c');
869 lf = plP_stsearch(opt, 'f');
870 li = plP_stsearch(opt, 'i');
871 ll = plP_stsearch(opt, 'l');
872 lm = plP_stsearch(opt, 'm');
873 ln = plP_stsearch(opt, 'n');
874 ls = plP_stsearch(opt, 's');
875 lt = plP_stsearch(opt, 't');
876 lu = plP_stsearch(opt, 'u');
877 lv = plP_stsearch(opt, 'v');
878
879 if (lu && !right)
880 plztx("h", dx, dy, wx, wy1, wy2, 5.0, 0.5, 0.5, label);
881
882 if (lv && right)
883 plztx("h", dx, dy, wx, wy1, wy2, -5.0, 0.5, 0.5, label);
884
885 if (right && !lc)
886 return;
887
888 if (!right && !lb)
889 return;
890
891 if (ll)
892 tick1 = 1.0;
893
894 if (lt)
895 pldtik(vmin, vmax, &tick1, &nsub1);
896
897 if ((li && !right) || (!li && right)) {
898 minor = -minor;
899 major = -major;
900 }
901
902 dxm = dx * plsc->wmxscl;
903 dym = dy * plsc->wmyscl;
904 diag = sqrt(dxm * dxm + dym * dym);
905
906 xminor = minor * dxm / diag;
907 xmajor = major * dxm / diag;
908 yminor = minor * dym / diag;
909 ymajor = major * dym / diag;
910
911 /* Draw the line */
912
913 plP_movwor(wx, wy1);
914 if (lt) {
915 tp = tick1 * floor(vmin / tick1);
916 for (;;) {
917 tn = tp + tick1;
918 if (ls) {
919 if (ll) {
920 for (i = 0; i <= 7; i++) {
921 temp = tp + xlog[i];
922 if (BETW(temp, vmin, vmax)) {
923 lambda = (vmax_in > vmin_in)?
924 (temp - vmin) / (vmax - vmin):
925 (vmax - temp) / (vmax - vmin);
926 plstik(plP_wcmmx(wx),
927 plP_wcmmy((PLFLT) (wy1 + lambda * dwy)),
928 xminor, yminor);
929 }
930 }
931 }
932 else {
933 for (i = 1; i <= nsub1 - 1; i++) {
934 temp = tp + i * tick1 / nsub1;
935 if (BETW(temp, vmin, vmax)) {
936 lambda = (vmax_in > vmin_in)?
937 (temp - vmin) / (vmax - vmin):
938 (vmax - temp) / (vmax - vmin);
939 plstik(plP_wcmmx(wx),
940 plP_wcmmy((PLFLT) (wy1 + lambda * dwy)),
941 xminor, yminor);
942 }
943 }
944 }
945 }
946 temp = tn;
947 if (!BETW(temp, vmin, vmax))
948 break;
949 lambda = (vmax_in > vmin_in)?
950 (temp - vmin) / (vmax - vmin):
951 (vmax - temp) / (vmax - vmin);
952 plstik(plP_wcmmx(wx), plP_wcmmy((PLFLT) (wy1 + lambda * dwy)),
953 xmajor, ymajor);
954 tp = tn;
955 }
956 }
957
958 plP_drawor(wx, wy2);
959
960 /* Label the line */
961
962 if ((ln || lm) && lt) {
963 pldprec(vmin, vmax, tick1, lf, &mode, &prec, *digits, &scale);
964 *digits = 0;
965 tp = tick1 * floor(vmin / tick1);
966 for (tn = tp + tick1; BETW(tn, vmin, vmax); tn += tick1) {
967 plform(tn, scale, prec, string, ll, lf);
968 pos = (vmax_in > vmin_in)?
969 (tn - vmin) / (vmax - vmin):
970 (vmax - tn) / (vmax - vmin);
971 if (ln && !right)
972 plztx("v", dx, dy, wx, wy1, wy2, 0.5, pos, 1.0, string);
973
974 if (lm && right)
975 plztx("v", dx, dy, wx, wy1, wy2, -0.5, pos, 0.0, string);
976
977 lstring = strlen(string);
978 *digits = MAX(*digits, lstring);
979 }
980 if (!ll && mode) {
981 sprintf(string, "(x10#u%d#d)", (int) scale);
982 pos = 1.15;
983 height = 0.5;
984 if (ln && !right) {
985 plztx("v", dx, dy, wx, wy1, wy2, height, pos, 0.5, string);
986 }
987 if (lm && right) {
988 plztx("v", dx, dy, wx, wy1, wy2,
989 (PLFLT) -height, pos, 0.5, string);
990 }
991 }
992 }
993 }
994
995 /*--------------------------------------------------------------------------*\
996 * void plztx()
997 *
998 * Prints out text along a vertical axis for a 3d plot joining
999 * world coordinates (wx,wy1) to (wx,wy2).
1000 \*--------------------------------------------------------------------------*/
1001
1002 static void
plztx(const char * opt,PLFLT dx,PLFLT dy,PLFLT wx,PLFLT wy1,PLFLT wy2,PLFLT disp,PLFLT pos,PLFLT just,const char * text)1003 plztx(const char *opt, PLFLT dx, PLFLT dy, PLFLT wx, PLFLT wy1,
1004 PLFLT wy2, PLFLT disp, PLFLT pos, PLFLT just, const char *text)
1005 {
1006 PLINT refx = 0, refy = 0, x = 0, y = 0, vert = 0;
1007 PLFLT shift, cc, ss, wy;
1008 PLFLT xdv, ydv, xmm, ymm, refxmm, refymm, xform[4], diag;
1009 PLFLT dispx, dispy;
1010 PLFLT chrdef, chrht;
1011
1012 cc = plsc->wmxscl * dx;
1013 ss = plsc->wmyscl * dy;
1014 diag = sqrt(cc * cc + ss * ss);
1015 cc /= diag;
1016 ss /= diag;
1017 wy = wy1 + pos * (wy2 - wy1);
1018
1019 if (plP_stsearch(opt, 'v'))
1020 vert = 0;
1021 else if (plP_stsearch(opt, 'h'))
1022 vert = 1;
1023
1024 if (vert) {
1025 xform[0] = 0.0;
1026 xform[1] = -cc;
1027 xform[2] = 1.0;
1028 xform[3] = -ss;
1029 } else {
1030 xform[0] = cc;
1031 xform[1] = 0.0;
1032 xform[2] = ss;
1033 xform[3] = 1.0;
1034 }
1035
1036 xdv = plP_wcdcx(wx);
1037 ydv = plP_wcdcy(wy);
1038
1039 dispx = -disp * cc;
1040 dispy = -disp * ss;
1041
1042 plgchr(&chrdef, &chrht);
1043 shift = (just == 0.0) ? 0.0 : plstrl(text) * just;
1044
1045 xmm = plP_dcmmx(xdv) + dispx * chrht;
1046 ymm = plP_dcmmy(ydv) + dispy * chrht;
1047 refxmm = xmm - shift * xform[0];
1048 refymm = ymm - shift * xform[2];
1049
1050 x = plP_mmpcx(xmm);
1051 y = plP_mmpcy(ymm);
1052 refx = plP_mmpcx(refxmm);
1053 refy = plP_mmpcy(refymm);
1054
1055 plP_text(0, just, xform, x, y, refx, refy, text);
1056 }
1057
1058 /*--------------------------------------------------------------------------*\
1059 * void grid_box()
1060 *
1061 * Draws grids at tick locations (major and/or minor).
1062 *
1063 * Note that 'tspace' is the minimim distance away (in fractional number
1064 * of ticks or subticks) from the boundary a grid line can be drawn. If
1065 * you are too close, it looks bad.
1066 \*--------------------------------------------------------------------------*/
1067
1068 static void
grid_box(const char * xopt,PLFLT xtick1,PLINT nxsub1,const char * yopt,PLFLT ytick1,PLINT nysub1)1069 grid_box(const char *xopt, PLFLT xtick1, PLINT nxsub1,
1070 const char *yopt, PLFLT ytick1, PLINT nysub1)
1071 {
1072 PLINT lgx, lhx, llx;
1073 PLINT lgy, lhy, lly;
1074 PLFLT vpwxmi, vpwxma, vpwymi, vpwyma;
1075 PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax;
1076 PLFLT tn, temp, tcrit, tspace = 0.1;
1077 PLINT i;
1078
1079 /* Set plot options from input */
1080
1081 lgx = plP_stsearch(xopt, 'g');
1082 lhx = plP_stsearch(xopt, 'h');
1083 llx = plP_stsearch(xopt, 'l');
1084
1085 lgy = plP_stsearch(yopt, 'g');
1086 lhy = plP_stsearch(yopt, 'h');
1087 lly = plP_stsearch(yopt, 'l');
1088
1089 plgvpw(&vpwxmin, &vpwxmax, &vpwymin, &vpwymax);
1090 /* n.b. large change; vpwxmi always numerically less than vpwxma, and
1091 * similarly for vpwymi */
1092 vpwxmi = (vpwxmax > vpwxmin) ? vpwxmin : vpwxmax;
1093 vpwxma = (vpwxmax > vpwxmin) ? vpwxmax : vpwxmin;
1094 vpwymi = (vpwymax > vpwymin) ? vpwymin : vpwymax;
1095 vpwyma = (vpwymax > vpwymin) ? vpwymax : vpwymin;
1096
1097 /* Draw grid in x direction. */
1098
1099 if (lgx) {
1100 for (tn = xtick1 * floor(vpwxmi/xtick1);
1101 tn <= vpwxma; tn += xtick1) {
1102 if (lhx) {
1103 if (llx) {
1104 PLFLT otemp = tn;
1105 for (i = 0; i <= 7; i++) {
1106 temp = tn + xlog[i];
1107 tcrit = (temp - otemp)*tspace;
1108 otemp = temp;
1109 if (BETW(temp, vpwxmi+tcrit, vpwxma-tcrit))
1110 pljoin(temp, vpwymi, temp, vpwyma);
1111 }
1112 }
1113 else {
1114 for (i = 1; i <= nxsub1 - 1; i++) {
1115 temp = tn + i * xtick1 / nxsub1;
1116 tcrit = xtick1 / nxsub1 * tspace;
1117 if (BETW(temp, vpwxmi+tcrit, vpwxma-tcrit))
1118 pljoin(temp, vpwymi, temp, vpwyma);
1119 }
1120 }
1121 }
1122 tcrit = xtick1*tspace;
1123 if (BETW(tn, vpwxmi+tcrit, vpwxma-tcrit))
1124 pljoin(tn, vpwymi, tn, vpwyma);
1125 }
1126 }
1127
1128 /* Draw grid in y direction */
1129
1130 if (lgy) {
1131 tn = ytick1 * floor(vpwymi / ytick1 + tspace);
1132 for (tn = ytick1 * floor(vpwymi/ytick1);
1133 tn <= vpwyma; tn += ytick1) {
1134 if (lhy) {
1135 if (lly) {
1136 PLFLT otemp = tn;
1137 for (i = 0; i <= 7; i++) {
1138 temp = tn + xlog[i];
1139 tcrit = (temp - otemp)*tspace;
1140 otemp = temp;
1141 if (BETW(temp, vpwymi+tcrit, vpwyma-tcrit))
1142 pljoin(vpwxmi, temp, vpwxma, temp);
1143 }
1144 }
1145 else {
1146 for (i = 1; i <= nysub1 - 1; i++) {
1147 temp = tn + i * ytick1 / nysub1;
1148 tcrit = ytick1 / nysub1 * tspace;
1149 if (BETW(temp, vpwymi+tcrit, vpwyma-tcrit))
1150 pljoin(vpwxmi, temp, vpwxma, temp);
1151 }
1152 }
1153 }
1154 tcrit = ytick1*tspace;
1155 if (BETW(tn, vpwymi+tcrit, vpwyma-tcrit))
1156 pljoin(vpwxmi, tn, vpwxma, tn);
1157 }
1158 }
1159 }
1160
1161 /*--------------------------------------------------------------------------*\
1162 * void label_box()
1163 *
1164 * Writes numeric labels on side(s) of box.
1165 \*--------------------------------------------------------------------------*/
1166
1167 static void
label_box(const char * xopt,PLFLT xtick1,const char * yopt,PLFLT ytick1)1168 label_box(const char *xopt, PLFLT xtick1, const char *yopt, PLFLT ytick1)
1169 {
1170 static char string[40];
1171 PLINT lfx, lix, llx, lmx, lnx, ltx;
1172 PLINT lfy, liy, lly, lmy, lny, lty, lvy;
1173 PLFLT vpwxmi, vpwxma, vpwymi, vpwyma;
1174 PLFLT vpwxmin, vpwxmax, vpwymin, vpwymax;
1175 PLFLT pos, tn, tp, offset, height;
1176
1177 /* Set plot options from input */
1178
1179 lfx = plP_stsearch(xopt, 'f');
1180 lix = plP_stsearch(xopt, 'i');
1181 llx = plP_stsearch(xopt, 'l');
1182 lmx = plP_stsearch(xopt, 'm');
1183 lnx = plP_stsearch(xopt, 'n');
1184 ltx = plP_stsearch(xopt, 't');
1185
1186 lfy = plP_stsearch(yopt, 'f');
1187 liy = plP_stsearch(yopt, 'i');
1188 lly = plP_stsearch(yopt, 'l');
1189 lmy = plP_stsearch(yopt, 'm');
1190 lny = plP_stsearch(yopt, 'n');
1191 lty = plP_stsearch(yopt, 't');
1192 lvy = plP_stsearch(yopt, 'v');
1193
1194 plgvpw(&vpwxmin, &vpwxmax, &vpwymin, &vpwymax);
1195 /* n.b. large change; vpwxmi always numerically less than vpwxma, and
1196 * similarly for vpwymi */
1197 vpwxmi = (vpwxmax > vpwxmin) ? vpwxmin : vpwxmax;
1198 vpwxma = (vpwxmax > vpwxmin) ? vpwxmax : vpwxmin;
1199 vpwymi = (vpwymax > vpwymin) ? vpwymin : vpwymax;
1200 vpwyma = (vpwymax > vpwymin) ? vpwymax : vpwymin;
1201
1202 /* Write horizontal label(s) */
1203
1204 if ((lmx || lnx) && ltx) {
1205 PLINT xmode, xprec, xdigmax, xdigits, xscale;
1206
1207 plgxax(&xdigmax, &xdigits);
1208 pldprec(vpwxmi, vpwxma, xtick1, lfx, &xmode, &xprec, xdigmax, &xscale);
1209
1210 tp = xtick1 * (1. + floor(vpwxmi / xtick1));
1211 for (tn = tp; BETW(tn, vpwxmi, vpwxma); tn += xtick1) {
1212 plform(tn, xscale, xprec, string, llx, lfx);
1213 height = lix ? 1.75 : 1.5;
1214 pos = (vpwxmax > vpwxmin)?
1215 (tn - vpwxmi) / (vpwxma - vpwxmi):
1216 (vpwxma - tn) / (vpwxma - vpwxmi);
1217 if (lnx)
1218 plmtex("b", height, pos, 0.5, string);
1219 if (lmx)
1220 plmtex("t", height, pos, 0.5, string);
1221 }
1222 xdigits = 2;
1223 plsxax(xdigmax, xdigits);
1224
1225 /* Write separate exponential label if mode = 1. */
1226
1227 if (!llx && xmode) {
1228 pos = 1.0;
1229 height = 3.2;
1230 sprintf(string, "(x10#u%d#d)", (int) xscale);
1231 if (lnx)
1232 plmtex("b", height, pos, 0.5, string);
1233 if (lmx)
1234 plmtex("t", height, pos, 0.5, string);
1235 }
1236 }
1237
1238 /* Write vertical label(s) */
1239
1240 if ((lmy || lny) && lty) {
1241 PLINT ymode, yprec, ydigmax, ydigits, yscale;
1242
1243 plgyax(&ydigmax, &ydigits);
1244 pldprec(vpwymi, vpwyma, ytick1, lfy, &ymode, &yprec, ydigmax, &yscale);
1245
1246 ydigits = 0;
1247 tp = ytick1 * (1. + floor(vpwymi / ytick1));
1248 for (tn = tp; BETW(tn, vpwymi, vpwyma); tn += ytick1) {
1249 plform(tn, yscale, yprec, string, lly, lfy);
1250 pos = (vpwymax > vpwymin)?
1251 (tn - vpwymi) / (vpwyma - vpwymi):
1252 (vpwyma - tn) / (vpwyma - vpwymi);
1253 if (lny) {
1254 if (lvy) {
1255 height = liy ? 1.0 : 0.5;
1256 plmtex("lv", height, pos, 1.0, string);
1257 } else {
1258 height = liy ? 1.75 : 1.5;
1259 plmtex("l", height, pos, 0.5, string);
1260 }
1261 }
1262 if (lmy) {
1263 if (lvy) {
1264 height = liy ? 1.0 : 0.5;
1265 plmtex("rv", height, pos, 0.0, string);
1266 } else {
1267 height = liy ? 1.75 : 1.5;
1268 plmtex("r", height, pos, 0.5, string);
1269 }
1270 }
1271 ydigits = MAX(ydigits, (PLINT) strlen(string));
1272 }
1273 if (!lvy)
1274 ydigits = 2;
1275
1276 plsyax(ydigmax, ydigits);
1277
1278 /* Write separate exponential label if mode = 1. */
1279
1280 if (!lly && ymode) {
1281 sprintf(string, "(x10#u%d#d)", (int) yscale);
1282 offset = 0.02;
1283 height = 2.0;
1284 if (lny) {
1285 pos = 0.0 - offset;
1286 plmtex("t", height, pos, 1.0, string);
1287 }
1288 if (lmy) {
1289 pos = 1.0 + offset;
1290 plmtex("t", height, pos, 0.0, string);
1291 }
1292 }
1293 }
1294 }
1295
1296 /*--------------------------------------------------------------------------*\
1297 * void plform()
1298 *
1299 * Formats a PLFLT value in one of the following formats.
1300 *
1301 * If ll (logarithmic), then:
1302 *
1303 * - If lf (fixed), then used fixed point notation, i.e. .1, 1, 10, etc,
1304 * with unnecessary trailing .'s or 0's removed.
1305 *
1306 * - If !lf (default), then use exponential notation, i.e. 10^-1, etc.
1307 *
1308 * If !ll (linear), then:
1309 *
1310 * - If scale == 0, use fixed point format with "prec" places after the
1311 * decimal point.
1312 *
1313 * - If scale == 1, use scientific notation with one place before the
1314 * decimal point and "prec" places after. In this case, the value
1315 * must be divided by 10^scale.
1316 \*--------------------------------------------------------------------------*/
1317
1318 static void
plform(PLFLT value,PLINT scale,PLINT prec,char * string,PLINT ll,PLINT lf)1319 plform(PLFLT value, PLINT scale, PLINT prec, char *string, PLINT ll, PLINT lf)
1320 {
1321 if (ll) {
1322
1323 /* Logarithmic */
1324
1325 if (lf) {
1326
1327 /* Fixed point, i.e. .1, 1, 10, etc */
1328
1329 int exponent = ROUND(value);
1330
1331 value = pow(10.0, exponent);
1332 if (exponent < 0) {
1333 char form[10];
1334 sprintf(form, "%%.%df", ABS(exponent));
1335 sprintf(string, form, value);
1336 }
1337 else {
1338 sprintf(string, "%d", (int) value);
1339 }
1340 }
1341 else {
1342
1343 /* Exponential, i.e. 10^-1, 10^0, 10^1, etc */
1344
1345 sprintf(string, "10#u%d", (int) ROUND(value));
1346 }
1347 }
1348 else {
1349
1350 /* Linear */
1351
1352 PLINT setpre, precis;
1353 char form[10], temp[30];
1354 double scale2;
1355
1356 plP_gprec(&setpre, &precis);
1357
1358 if (setpre)
1359 prec = precis;
1360
1361 if (scale)
1362 value /= pow(10.,(double)scale);
1363
1364 /* This is necessary to prevent labels like "-0.0" on some systems */
1365
1366 scale2 = pow(10., prec);
1367 value = floor((value * scale2) + .5) / scale2;
1368
1369 sprintf(form, "%%.%df", (int) prec);
1370 sprintf(temp, form, value);
1371 strcpy(string, temp);
1372 }
1373 }
1374