home *** CD-ROM | disk | FTP | other *** search
- /* scale - calculate scaling parameters for plotting so that axes
- have convenient labels
- */
-
- #include <stdio.h>
- #include <math.h>
- #include "g.h"
- #include "g3.h"
- #include "graph.h"
-
- /*
- #define xxxx
- #define xxx
- #define xx
- */
-
- #define NTIC 30.
- #define minimum(x, y) (((x) < (y))?(x):(y))
- #define maximum(x, y) (((x) > (y))?(x):(y))
- #define power(x, y) (exp(log(x)*(y)))
-
- /* local functions */
- static MODEL exptext( int flag, char *buf );
- static double MODEL adjust( char *fmt, double x1, double x2, int nlx );
- static MODEL scale_one ( double amin, double amax, double *bmin,
- double *bmax, int lab_requested, int tic_requested,
- int *nlab, int *ntic, int kind );
-
- #ifdef xxx
-
- static int used[4][4] = { {0, 0, 0, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}
- };
- #endif
-
- static double decide[4][3] ={ {1.414, 3.162, 7.071 },
- {1.414, 1.414, 1.414 },
- {2.236, 2.236, 2.236 },
- {1.414, 3.162, 7.071 }
- };
- static int mtic[4][4] = { {1, 2, 5, 10},
- {1, 2, 2, 2},
- {1, 5, 5, 5},
- {1, 2, 5, 10}
- };
- static double x1; /* minimum x value */
- static double x2; /* maximum x value */
- static int kx; /* kind of axis...0 for linear, 1 for log */
- static int nlx; /* number of long tic marks */
- static int ntx; /* number of short tic marks */
- static double y1, y2; /* (similar for y's) */
- static int ky, nly, nty;
-
- scale (amin, amax, rlx, rtx, ka, bmin, bmax, rly, rty, kb)
- double amin, amax, bmin, bmax;
- int ka, kb, rlx, rly;
- {
- #ifdef xxx
- printf("scale: amin = %f amax = %f ka = %d \n", amin, amax, ka);
- #endif
- scale_one(amin, amax, &x1, &x2, rlx, rtx, &nlx, &ntx, ka);
- #ifdef xxx
- printf("scale: x1 = %f x2 = %f nlx = %d ntx = %d \n", x1, x2, nlx, ntx);
- printf("scale: bmin = %f bmax = %f kb = %d \n", bmin, bmax, kb);
- #endif
- scale_one(bmin, bmax, &y1, &y2, rly, rty, &nly, &nty, kb);
- #ifdef xxx
- printf("scale: y1 = %f y2 = %f nly = %d nty = %d \n", y1, y2, nly, nty);
- #endif
- kx = ka; ky = kb;
- window(x1, x2, y1, y2);
- }
-
- static scale_one (amin, amax, bmin, bmax, lab_requested, tic_requested, nlab,
- ntic, kind)
-
- double amin, amax, *bmin, *bmax; int lab_requested, tic_requested,
- *nlab, *ntic, kind;
-
- { double tens, top, bottom, fraction, d, interval;
- int i, j;
-
- if(!kind) /* linear scale */
- {if(amax <= amin) amax = amin + 1.;
- fraction = (amax - amin)/maximum(lab_requested - 1, 1);
- #ifdef xxx
- printf("\nscale_one: fraction = %f", fraction);
- #endif
- tens = power(10., floor(log10(fraction)));
- fraction /= tens;
- for (j = 0; j <= 2; j++) if(fraction < decide[0][j]) break;
- d = mtic[0][j]*tens; /* data increment between labels */
- bottom = floor(amin/d + .002); *bmin = bottom*d;
- top = ceil(amax/d - .002); *bmax = top*d;
- *nlab = (int)(top - bottom + .25); /* # labels */
- interval = tic_requested/ *nlab;
- for (i = 0; i <= 2; i++) if(interval < decide[j][i]) break;
- *ntic = mtic[j][i]* *nlab; /* # tic marks */
- #ifdef xxx
- used[j][i]++;
- printf("(-->%f) ?= d = %f, tens = %f \n", fraction, d, tens);
- printf(" bottom = %f, top = %f, interval = %f \n",
- bottom, top, interval);
- printf("i = %d j = %d bmin = %f bmax = %f \n", i, j, *bmin, *bmax);
- #endif
- }
- else /* log scale */
- {*bmin = floor(amin + .001); *bmax = ceil(amax - .001);
- *nlab = *bmax - *bmin + .1;
- if ((*nlab * 3) > tic_requested) *ntic = *nlab;
- else *ntic = *nlab*9;
- }
- #ifdef xx
- printf("\n scale_one: *bmin=%f *bmax=%f *nlab=%d *ntic=%d kind=%d \n",
- *bmin, *bmax, *nlab, *ntic, kind);
- #endif
- }
-
- /* return scale factor and format for printing nlx labels from x1 to x2 */
- static double adjust(fmt, x1, x2, nlx) char *fmt; double x1, x2; int nlx;
- { double large, a1, a2, adj = 1.;
- int exponent = 0, after; /* "after" is # digits needed after decimal */
- a1 = fabs(x1);
- a2 = fabs(x2);
- large = (a1 > a2)?a1:a2;
- if(large < .01)
- while(large*adj < 1.) {adj *= 1000.; exponent -= 3;}
- if(large*adj > 10000.)
- while(large*adj > 1000.) {adj /= 1000.; exponent += 3;}
- after = ceil(-log10((x2*adj - x1*adj)/nlx) - .01);
- if(after < 0) after = 0;
- if(exponent)
- {sprintf(fmt, "%%%d.%dfe%d", after, after, exponent);
- }
- else
- {sprintf(fmt, "%%%d.%df", after, after);
- }
- return (adj);
- }
-
- static double segl[9] = {.301, .176, .125, .097, .079, .067, .058, .051, .046};
- static double ch; /* height of a character (world coordinates) */
- static double cw; /* width of a character (world coordinates) */
-
- axis(numbers, grid_style, grid_width, width_used, height_used)
- int numbers, grid_style, grid_width;
- double width_used, height_used;
- { int i, j, after;
- double adj = 1., tic, t1, t11, e1, t2, t22, e2, s, x, y, y0, yval, dely,
- offset;
- static double wx1, wx2, wy1, wy2; /* window limits (world coordinates) */
- static double vx1, vx2, vy1, vy2; /* viewport limits */
- char buf[80], format[80];
-
- if(grid_style == 0) return;
- clip_window(0);
- if(grid_width < 1) grid_width = 1;
- else if(grid_width > 9) grid_width = 9;
- set_linewidth(grid_width);
- inquire_window(&wx1, &wx2, &wy1, &wy2);
- inquire_viewport_2(&vx1, &vx2, &vy1, &vy2);
- /*
- W1 = pixels_wide*(vx2-vx1)/best_width is the width of
- the viewport in pixels. W2 = char_width/W1 is the
- width of a character as a fraction of the viewport
- width. cw = W2*(wx2-wx1) is the width of a
- character in user units.
- */
- cw = (wx2 - wx1)*best_width/(vx2 - vx1)*char_width/(double)pixels_wide;
- ch = (wy2 - wy1)*best_height/(vy2 - vy1)*char_height/(double)pixels_high;
- tic = .01*sqrt(width_used*width_used + height_used*height_used);
- t1 = tic/width_used*(x2 - x1); /* length of small horizontal tic mark */
- e1 = t1*.0000001; /* invisibly small horizontal distance */
- x1 += e1; x2 -= e1;
- t2 = tic/height_used*(y2 - y1);
- e2 = t2*.0000001; /* invisibly small vertical distance */
- y1 += e2; y2 -= e2;
- if(grid_style < 0 && grid_style != -2) /* tics on outside */
- {t1 = -t1; t2 = -t2;
- }
- t11 = t1*2.; t22 = t2*2.; /* length of long tic mark */
- if(abs(grid_style) == 2) {t11 = x2 - x1; t22 = 0.;} /* full grid */
- y_axis(y1, y2, ky, nly, nty, x1, t1, t11, grid_style); /* left */
- if(abs(grid_style) < 3)
- x_axis(x1, x2, kx, nlx, ntx, y2, -t2, -t22, grid_style); /* top */
- if(abs(grid_style) == 2) {t11 = 0.; t22 = y2 - y1;}
- x_axis(x1, x2, kx, nlx, ntx, y1, t2, t22, grid_style); /* bottom */
- if(abs(grid_style) < 3)
- y_axis(y1, y2, ky, nly, nty, x2, -t1, -t11, grid_style); /* right */
- if(numbers)
- {if(!ky) adj = adjust(format, y1, y2, nly);
- x = x1;
- if(grid_style < 0 && grid_style != -2) x += t11;
- if(grid_style == 4) x -= 3.*t1;
- else if(grid_style == -4) x += t1;
- yval = y2;
- dely = (y2 - y1)/nly;
- y = y0 = y2 - .4*ch;
- if(char_v_adjusted && !plotting_device && grid_style > 0)
- {y -= .6*ch; /* stay within screen */
- if(ky) y -= .4*ch; /* allow for superscripts */
- }
- for(i = 0; i <= nly; i++) /* label y axis */
- {if(ky) sprintf(buf, "1e%1.0f", yval);
- else sprintf(buf, format, yval*adj);
- move_abs_2(x - cw*(1. + strlen(buf)), y);
- exptext(ky, buf);
- y = y0 - dely*(i + 1); yval -= (y2 - y1)/nly;
- }
-
- if(!kx) adj = adjust(format, x1, x2, nlx);
- x = x1; y = y1 - (kx?1.6:1.3)*ch;
- if(grid_style < 0 && grid_style != -2) y += t22;
- if(grid_style == 4) y -= 3.*t2;
- else if(grid_style == -4) y += t2;
- offset = .5;
- for(i = 0; i <= nlx; i++) /* label x axis */
- {if(kx) sprintf(buf, "1e%1.0f", x);
- else sprintf(buf, format, x*adj);
- if(i == nlx && !plotting_device)
- offset = 1.; /* on screen, offset label for clearance */
- move_abs_2(x - cw*offset*strlen(buf), y);
- exptext(kx, buf);
- x += (x2 - x1)/nlx;
- }
- }
- clip_window(1);
- }
-
- static exptext(flag, buf) int flag; char *buf;
- { if(flag && char_v_adjusted)
- {text("10");
- move_rel_2(cw*2.,ch*.4);
- buf += 2;
- }
- text(buf);
- }
-
- static x_axis(x, x2, kx, nlx, ntx, y, t, tlarge, grid_style)
- double x, x2, /* beginning and ending x locations */
- y, /* y location of axis */
- t, /* y displacement for small tic marks */
- tlarge; /* y displacement for large tic marks */
- int kx, /* nonzero for log axis */
- nlx, /* # large tic marks */
- ntx, /* # small tic marks */
- grid_style; /* 1 = frame with tic marks inside (default)
- -1 = frame with tic marks outside the graph area
- 2 = full grid
- 3 = bottom and left axes only
- -3 = bottom and left axes, tic marks on outside
- 4 = separated bottom and left axes only
- -4 = separated bottom and left axes, tic marks on outside
- */
- { int i, j; double s;
-
- if(grid_style == 4) y -= 3.*t;
- else if(grid_style == -4) y += t;
-
- /* display 1st large tic mark */
- if(grid_style < 0 || grid_style > 3)
- {move_abs_2(x, y + tlarge);
- line_abs_2(x, y);
- }
- else move_abs_2(x, y);
- if(kx) /* log axis */
- {s = (x2 - x)/nlx;
- for ( i = nlx ; i ; i-- )
- {if(ntx > nlx)
- {for ( j = 0 ; j < 9 ; j++ )
- {if(plotting_device)
- line_abs_2(x, y);
- else
- move_abs_2(x, y);
- line_abs_2(x += s*segl[j], y);
- line_abs_2(x, y + t);
- }
- line_abs_2(x, y + tlarge);
- }
- else
- {if(plotting_device)
- line_abs_2(x, y);
- else
- move_abs_2(x, y);
- line_abs_2(x += s, y);
- line_abs_2(x, y + tlarge);
- }
- }
- }
- else /* linear axis */
- {s = (x2 - x)/ntx;
- for( i = nlx ; i ; i-- )
- {for ( j = ntx/nlx ; j > 0 ; j-- )
- {if(plotting_device)
- line_abs_2(x, y);
- else
- move_abs_2(x, y);
- line_abs_2(x += s, y);
- line_abs_2(x, y + t);
- }
- line_abs_2(x, y + tlarge);
- }
- }
- }
-
- static y_axis(y, y2, ky, nly, nty, x, t, tlarge, grid_style)
- double y, y2, /* beginning and ending y locations */
- x, /* x location of axis */
- t, /* x displacement for small tic marks */
- tlarge; /* x displacement for large tic marks */
- int ky, /* nonzero for log axis */
- nly, /* # large tic marks */
- nty, /* # small tic marks */
- grid_style; /* 1 = frame with tic marks inside (default),
- -1 = frame with tic marks outside the graph area,
- 2 = full grid
- 3 = bottom and left axes only
- -3 = bottom and left axes, tic marks on outside.
- 4 = separated bottom and left axes only
- -4 = separated bottom and left axes, tic marks on outside.
- */
- { int i,j; double s;
-
- if(grid_style == 4) x -= 3.*t;
- else if(grid_style == -4) x += t;
-
- if(grid_style < 0 || grid_style > 3)
- {move_abs_2(x + tlarge, y);
- line_abs_2(x, y);
- }
- else move_abs_2(x, y);
- move_abs_2(x, y);
- if(ky) /* log axis */
- {s = (y2 - y)/nly;
- for ( i = nly ; i ; i-- )
- {if(nty > nly)
- {for ( j = 0 ; j < 9 ; j++ )
- {if(plotting_device)
- line_abs_2(x, y);
- else
- move_abs_2(x, y);
- line_abs_2(x, y += s*segl[j]);
- line_abs_2(x + t, y);
- }
- line_abs_2(x + tlarge, y);
- }
- else
- {if(plotting_device)
- line_abs_2(x, y);
- else
- move_abs_2(x, y);
- line_abs_2(x, y += s);
- line_abs_2(x + tlarge, y);
- }
- }
- }
- else /* linear axis */
- {s = (y2 - y)/nty;
- for( i = nly ; i ; i-- )
- {for ( j = nty/nly ; j > 0 ; j-- )
- {if(plotting_device)
- line_abs_2(x, y);
- else
- move_abs_2(x, y);
- line_abs_2(x, y += s);
- line_abs_2(x + t, y);
- }
- line_abs_2(x + tlarge, y);
- }
- }
- }
-
- #ifdef xxxx
-
- /* illustrate a lot of labeled axes */
- main()
- { double lower, upper, delt, span;
- int nlab, ntic, i, j;
-
- initialize_core(1);
- initialize_view_surface(1);
- ndc_space_2(1., .8);
- /* viewport2(.1, 1., .1, .8); */
- clip_window(1);
- delt = power(10., 0.1);
- lower = -5.;
- for (i = 4; i; i--)
- {span = 1.;
- for (j = 11; j; j--)
- {new_frame();
- /* generate the figure */
- upper = lower + span;
- /**** old calling sequence *****/
- scale(lower, upper, 2, lower, upper, 2);
- create_temporary_segment();
- axis();
- printf("\n lower = %10.4f...upper = %10.4f \n",
- lower, upper);
- close_temporary_segment();
- span *= delt;
- getchar();
- }
- lower += 3.;
- }
- printf("mtic[][]...\n");
- for(j = 0; j < 4; j++)
- {for(i = 0; i < 4; i++) printf("%4d", mtic[j][i]);
- printf("\n");
- }
- printf("usage of cells of mtic[][]...\n");
- for(j = 0; j < 4; j++)
- {for(i = 0; i < 4; i++) printf("%4d", used[j][i]);
- printf("\n");
- }
- }
-
- #endif
-
-
- #ifdef FORMATS
-
- /* illustrate the formats generated by adjust() for numeric axis labels */
- main()
- { char format[80], s1[30], s2[30], s3[30], s4[30];
- double x, x0 = .000001, adj;
- int i;
-
- for (i = 0; i < 2; i++)
- {for (x = x0; x < 1.e6; x *= 10.)
- {adj = adjust(format, x/5, x, 5);
- sprintf(s1, format, x/5*adj);
- sprintf(s2, format, x*adj);
- adj = adjust(format, x/10, x, 10);
- sprintf(s3, format, x/10*adj);
- sprintf(s4, format, x*adj);
- printf("%8s ...%8s %8s ...%8s\n", s1, s2, s3, s4);
- }
- x0 *= 3.;
- }
- }
- #endif
-