home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / gems / graphics / label.c < prev    next >
C/C++ Source or Header  |  1992-04-09  |  2KB  |  117 lines

  1. /* 
  2.  * Nice Numbers for Graph Labels
  3.  * by Paul Heckbert
  4.  * from "Graphics Gems", Academic Press, 1990
  5.  */
  6.  
  7. /*
  8.  * label.c: demonstrate nice graph labeling
  9.  *
  10.  * Paul Heckbert    2 Dec 88
  11.  */
  12.  
  13. #include "GraphicsGems.h"
  14. #include <stdio.h>
  15. #include <math.h>
  16.  
  17. double nicenum();
  18.  
  19. /* expt(a,n)=a^n for integer n */
  20.  
  21. #ifdef POW_NOT_TRUSTWORTHY
  22. /* if roundoff errors in pow cause problems, use this: */
  23.  
  24. double expt(a, n)
  25. double a;
  26. register int n;
  27. {
  28.     double x;
  29.  
  30.     x = 1.;
  31.     if (n>0) for (; n>0; n--) x *= a;
  32.     else for (; n<0; n++) x /= a;
  33.     return x;
  34. }
  35.  
  36. #else
  37. #define expt(a, n) pow(a, (double)(n))
  38. #endif
  39.  
  40.  
  41. #define NTICK 5            /* desired number of tick marks */
  42.  
  43. main(ac, av)
  44. int ac;
  45. char **av;
  46. {
  47.     double min, max;
  48.  
  49.     if (ac!=3) {
  50.         fprintf(stderr, "Usage: label <min> <max>\n");
  51.         exit(1);
  52.     }
  53.     min = atof(av[1]);
  54.     max = atof(av[2]);
  55.     loose_label(min, max);
  56. }
  57.  
  58. /*
  59.  * loose_label: demonstrate loose labeling of data range from min to 
  60.  *               max.   (tight method is similar) 
  61.  */
  62.  
  63. loose_label(min, max)
  64. double min, max;
  65. {
  66.     char str[6], temp[20];
  67.     int nfrac;
  68.     double d;                /* tick mark spacing */
  69.     double graphmin, graphmax;        /* graph range min and max */
  70.     double range, x;
  71.  
  72.     /* we expect min!=max */
  73.     range = nicenum(max-min, 0);
  74.     d = nicenum(range/(NTICK-1), 1);
  75.     graphmin = floor(min/d)*d;
  76.     graphmax = ceil(max/d)*d;
  77.     nfrac = MAX(-floor(log10(d)), 0); 
  78.                     /* # of fractional digits to show */
  79.     sprintf(str, "%%.%df", nfrac);    /* simplest axis labels */
  80.  
  81.     printf("graphmin=%g graphmax=%g increment=%g\n", 
  82.                 graphmin, graphmax, d);
  83.     for (x=graphmin; x<graphmax+.5*d; x+=d) {
  84.         sprintf(temp, str, x);
  85.         printf("(%s)\n", temp);
  86.     }
  87. }
  88.  
  89.  
  90. /*
  91.  * nicenum: find a "nice" number approximately equal to x.
  92.  * Round the number  if round=1, take ceiling if round=0
  93.  */
  94.  
  95. static double nicenum(x, round)
  96. double x;
  97. int round;
  98. {
  99.     int exp;                /* exponent of x */
  100.     double f;                /* fractional part of x */
  101.     double nf;                /* nice, rounded fraction */
  102.  
  103.     exp = floor(log10(x));
  104.     f = x/expt(10., exp);        /* between 1 and 10 */
  105.     if (round)
  106.         if (f<1.5) nf = 1.;
  107.         else if (f<3.) nf = 2.;
  108.         else if (f<7.) nf = 5.;
  109.         else nf = 10.;
  110.     else
  111.         if (f<=1.) nf = 1.;
  112.         else if (f<=2.) nf = 2.;
  113.         else if (f<=5.) nf = 5.;
  114.         else nf = 10.;
  115.     return nf*expt(10., exp);
  116. }
  117.