r145: *** empty log message ***
[ctsim.git] / libctgraphics / ezsupport.cpp
1 /*****************************************************************************
2 **  This is part of the CTSim program
3 **  Copyright (C) 1983-2000 Kevin Rosenberg
4 **
5 **  $Id: ezsupport.cpp,v 1.4 2000/07/13 07:03:21 kevin Exp $
6 **
7 **  This program is free software; you can redistribute it and/or modify
8 **  it under the terms of the GNU General Public License (version 2) as
9 **  published by the Free Software Foundation.
10 **
11 **  This program is distributed in the hope that it will be useful,
12 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 **  GNU General Public License for more details.
15 **
16 **  You should have received a copy of the GNU General Public License
17 **  along with this program; if not, write to the Free Software
18 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 ******************************************************************************/
20
21 #include <math.h>
22 #include <algorithm>
23 #include "ctsupport.h"
24 #include "ezplot.h"
25
26
27 /* NAME
28  *    axis_scale                        calculates graph axis scaling
29  *
30  *  SYNOPSIS:
31  *    retval = axis_scale (min, max, nint, minp, maxp, nintp, 
32  *                         rec_total, rec_frac)
33  *
34  *    INPUT:
35  *      double min         Smallest value to plot
36  *      double max         Largest value to plot
37  *      int    nint        Number of intervals desired
38  *
39  *    OUTPUT:
40  *      int   retval       FALSE if illegal parameters, else TRUE
41  *      double *minp       Minimum graph value
42  *      double *maxp       Maximum graph value
43  *      int    *nintp      Number of intervals for graph
44  *      int    *rec_total  Recommended field width for printing out the number
45  *      int    *rec_frac   Recommended number of digits for print fraction
46  */
47
48 int 
49 axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp)
50 {
51     double eps, a, scale, mina, maxa, d, j, e, f, v, wdt, g, h;
52
53     if (min >= max || nint < 1) {
54         sys_error (ERR_WARNING, "Invalid params: min=%lf, min=%lf, num intervals=%d [axis_scale]", min, max, nint);
55             return (FALSE);
56         }
57
58     eps = 0.025;
59     a = fabs(min);
60     if (fabs(min) < fabs(max))
61         a = fabs(max);
62     scale = pow (10.0, floor(log10(a)));
63  loop:
64     mina = min / scale;
65     maxa = max / scale;
66     d = (maxa - mina) / nint;
67     j = d * eps;
68     e = floor (log10(d));
69     f = d / pow (10.0, e);
70     v = 10.0;
71     if (f < sqrt(2.0))
72         v = 1.0;
73     else if (f < sqrt (10.0))
74         v = 2.0;
75     else if (f < sqrt (50.0))
76         v = 5.0;
77     wdt = v * pow (10.0, e);
78     g = floor (mina / wdt);
79     if (fabs(g + 1 - mina / wdt) < j)
80         g = g + 1;
81     *minp = wdt * g;
82     h = floor (maxa / wdt) + 1.0;
83     if (fabs(maxa / wdt + 1 - h) < j)
84         h = h - 1;
85     *maxp = wdt * h;
86     *nintp = static_cast<int>(h - g);
87     if (fabs(*maxp) >= 10.0 || fabs(*minp) >= 10.0) {
88         scale = scale * 10.0;
89         goto loop;
90     }
91     
92     *minp *= scale;
93     *maxp *= scale;
94     
95     return (TRUE);
96 }
97
98
99 /* NAME
100  *   make_numfmt                Make a numeric format string
101  *
102  * SYNOPSIS
103  *   make_numfmt (fmtstr, fldwid, nfrac, min, max, nint)
104  *   char *fmtstr               Returned format string for printf()
105  *   int  *fldwid               Returned field width
106  *   int  *nfrac                If < 0, then calculate best number of
107  *                              fraction places & return that value
108  *                              If >= 0, then use that number of places
109  *   double min                 Minimum value
110  *   double max                 Maximum value
111  *   int nint                   Number of intervals between min & max
112  *
113  * DESCRIPTION
114  *   This  routine is written as an INTERNAL routine for EZPLOT
115  */
116
117 static inline double 
118 trunc (double x)
119 {
120   double integer;
121   
122   modf (x, &integer);
123   
124   return (integer);
125 }
126
127 void 
128 make_numfmt (char *fmtstr, int *fldwid, int *nfrac, double minval, double maxval, int nint)
129 {
130   int wid, frac, expon;
131
132   double delta = (maxval - minval) / nint;
133   double absmin = fabs(minval);
134   double absmax = fabs(maxval);
135   double logt = log10( max(absmin, absmax) );
136
137   if (fabs(logt) >= 6) {                /* use exponential format */
138     if (fabs(logt) > 99)
139       expon = 5;                /*  E+102 */
140     else
141       expon = 4;                /*  E+00 */
142     
143     if (*nfrac < 0) {           /* calculate frac */
144       delta /= pow (10., floor(logt));  /* scale delta */
145       frac = static_cast<int>(fabs(trunc(log10(delta)))) + 1;
146       if (frac < 1)
147         frac = 1;               /* to be safe, add decimal pt */
148     } else                      /* use users' frac */
149       frac = *nfrac;
150     
151     wid = 2 + frac + expon;
152     if (minval < 0. || maxval < 0.)
153       ++wid;
154     sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "g");
155   } else {                      /* use fixed format */
156     wid = static_cast<int>(trunc(logt)) + 1;
157     if (wid < 1)
158       wid = 1;
159     if (minval < 0. || maxval < 0.)
160       ++wid;
161     
162     if (*nfrac < 0) {           /* calculate frac */
163       if (delta >= 0.999999)
164         frac = 1;               /* add a decimal pt to be safe */
165       else
166         frac = static_cast<int>(fabs(trunc(log10(delta)))) + 1;
167     } else                      /* use users' frac */
168       frac = *nfrac;
169     
170     wid += 1 + frac;
171     sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "f");
172   }
173
174   *fldwid = wid;
175   *nfrac = frac;
176 }
177
178 #ifdef TEST
179 int 
180 main (void)
181 {
182   double min, max;
183   double x, xinc;
184   int i, nint, wid, frac;
185   char fmtstr[10];
186   
187   printf ("Enter min, max, & number of intervals -- ");
188   scanf ("%lf %lf %d", &min, &max, &nint);
189   
190   frac = -1;    /* let makefmt determine fraction */
191   
192   makefmt (fmtstr, &wid, &frac, min, max, nint);
193   
194   printf ("Format string = %s\n", fmtstr);
195
196   xinc = (max - min) / nint;
197   
198   x = min;
199   for (i = 0; i <= nint; i++) {
200     printf (fmtstr, x);
201     x += xinc;
202     printf ("\n");
203   }
204 }
205 #endif
206
207 void 
208 ezplot_1d (double *y, int n)
209 {
210   double x [n];
211
212   for (int i = 0; i < n; i++)
213     x[i] = i;
214
215   ezplot (x, y, n);
216 }