home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
gle
/
gle
/
axis.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-29
|
13KB
|
474 lines
#include "all.h"
#include "justify.h"
#include "axis.h"
#include <math.h>
#include "mygraph.h"
int start_subtick(double *tick1, double gmin, double dticks);
int nice_ticks(double *dticks, double *gmin,double *gmax
, double *t1,double *tn,int minset, int maxset);
int numtrim(char **d,char *s, double dticks);
int nice_log_ticks(double *start, double *last, double *gmin, double *gmax);
double fnloglen(double v,struct axis_struct *ax);
double fnlogx(double v,struct axis_struct *ax);
int fnbig(double v);
#define fnx(vv) (((vv-gmin)/(gmax-gmin)) * ax->length)
#define fnlx(vv) fnlogx(vv,ax)
#define true (!false)
#define false 0
struct axis_struct ax;
#define kw(ss) if (strcmp(tok(ct),ss)==0)
draw_axis(struct axis_struct *ax) /* Draws the axis */
{
double fi,x,y,gmin,gmax,dticks,tick1,tickn;
int i,xax,n,savecap,dolittle;
int isbig;
double tlen,stlen,dsubticks,tt,t,start;
double h,label_width,dist;
double bl,br,bu,bd;
double ox,oy,llen,maxd,maxwid,ty,tx;
double th;
if (ax->type==1 || ax->type==3) xax = true; else xax = false;
g_source("BEGIN AXIS =====\n");
/*! Return if side is turned OFF*/
if (ax->off) return ;
#define dont if (1==2)
/*! Ok lets draw the side first. */
g_get_line_cap(&savecap);
g_get_xy(&ox,&oy);
g_gsave();
g_set_color(ax->side_color);
g_set_line_width(ax->side_lwidth);
g_set_line_style(ax->side_lstyle);
if (!ax->side_off) {
g_set_line_cap(1);
g_get_xy(&x,&y);
if (xax)
g_line(x+ax->length,y);
else
g_line(x,y+ax->length);
}
g_grestore();
g_set_line_cap(savecap);
/*----------------------------- Generate the places for labels to go */
gmin = ax->min;
gmax = ax->max;
if (ax->log) { /* generate places for log main ticks */
if (!ax->lgset) {
/* dist between 10^0 and 10^1 */
dist = fnloglen(2,ax) - fnloglen(1,ax);
if (dist > ax->base*4.5) ax->lg25 = true;
if (dist > ax->base*22.0) ax->lg1 = true;
}
nice_log_ticks(&tick1,&tickn,&gmin,&gmax);
if (ax->nplaces == 0) { /* haven't been set, so generate positions. */
for (fi=tick1; fi<= tickn+(pow(10.0,floor(log10(fi)+.0001)))/100
; fi += pow(10.0,floor(log10(fi)+.0001))) {
i = floor(.0001 + fi/pow(10.0,floor(log10(fi))));
if (fnbig(fi) || (ax->lg1) || (ax->lg25 && ((i==2) || (i==5))) ) {
if (++(ax->nplaces)>199) {gprint("Too many places\n");return;}
ax->places[ax->nplaces] = fi;
}
}
}
} else {
dticks = 0;
if (ax->nticks!=0) dticks = (gmax - gmin)/ax->nticks;
if (ax->dticks!=0) dticks = ax->dticks ;
if (dticks>0) if ((gmax - gmin)/dticks>90) {gprint("too many ticks \n"); dticks = 0;}
nice_ticks(&dticks, &gmin, &gmax, &tick1, &tickn,ax->minset,ax->maxset);
if (ax->nofirst) tick1 = tick1 + dticks;
if (ax->nolast) tickn = tickn - dticks;
tickn = tickn + dticks/100; /* to avoid rounding errors */
if (ax->nplaces == 0) { /* haven't been set, so generate positions. */
{ double end_tick = (tickn+dticks/100.0);
for (fi=tick1; fi<=end_tick; fi += dticks) {
if (++(ax->nplaces)>49) {gprint("Too many places\n");return;}
ax->places[ax->nplaces] = fi;
}
}
}
}
/*------------------------------ Now draw the ticks (subticks first) */
g_gsave();
tlen = ax->base/5;
if (ax->ticks_length!=0) tlen = ax->ticks_length;
/* first the subticks */
stlen = tlen/2;
if (ax->subticks_length!=0) stlen = ax->subticks_length;
dsubticks = 0;
if (!ax->log) { /* Draw little log ticks if enough space */
if (ax->nsubticks!=0) dsubticks = (dticks)/(ax->nsubticks+1);
if (ax->dsubticks!=0) dsubticks = ax->dsubticks;
if (dsubticks==0) dsubticks = dticks / 2.0;
if ((gmax - gmin)/dsubticks>2000) {gprint("too many subticks \n");
dsubticks = dticks;}
start_subtick(&tick1, gmin, dsubticks);
g_set_color(ax->subticks_color);
g_set_line_width(ax->subticks_lwidth);
g_set_line_style(ax->subticks_lstyle);
if (ax->type>2) t = -stlen; else t = stlen;
if (!ax->subticks_off) {
if (dsubticks==0) dsubticks = dticks / 2.0;
for (fi=tick1; fi<=gmax; fi += dsubticks) {
/* if (!fnbig(fi)) { */
if (xax) {
g_move(ox+fnx(fi),oy);
g_line(ox+fnx(fi),oy+t);
} else {
g_move(ox,fnx(fi)+oy);
g_line(ox+t,oy+fnx(fi));
}
/* } */
}
}
}
/*------------------------------ Now the main ticks */
g_set_color(ax->ticks_color);
g_set_line_width(ax->ticks_lwidth);
g_set_line_style(ax->ticks_lstyle);
if (ax->type>2) t = -tlen; else t = tlen;
if (ax->type>2) tt = -stlen; else tt = stlen;
if (!ax->ticks_off) {
if (ax->log) { /* Draw log ticks */
g_set_color(ax->subticks_color);
g_set_line_width(ax->subticks_lwidth);
g_set_line_style(ax->subticks_lstyle);
nice_log_ticks(&tick1,&tickn,&gmin,&gmax);
for (fi=tick1; fi<= tickn+(pow(10.0,floor(log10(fi)+.0001)))/100
; fi += pow(10.0,floor(log10(fi)+.0001))) {
i = floor(fi/pow(10.0,floor(log10(fi))));
isbig = (fnbig(fi));
if (isbig) {
x = t;
g_set_color(ax->ticks_color);
g_set_line_width(ax->ticks_lwidth);
g_set_line_style(ax->ticks_lstyle);
} else x = tt;
if (xax) {
g_move(ox+fnlx(fi),oy);
g_line(ox+fnlx(fi),oy+x);
} else {
g_move(ox,fnlx(fi)+oy);
g_line(ox+x,oy+fnlx(fi));
}
if (isbig) {
g_set_color(ax->subticks_color);
g_set_line_width(ax->subticks_lwidth);
g_set_line_style(ax->subticks_lstyle);
}
}
} else {
for (i=1;i<=ax->nplaces; i++) {
fi = ax->places[i];
if (xax) {
g_move(ox+fnx(fi),oy);
g_line(ox+fnx(fi),oy+t);
} else {
g_move(ox,fnx(fi)+oy);
g_line(ox+t,oy+fnx(fi));
}
}
}
}
g_grestore();
/*------------------------------ Now draw the labels */
llen = 0;
if (tlen<0) llen = -tlen;
h = ax->label_hei;
if (h==0) h = ax->base;
llen = llen + h*.5;
if (ax->label_dist!=0) llen = ax->label_dist;
{char cbuff[100];
if (ax->nnam==0) {
if (ax->log) {
if (log10(gmax)-log10(gmin) < 5) dolittle = true;
else dolittle = false;
for (i=1;i<=ax->nplaces; i++) {
fi = ax->places[i];
n = floor(.0001 + fi/pow(10.0,floor(log10(fi))));
if (fnbig(fi)) {
n = floor(log10(fi)+.5);
sprintf(cbuff,"10\\sup {%d}",n);
mystrcpy(&ax->names[i],cbuff);
} else {
if (dolittle) {
n = floor(.0001 + fi/(pow(10.0,floor(log10(fi)))));
sprintf(cbuff,"{\\sethei{%g}%d}",h*.7,n);
mystrcpy(&ax->names[i],cbuff);
}
}
}
ax->nnam = ax->nplaces;
} else {
for (i=1;i<=ax->nplaces; i++) {
fi = ax->places[i];
x = fabs(fi);
if (x<.00001*dticks) {fi = 0; x = 0;}
if (ax->decimal>0) {
sprintf(cbuff,"%.*f",ax->decimal,fi);
ax->names[i] = myallocz(20);
strncpy(ax->names[i],cbuff,19);
} else {
if (fi==0 || (x>1e-5 && x<1e6)) sprintf(cbuff,"%f",fi);
else sprintf(cbuff,"%e",fi);
numtrim(&ax->names[i],cbuff,dticks);
}
}
ax->nnam = ax->nplaces;
}
}}
g_set_color(ax->label_color);
g_set_line_width(ax->label_lwidth);
g_set_line_style(ax->label_lstyle);
g_set_font(ax->label_font);
g_set_hei(h);
maxd = 0;
maxwid = 0;
tx = ox-.3*h; /* I wonder what tx should be set to ??? */
if (ax->type==4) tx = ox + .3*h;
if (ax->type==1) ty = oy-llen-.3*h;
if (ax->type==3) ty = oy+llen;
if (!ax->label_off) {
for (i=1;i<=ax->nnam;i++) {
g_measure(ax->names[i],&bl,&br,&bu,&bd);
if (bd>maxd) maxd = bd;
if (bl+br>maxwid) maxwid = bl+br;
}
for (i=1;i<=ax->nnam;i++) {
g_measure(ax->names[i], &bl, &br,&bu,&bd);
fi = fnx(ax->places[i]);
if (ax->log) fi = fnlx(ax->places[i]);
switch (ax->type) {
case 1: /* xaxis */
y = oy-llen-bu+bd-.3*h;
if (y<ty) ty = y;
g_move(ox+fi+ax->shift,oy-llen-(.7*h) );
g_jtext(JUST_CENTRE);
break;
case 2: /* yaxis */
x = ox-br+bl-llen-.3*h;
/* bug here with axis labels 0 10 20, nofirst */
if (i!=1 && i!=ax->nnam) if (x<tx) tx = x;
g_move(ox -llen ,oy+fi+ax->shift);
g_jtext(JUST_RC);
break;
case 3: /* x2axis */
y = oy+llen+maxd+bu;
if (y>ty) ty = y;
g_move(ox+fi+ax->shift,oy+llen+maxd);
g_jtext(JUST_CENTRE);
break;
case 4: /* y2axis */
x = ox+br-bl+llen+.3*h;
if (i!=1 && i!=ax->nnam) if (x>tx) tx = x;
g_move(ox+llen ,oy + fi +ax->shift);
g_jtext(JUST_LC);
break;
}
if (bd>maxd) maxd = bd;
if (bl+br>maxwid) maxwid = bl+br;
}
}
/*---------------------------------- Now the axis title. */
if (ax->title==NULL) return;
g_gsave();
th = h * 1.3;
if (ax->title_scale!=0) th = th*ax->title_scale ;
if (ax->title_hei!=0) th = ax->title_hei ;
g_set_color(ax->title_color);
g_set_font(ax->title_font);
g_set_hei(th);
g_measure(ax->title,&bl,&br,&bu,&bd);
if (!ax->title_off) {
switch (ax->type) {
case 1: /* xaxis */
g_move(ox+ax->length/2,ty - ax->title_dist);
g_jtext(JUST_TC);
break;
case 2: /* yaxis */
g_move(tx - ax->title_dist,oy + ax->length/2);
g_rotate(90.0);
g_jtext(JUST_BC);
g_rotate(-90.0);
break;
case 3: /* x2axis */
g_move(ox+ax->length/2,ty + ax->title_dist);
g_jtext(JUST_BC);
break;
case 4: /* y2axis */
g_move(tx + ax->title_dist,oy + ax->length/2);
if (ax->title_rot) {
g_rotate(-90.0);
g_jtext(JUST_BC);
g_rotate(90.0);
} else {
g_rotate(90.0);
g_jtext(JUST_TC);
g_rotate(-90.0);
}
break;
}
}
g_grestore();
g_move(ox,oy);
g_source("END AXIS ===== \n");
}
/*-------------------------------------------------------------------------*/
nice_ticks(double *dticks, double *gmin,double *gmax
, double *t1,double *tn,int minset, int maxset)
{
double delta,st,expnt,n;
int ni;
/* GMIN AND GMAX are set in GRAPH2.C in setrange() */
/* printf("nice %g %g %g \n",*gmin,*gmax,*dticks); */
delta = *gmax-*gmin;
if (delta==0) {gprint("Axis range error min=%g max=%g \n",*gmin,*gmax);
*gmax = *gmin+10;
delta = 10;
}
st = delta/10;
expnt = floor(log10(st));
n = st/pow(10,expnt);
if (n>5)
ni = 10;
else if (n>2)
ni = 5;
else if (n>1)
ni = 2;
else
ni = 1;
if (*dticks==0) *dticks = ni * pow(10,expnt);
if (*gmin - (delta/1000) <= floor( *gmin/ *dticks) * *dticks)
*t1 = *gmin;
else
*t1 = (floor(*gmin/ *dticks) * *dticks ) + *dticks;
*tn = *gmax;
if (( floor( *gmax/ *dticks) * *dticks) < (*gmax - (delta/1000) ))
*tn = floor(*gmax/ *dticks ) * *dticks;
}
/*-------------------------------------------------------------------------*/
double chop(double f);
double chop(double f)
{
return (double) (long) f;
}
/*-------------------------------------------------------------------------*/
start_subtick(double *tick1, double gmin, double dticks)
{
if (gmin == chop(gmin/dticks) * dticks)
*tick1 = gmin;
else
*tick1 = chop(gmin/dticks) * dticks + dticks;
}
/*-------------------------------------------------------------------------*/
numtrime(char *o,char *s)
{
char *nonzero;
char *e,*f;
strcpy(o,s);
e = strchr(s,'e');
if (e==NULL) return;
e--;
for (; *e=='0'; e--) ;
f = strchr(s,'e');
strcpy(e+1,f);
strcpy(o,s);
}
/*-------------------------------------------------------------------------*/
numtrim(char **d,char *s,double dticks)
{
char *o,*nonzero=0;
if (*d==0) *d = myallocz(20);
o = *d;
nonzero = 0;
if (strchr(s,'e')!=NULL) {
numtrime(o,s);
return;
}
while (*s==' ' && *s!=0) s++;
while (*s!=0) {
*(o++) = *(s++);
if (*s=='.') {
nonzero = o-1;
if (dticks!=floor(dticks)) nonzero = o+1;
while (*s!=0) {
*(o++) = *(s++);
if ((*s!='0') && (*s!=0))
if (o>nonzero) nonzero = o;
}
}
}
*(o++) = 0;
if (nonzero!=NULL) *(nonzero+1) = 0;
}
/*-------------------------------------------------------------------------*/
nice_log_ticks(double *start, double *last, double *gmin, double *gmax)
{
double sz;
if (*gmin<=0) {
gprint("FATAL ERROR, LOG AXIS WITH MIN OF ZERO***\n");
*gmin = 1;
}
if (*gmax<=0) *gmax = 10;
*start = pow(10.0,floor(log10(*gmin)));
if (floor(log10(*gmin)) != log10(*gmin)) {
sz = pow(10.0,floor(log10(*gmin)));
*start = floor((*gmin)/sz)*sz + sz;
if (*start>(*gmin+sz-sz/100)) *start = *start - sz;
}
*last = floor(log10(*gmax))+1;
if (floor(log10(*gmax))==log10(*gmax)) {
--*last;
*last = pow(10.0,*last);
} else {
*last = pow(10.0,*last-1);
*last = floor((*gmax) / *last) * *last;
}
}
double fnloglen(double v,struct axis_struct *ax) /* Dist in cm in log axis */
{
return ((v-log10(ax->min))/(log10(ax->max)-log10(ax->min))) * ax->length;
}
double fnlogx(double v,struct axis_struct *ax)
{
return fnloglen(log10(v),ax);
}
fnbig(double v)
{
if (fabs(log10(v)-floor(log10(v)+.5)) < .001)
return true;
else return false;
}