home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / gle / gle / axis.c < prev    next >
C/C++ Source or Header  |  1992-11-29  |  13KB  |  474 lines

  1. #include "all.h"
  2.  
  3. #include "justify.h"
  4. #include "axis.h"
  5. #include <math.h>
  6. #include "mygraph.h"
  7. int start_subtick(double *tick1, double gmin, double dticks);
  8. int nice_ticks(double *dticks, double *gmin,double *gmax
  9.     , double *t1,double *tn,int minset, int maxset);
  10. int numtrim(char **d,char *s, double dticks);
  11.  
  12. int nice_log_ticks(double *start, double *last, double *gmin, double *gmax);
  13. double fnloglen(double v,struct axis_struct *ax);
  14. double fnlogx(double v,struct axis_struct *ax);
  15. int fnbig(double v);
  16.  
  17. #define fnx(vv)  (((vv-gmin)/(gmax-gmin)) * ax->length)
  18. #define fnlx(vv) fnlogx(vv,ax)
  19. #define true (!false)
  20. #define false 0
  21. struct axis_struct ax;
  22.  
  23. #define kw(ss) if (strcmp(tok(ct),ss)==0)
  24.  
  25. draw_axis(struct axis_struct *ax)    /* Draws the axis */
  26. {
  27.     double fi,x,y,gmin,gmax,dticks,tick1,tickn;
  28.     int i,xax,n,savecap,dolittle;
  29.        int isbig;
  30.     double tlen,stlen,dsubticks,tt,t,start;
  31.     double h,label_width,dist;
  32.     double bl,br,bu,bd;
  33.     double ox,oy,llen,maxd,maxwid,ty,tx;
  34.     double th;
  35.  
  36.     if (ax->type==1 || ax->type==3) xax = true; else xax = false;
  37.     g_source("BEGIN AXIS  =====\n");
  38. /*! Return if side is turned OFF*/
  39.     if (ax->off) return ;
  40. #define dont if (1==2)
  41. /*! Ok lets draw the side first. */
  42.     g_get_line_cap(&savecap);
  43.     g_get_xy(&ox,&oy);
  44.     g_gsave();
  45.     g_set_color(ax->side_color);
  46.     g_set_line_width(ax->side_lwidth);
  47.     g_set_line_style(ax->side_lstyle);
  48.     if (!ax->side_off) {
  49.         g_set_line_cap(1);
  50.         g_get_xy(&x,&y);
  51.         if (xax)
  52.             g_line(x+ax->length,y);
  53.         else
  54.             g_line(x,y+ax->length);
  55.     }
  56.     g_grestore();
  57.     g_set_line_cap(savecap);
  58.  
  59. /*----------------------------- Generate the places for labels to go */
  60.     gmin = ax->min;
  61.     gmax = ax->max;
  62.  
  63.     if (ax->log) {    /* generate places for log main ticks */
  64.      if (!ax->lgset) {
  65.         /* dist between 10^0 and 10^1 */
  66.         dist = fnloglen(2,ax) - fnloglen(1,ax);
  67.         if (dist > ax->base*4.5) ax->lg25 = true;
  68.         if (dist > ax->base*22.0) ax->lg1 = true;
  69.      }
  70.      nice_log_ticks(&tick1,&tickn,&gmin,&gmax);
  71.      if (ax->nplaces == 0) { /* haven't been set, so generate positions. */
  72.       for (fi=tick1; fi<= tickn+(pow(10.0,floor(log10(fi)+.0001)))/100
  73.             ; fi += pow(10.0,floor(log10(fi)+.0001))) {
  74.         i = floor(.0001 + fi/pow(10.0,floor(log10(fi))));
  75.         if (fnbig(fi) || (ax->lg1) || (ax->lg25 && ((i==2) || (i==5))) ) {
  76.          if (++(ax->nplaces)>199) {gprint("Too many places\n");return;}
  77.          ax->places[ax->nplaces] = fi;
  78.         }
  79.       }
  80.      }
  81.     } else {
  82.     dticks = 0;
  83.     if (ax->nticks!=0)  dticks = (gmax - gmin)/ax->nticks;
  84.     if (ax->dticks!=0)  dticks = ax->dticks ;
  85.     if (dticks>0) if ((gmax - gmin)/dticks>90) {gprint("too many ticks \n"); dticks = 0;}
  86.  
  87.     nice_ticks(&dticks, &gmin, &gmax, &tick1, &tickn,ax->minset,ax->maxset);
  88.  
  89.     if (ax->nofirst) tick1 = tick1 + dticks;
  90.     if (ax->nolast) tickn = tickn - dticks;
  91.     tickn = tickn + dticks/100; /* to avoid rounding errors */
  92.     if (ax->nplaces == 0) { /* haven't been set, so generate positions. */
  93.       { double end_tick = (tickn+dticks/100.0);
  94.       for (fi=tick1; fi<=end_tick; fi += dticks) {
  95.         if (++(ax->nplaces)>49) {gprint("Too many places\n");return;}
  96.         ax->places[ax->nplaces] = fi;
  97.       }
  98.       }
  99.     }
  100.     }
  101.  
  102. /*------------------------------  Now draw the ticks    (subticks first) */
  103.     g_gsave();
  104.  
  105.     tlen = ax->base/5;
  106.     if (ax->ticks_length!=0) tlen = ax->ticks_length;
  107.     /* first the subticks */
  108.     stlen = tlen/2;
  109.     if (ax->subticks_length!=0) stlen = ax->subticks_length;
  110.     dsubticks = 0;
  111.  
  112.     if (!ax->log) {    /* Draw little log ticks if enough space */
  113.     if (ax->nsubticks!=0)  dsubticks = (dticks)/(ax->nsubticks+1);
  114.     if (ax->dsubticks!=0)  dsubticks = ax->dsubticks;
  115.     if (dsubticks==0) dsubticks = dticks / 2.0;
  116.     if ((gmax - gmin)/dsubticks>2000) {gprint("too many subticks \n");
  117.                         dsubticks = dticks;}
  118.  
  119.     start_subtick(&tick1, gmin, dsubticks);
  120.     g_set_color(ax->subticks_color);
  121.     g_set_line_width(ax->subticks_lwidth);
  122.     g_set_line_style(ax->subticks_lstyle);
  123.     if (ax->type>2) t = -stlen; else t = stlen;
  124.     if (!ax->subticks_off) {
  125.       if (dsubticks==0) dsubticks = dticks / 2.0;
  126.       for (fi=tick1; fi<=gmax; fi += dsubticks) {
  127. /*         if (!fnbig(fi)) { */
  128.         if (xax) {
  129.             g_move(ox+fnx(fi),oy);
  130.             g_line(ox+fnx(fi),oy+t);
  131.         } else {
  132.             g_move(ox,fnx(fi)+oy);
  133.             g_line(ox+t,oy+fnx(fi));
  134.         }
  135. /*        }     */
  136.       }
  137.     }
  138.     }
  139.  
  140. /*------------------------------  Now the main ticks */
  141.     g_set_color(ax->ticks_color);
  142.     g_set_line_width(ax->ticks_lwidth);
  143.     g_set_line_style(ax->ticks_lstyle);
  144.  
  145.     if (ax->type>2) t = -tlen; else t = tlen;
  146.     if (ax->type>2) tt = -stlen; else tt = stlen;
  147.     if (!ax->ticks_off) {
  148.       if (ax->log) {    /* Draw log ticks */
  149.         g_set_color(ax->subticks_color);
  150.         g_set_line_width(ax->subticks_lwidth);
  151.         g_set_line_style(ax->subticks_lstyle);
  152.         nice_log_ticks(&tick1,&tickn,&gmin,&gmax);
  153.         for (fi=tick1; fi<= tickn+(pow(10.0,floor(log10(fi)+.0001)))/100
  154.             ; fi += pow(10.0,floor(log10(fi)+.0001))) {
  155.         i = floor(fi/pow(10.0,floor(log10(fi))));
  156.         isbig = (fnbig(fi));
  157.         if (isbig) {
  158.             x = t;
  159.                 g_set_color(ax->ticks_color);
  160.                 g_set_line_width(ax->ticks_lwidth);
  161.                 g_set_line_style(ax->ticks_lstyle);
  162.         } else x = tt;
  163.         if (xax) {
  164.             g_move(ox+fnlx(fi),oy);
  165.             g_line(ox+fnlx(fi),oy+x);
  166.         } else {
  167.             g_move(ox,fnlx(fi)+oy);
  168.             g_line(ox+x,oy+fnlx(fi));
  169.         }
  170.         if (isbig) {
  171.                 g_set_color(ax->subticks_color);
  172.                 g_set_line_width(ax->subticks_lwidth);
  173.                 g_set_line_style(ax->subticks_lstyle);
  174.         }
  175.         }
  176.       } else {
  177.         for (i=1;i<=ax->nplaces; i++) {
  178.         fi = ax->places[i];
  179.         if (xax) {
  180.             g_move(ox+fnx(fi),oy);
  181.             g_line(ox+fnx(fi),oy+t);
  182.         } else {
  183.             g_move(ox,fnx(fi)+oy);
  184.             g_line(ox+t,oy+fnx(fi));
  185.         }
  186.         }
  187.       }
  188.     }
  189.     g_grestore();
  190. /*------------------------------  Now draw the labels     */
  191.     llen = 0;
  192.     if (tlen<0) llen = -tlen;
  193.     h = ax->label_hei;
  194.     if (h==0) h = ax->base;
  195.     llen = llen + h*.5;
  196.     if (ax->label_dist!=0) llen = ax->label_dist;
  197.  
  198.     {char cbuff[100];
  199.     if (ax->nnam==0) {
  200.       if (ax->log) {
  201.         if (log10(gmax)-log10(gmin) < 5) dolittle = true;
  202.         else dolittle = false;
  203.         for (i=1;i<=ax->nplaces; i++) {
  204.         fi = ax->places[i];
  205.         n = floor(.0001 + fi/pow(10.0,floor(log10(fi))));
  206.         if (fnbig(fi)) {
  207.             n = floor(log10(fi)+.5);
  208.             sprintf(cbuff,"10\\sup {%d}",n);
  209.             mystrcpy(&ax->names[i],cbuff);
  210.         } else {
  211.           if (dolittle) {
  212.             n = floor(.0001 + fi/(pow(10.0,floor(log10(fi)))));
  213.             sprintf(cbuff,"{\\sethei{%g}%d}",h*.7,n);
  214.             mystrcpy(&ax->names[i],cbuff);
  215.           }
  216.         }
  217.         }
  218.         ax->nnam = ax->nplaces;
  219.       } else {
  220.         for (i=1;i<=ax->nplaces; i++) {
  221.         fi = ax->places[i];
  222.         x = fabs(fi);
  223.         if (x<.00001*dticks) {fi = 0; x = 0;}
  224.         if (ax->decimal>0) {
  225.             sprintf(cbuff,"%.*f",ax->decimal,fi);
  226.             ax->names[i] = myallocz(20);
  227.             strncpy(ax->names[i],cbuff,19);
  228.         } else {
  229.             if (fi==0 || (x>1e-5 && x<1e6)) sprintf(cbuff,"%f",fi);
  230.             else sprintf(cbuff,"%e",fi);
  231.             numtrim(&ax->names[i],cbuff,dticks);
  232.         }
  233.         }
  234.         ax->nnam = ax->nplaces;
  235.       }
  236.     }}
  237.     g_set_color(ax->label_color);
  238.     g_set_line_width(ax->label_lwidth);
  239.     g_set_line_style(ax->label_lstyle);
  240.     g_set_font(ax->label_font);
  241.     g_set_hei(h);
  242.     maxd = 0;
  243.     maxwid = 0;
  244.     tx = ox-.3*h;   /* I wonder what tx should be set to ??? */
  245.      if (ax->type==4) tx = ox + .3*h;
  246.     if (ax->type==1) ty = oy-llen-.3*h;
  247.     if (ax->type==3) ty = oy+llen;
  248.     if (!ax->label_off) {
  249.       for (i=1;i<=ax->nnam;i++) {
  250.         g_measure(ax->names[i],&bl,&br,&bu,&bd);
  251.         if (bd>maxd) maxd = bd;
  252.         if (bl+br>maxwid) maxwid = bl+br;
  253.       }
  254.       for (i=1;i<=ax->nnam;i++) {
  255.         g_measure(ax->names[i], &bl, &br,&bu,&bd);
  256.         fi = fnx(ax->places[i]);
  257.         if (ax->log) fi = fnlx(ax->places[i]);
  258.         switch (ax->type) {
  259.           case 1: /* xaxis */
  260.             y = oy-llen-bu+bd-.3*h;
  261.             if (y<ty) ty = y;
  262.             g_move(ox+fi+ax->shift,oy-llen-(.7*h) );
  263.             g_jtext(JUST_CENTRE);
  264.             break;
  265.           case 2: /* yaxis */
  266.             x = ox-br+bl-llen-.3*h;
  267. /* bug here with axis labels 0 10 20, nofirst  */
  268.             if (i!=1 && i!=ax->nnam) if (x<tx) tx = x;
  269.             g_move(ox -llen ,oy+fi+ax->shift);
  270.             g_jtext(JUST_RC);
  271.             break;
  272.           case 3: /* x2axis */
  273.             y = oy+llen+maxd+bu;
  274.             if (y>ty) ty = y;
  275.             g_move(ox+fi+ax->shift,oy+llen+maxd);
  276.             g_jtext(JUST_CENTRE);
  277.             break;
  278.           case 4: /* y2axis */
  279.             x = ox+br-bl+llen+.3*h;
  280.             if (i!=1 && i!=ax->nnam) if (x>tx) tx = x;
  281.             g_move(ox+llen ,oy + fi +ax->shift);
  282.             g_jtext(JUST_LC);
  283.             break;
  284.         }
  285.         if (bd>maxd) maxd = bd;
  286.         if (bl+br>maxwid) maxwid = bl+br;
  287.       }
  288.     }
  289. /*---------------------------------- Now the axis title. */
  290.  
  291.     if (ax->title==NULL) return;
  292.     g_gsave();
  293.     th = h * 1.3;
  294.     if (ax->title_scale!=0) th = th*ax->title_scale ;
  295.     if (ax->title_hei!=0) th = ax->title_hei ;
  296.     g_set_color(ax->title_color);
  297.     g_set_font(ax->title_font);
  298.     g_set_hei(th);
  299.     g_measure(ax->title,&bl,&br,&bu,&bd);
  300.     if (!ax->title_off) {
  301.       switch (ax->type) {
  302.         case 1: /*  xaxis   */
  303.         g_move(ox+ax->length/2,ty - ax->title_dist);
  304.         g_jtext(JUST_TC);
  305.         break;
  306.         case 2: /*  yaxis   */
  307.         g_move(tx - ax->title_dist,oy + ax->length/2);
  308.         g_rotate(90.0);
  309.         g_jtext(JUST_BC);
  310.         g_rotate(-90.0);
  311.         break;
  312.         case 3: /*  x2axis   */
  313.         g_move(ox+ax->length/2,ty + ax->title_dist);
  314.         g_jtext(JUST_BC);
  315.         break;
  316.         case 4: /*  y2axis   */
  317.         g_move(tx + ax->title_dist,oy + ax->length/2);
  318.         if (ax->title_rot) {
  319.             g_rotate(-90.0);
  320.             g_jtext(JUST_BC);
  321.             g_rotate(90.0);
  322.         } else {
  323.             g_rotate(90.0);
  324.             g_jtext(JUST_TC);
  325.             g_rotate(-90.0);
  326.         }
  327.         break;
  328.       }
  329.     }
  330.     g_grestore();
  331.     g_move(ox,oy);
  332.     g_source("END AXIS  ===== \n");
  333. }
  334. /*-------------------------------------------------------------------------*/
  335. nice_ticks(double *dticks, double *gmin,double *gmax
  336.     , double *t1,double *tn,int minset, int maxset)
  337. {
  338.     double delta,st,expnt,n;
  339.     int ni;
  340.  
  341. /*      GMIN AND GMAX are set in GRAPH2.C in setrange()     */
  342. /*    printf("nice  %g %g %g \n",*gmin,*gmax,*dticks); */
  343.     delta = *gmax-*gmin;
  344.     if (delta==0) {gprint("Axis range error min=%g max=%g \n",*gmin,*gmax);
  345.         *gmax = *gmin+10;
  346.         delta = 10;
  347.     }
  348.     st = delta/10;
  349.     expnt = floor(log10(st));
  350.     n = st/pow(10,expnt);
  351.     if (n>5)
  352.         ni = 10;
  353.     else if (n>2)
  354.         ni = 5;
  355.     else if (n>1)
  356.         ni = 2;
  357.     else
  358.         ni = 1;
  359.     if (*dticks==0) *dticks = ni * pow(10,expnt);
  360.     if (*gmin - (delta/1000) <=  floor( *gmin/ *dticks) * *dticks)
  361.         *t1 = *gmin;
  362.     else
  363.         *t1 = (floor(*gmin/ *dticks) * *dticks ) + *dticks;
  364.  
  365.     *tn = *gmax;
  366.     if (( floor( *gmax/ *dticks) * *dticks) < (*gmax - (delta/1000) ))
  367.         *tn = floor(*gmax/ *dticks ) * *dticks;
  368. }
  369. /*-------------------------------------------------------------------------*/
  370. double chop(double f);
  371. double chop(double f)
  372. {
  373.     return (double) (long) f;
  374. }
  375. /*-------------------------------------------------------------------------*/
  376. start_subtick(double *tick1, double gmin, double dticks)
  377. {
  378.     if (gmin == chop(gmin/dticks) * dticks)
  379.         *tick1 = gmin;
  380.     else
  381.         *tick1 = chop(gmin/dticks) * dticks + dticks;
  382. }
  383. /*-------------------------------------------------------------------------*/
  384. numtrime(char *o,char *s)
  385. {
  386.     char *nonzero;
  387.     char *e,*f;
  388.  
  389.     strcpy(o,s);
  390.  
  391.     e = strchr(s,'e');
  392.     if (e==NULL) return;
  393.  
  394.     e--;
  395.     for (; *e=='0'; e--) ;
  396.  
  397.     f = strchr(s,'e');
  398.     strcpy(e+1,f);
  399.     strcpy(o,s);
  400.  
  401. }
  402. /*-------------------------------------------------------------------------*/
  403. numtrim(char **d,char *s,double dticks)
  404. {
  405.     char *o,*nonzero=0;
  406.  
  407.     if (*d==0)  *d = myallocz(20);
  408.     o = *d;
  409.     nonzero = 0;
  410.     if (strchr(s,'e')!=NULL) {
  411.         numtrime(o,s);
  412.         return;
  413.     }
  414.     while (*s==' ' && *s!=0) s++;
  415.     while (*s!=0) {
  416.         *(o++) = *(s++);
  417.         if (*s=='.') {
  418.             nonzero = o-1;
  419.             if (dticks!=floor(dticks)) nonzero = o+1;
  420.             while (*s!=0) {
  421.                 *(o++) = *(s++);
  422.                 if ((*s!='0') && (*s!=0))
  423.                     if (o>nonzero) nonzero = o;
  424.             }
  425.         }
  426.     }
  427.     *(o++) = 0;
  428.     if (nonzero!=NULL) *(nonzero+1) = 0;
  429. }
  430. /*-------------------------------------------------------------------------*/
  431. nice_log_ticks(double *start, double *last, double *gmin, double *gmax)
  432. {
  433.     double sz;
  434.  
  435.     if (*gmin<=0) {
  436.         gprint("FATAL ERROR, LOG AXIS WITH MIN OF ZERO***\n");
  437.         *gmin = 1;
  438.     }
  439.     if (*gmax<=0) *gmax = 10;
  440.     *start = pow(10.0,floor(log10(*gmin)));
  441.  
  442.     if (floor(log10(*gmin)) != log10(*gmin)) {
  443.         sz = pow(10.0,floor(log10(*gmin)));
  444.         *start = floor((*gmin)/sz)*sz + sz;
  445.         if (*start>(*gmin+sz-sz/100)) *start = *start - sz;
  446.     }
  447.     *last = floor(log10(*gmax))+1;
  448.     if (floor(log10(*gmax))==log10(*gmax)) {
  449.         --*last;
  450.         *last = pow(10.0,*last);
  451.     } else {
  452.         *last = pow(10.0,*last-1);
  453.         *last = floor((*gmax) / *last) * *last;
  454.     }
  455. }
  456. double fnloglen(double v,struct axis_struct *ax)  /* Dist in cm in log axis */
  457. {
  458.    return ((v-log10(ax->min))/(log10(ax->max)-log10(ax->min))) * ax->length;
  459. }
  460. double fnlogx(double v,struct axis_struct *ax)
  461. {
  462.     return fnloglen(log10(v),ax);
  463. }
  464. fnbig(double v)
  465. {
  466.     if (fabs(log10(v)-floor(log10(v)+.5)) < .001)
  467.         return true;
  468.     else return false;
  469. }
  470.  
  471.  
  472.                                                                                                                                                                                                        
  473.               
  474.