r104: initial cvs import
[ctsim.git] / libctgraphics / ezsupport.cpp
diff --git a/libctgraphics/ezsupport.cpp b/libctgraphics/ezsupport.cpp
new file mode 100644 (file)
index 0000000..51f9742
--- /dev/null
@@ -0,0 +1,216 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: ezsupport.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+#include <math.h>
+#include <algorithm>
+#include "kstddef.h"
+#include "ezplot.h"
+
+
+/* NAME
+ *    axis_scale                       calculates graph axis scaling
+ *
+ *  SYNOPSIS:
+ *    retval = axis_scale (min, max, nint, minp, maxp, nintp, 
+ *                        rec_total, rec_frac)
+ *
+ *    INPUT:
+ *     double min         Smallest value to plot
+ *     double max         Largest value to plot
+ *     int    nint        Number of intervals desired
+ *
+ *    OUTPUT:
+ *     int   retval       FALSE if illegal parameters, else TRUE
+ *     double *minp       Minimum graph value
+ *     double *maxp       Maximum graph value
+ *     int    *nintp      Number of intervals for graph
+ *      int    *rec_total  Recommended field width for printing out the number
+ *     int    *rec_frac   Recommended number of digits for print fraction
+ */
+
+int 
+axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp)
+{
+    double eps, a, scale, mina, maxa, d, j, e, f, v, wdt, g, h;
+
+    if (min >= max || nint < 1) {
+       sys_error (ERR_WARNING, "Invalid params: min=%lf, min=%lf, num intervals=%d [axis_scale]", min, max, nint);
+           return (FALSE);
+       }
+
+    eps = 0.025;
+    a = fabs(min);
+    if (fabs(min) < fabs(max))
+       a = fabs(max);
+    scale = pow (10.0, floor(log10(a)));
+ loop:
+    mina = min / scale;
+    maxa = max / scale;
+    d = (maxa - mina) / nint;
+    j = d * eps;
+    e = floor (log10(d));
+    f = d / pow (10.0, e);
+    v = 10.0;
+    if (f < sqrt(2.0))
+       v = 1.0;
+    else if (f < sqrt (10.0))
+       v = 2.0;
+    else if (f < sqrt (50.0))
+       v = 5.0;
+    wdt = v * pow (10.0, e);
+    g = floor (mina / wdt);
+    if (fabs(g + 1 - mina / wdt) < j)
+       g = g + 1;
+    *minp = wdt * g;
+    h = floor (maxa / wdt) + 1.0;
+    if (fabs(maxa / wdt + 1 - h) < j)
+       h = h - 1;
+    *maxp = wdt * h;
+    *nintp = static_cast<int>(h - g);
+    if (fabs(*maxp) >= 10.0 || fabs(*minp) >= 10.0) {
+       scale = scale * 10.0;
+       goto loop;
+    }
+    
+    *minp *= scale;
+    *maxp *= scale;
+    
+    return (TRUE);
+}
+
+
+/* NAME
+ *   make_numfmt               Make a numeric format string
+ *
+ * SYNOPSIS
+ *   make_numfmt (fmtstr, fldwid, nfrac, min, max, nint)
+ *   char *fmtstr              Returned format string for printf()
+ *   int  *fldwid              Returned field width
+ *   int  *nfrac               If < 0, then calculate best number of
+ *                             fraction places & return that value
+ *                             If >= 0, then use that number of places
+ *   double min                        Minimum value
+ *   double max                        Maximum value
+ *   int nint                  Number of intervals between min & max
+ *
+ * DESCRIPTION
+ *   This  routine is written as an INTERNAL routine for EZPLOT
+ */
+
+static inline double 
+trunc (double x)
+{
+  double integer;
+  
+  double frac = modf (x, &integer);
+  
+  return (integer);
+}
+
+void 
+make_numfmt (char *fmtstr, int *fldwid, int *nfrac, double minval, double maxval, int nint)
+{
+  int wid, frac, expon;
+
+  double delta = (maxval - minval) / nint;
+  double absmin = fabs(minval);
+  double absmax = fabs(maxval);
+  double logt = log10( max(absmin, absmax) );
+
+  if (fabs(logt) >= 6) {               /* use exponential format */
+    if (fabs(logt) > 99)
+      expon = 5;               /*  E+102 */
+    else
+      expon = 4;               /*  E+00 */
+    
+    if (*nfrac < 0) {          /* calculate frac */
+      delta /= pow (10., floor(logt)); /* scale delta */
+      frac = static_cast<int>(fabs(trunc(log10(delta)))) + 1;
+      if (frac < 1)
+       frac = 1;               /* to be safe, add decimal pt */
+    } else                     /* use users' frac */
+      frac = *nfrac;
+    
+    wid = 2 + frac + expon;
+    if (minval < 0. || maxval < 0.)
+      ++wid;
+    snprintf (fmtstr, sizeof(fmtstr), "%%%d.%dle", wid, frac);
+  } else {                     /* use fixed format */
+    wid = static_cast<int>(trunc(logt)) + 1;
+    if (wid < 1)
+      wid = 1;
+    if (minval < 0. || maxval < 0.)
+      ++wid;
+    
+    if (*nfrac < 0) {          /* calculate frac */
+      if (delta >= 0.999999)
+       frac = 1;               /* add a decimal pt to be safe */
+      else
+       frac = static_cast<int>(fabs(trunc(log10(delta)))) + 1;
+    } else                     /* use users' frac */
+      frac = *nfrac;
+    
+    wid += 1 + frac;
+    snprintf (fmtstr, sizeof(fmtstr), "%%%d.%dlf", wid, frac);
+  }
+  
+  *fldwid = wid;
+  *nfrac = frac;
+}
+
+#ifdef TEST
+int 
+main (void)
+{
+  double min, max;
+  double x, xinc;
+  int i, nint, wid, frac;
+  char fmtstr[10];
+  
+  printf ("Enter min, max, & number of intervals -- ");
+  scanf ("%lf %lf %d", &min, &max, &nint);
+  
+  frac = -1;   /* let makefmt determine fraction */
+  
+  makefmt (fmtstr, &wid, &frac, min, max, nint);
+  
+  printf ("Format string = %s\n", fmtstr);
+
+  xinc = (max - min) / nint;
+  
+  x = min;
+  for (i = 0; i <= nint; i++) {
+    printf (fmtstr, x);
+    x += xinc;
+    printf ("\n");
+  }
+}
+#endif
+
+void 
+ezplot_1d (double *y, int n)
+{
+  double x [n];
+
+  for (int i = 0; i < n; i++)
+    x[i] = i;
+
+  ezplot (x, y, n);
+}