home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
d
/
dots151.zip
/
GRAPHSRC.ZIP
/
SCALE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-04-19
|
13KB
|
444 lines
/* 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