r309: plotfile changes
[ctsim.git] / libctgraphics / ezplot.cpp
index 666f7593d0e9562aa0eb527483c13b0f05fafacd..5a2ec69a34a2700a309722310ee61cc19bfb4e0c 100644 (file)
@@ -6,7 +6,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2000 Kevin Rosenberg
 **
-**  $Id: ezplot.cpp,v 1.4 2000/07/04 18:33:35 kevin Exp $
+**  $Id: ezplot.cpp,v 1.20 2000/12/20 20:08:48 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
 ******************************************************************************/
 
 #include "ezplot.h"
-#include "algo.h"
+#include <algorithm>
 
+#ifdef __GNUWIN32__
+int snprintf (char *, size_t, const char*, ...);
+#endif
 
-static int plot (SGP_ID *gid);
-static void drawaxis(void);
-static void symbol (int sym, double symwidth, double symheight);
+// Defaults
+static const double TICKRATIO = 0.4;   // ratio of minor to major tick lengths
+static const int MAXNUMFMT = 15;       // maximum length of a numeric format 
+static const int DEF_CURVE_CLR = C_RED;
 
-/*-------------------------------------*/
-/* GLOBAL variables for EZPLOT & EZSET */
-/*-------------------------------------*/
 
-bool ezplot_firstcall = TRUE;  /* set to false on first call to EZSET or EZPLOT */
-struct ezplot_var ez;          /* ezplot variables */
-
-/*----------------*/
-/* DEFAULT values */
-/*----------------*/
-
-#define TICKRATIO 0.4          /* ratio of minor to major tick lengths */
-#define MAXNUMFMT 15           /* maximum length of a numeric format */
+EZPlotCurve::EZPlotCurve (const double* xData, const double* yData, int n, int color, int linestyle, int symbol, int symfreq, const std::string& legend)
+  : x(NULL), y(NULL), m_sLegend (legend)
+{
+  x = new double [n];
+  y = new double [n];
+
+  int copyCount = n * sizeof(double);
+  memcpy (x, xData, copyCount);
+  memcpy (y, yData, copyCount);
+
+  m_iPointCount = n;
+  m_iColor = color;
+  m_iLineStyle = linestyle;
+  m_iSymbol = symbol;
+  m_iSymbolFreq = symfreq;
+}
 
-#define DEF_CRTMODE    0  /*GM_HIGHRES*/       /* default crt mode */
-#define DEF_CHARHEIGHT (1./43.)        /* default size of characters in NDC */
-#define DEF_CHARWIDTH  (1./80.)
+EZPlotCurve::~EZPlotCurve ()
+{
+  delete x;
+  delete y;
+}
 
-#define DEF_CURVE_CLR   C_YELLOW
 
+void 
+EZPlot::addCurve (const double *y, int n)
+{
+  double* x = new double [n];
 
-/*----------------------------------------------------------------------*/
-/*                             GLOBAL VARIABLES                        */
-/*----------------------------------------------------------------------*/
+  for (int i = 0; i < n; i++)
+    x[i] = i;
 
-static
-double charwidth, charheight;  /* Size of characters in NDC */
+  addCurve (x, y, n);
+  delete x;
+}
 
-static
-double  xp_min, xp_max,
-    yp_min, yp_max;            /* boundry of plot frame in NDC */
-static
-double  xa_min, xa_max,
-    ya_min, ya_max;            /* extent of axes in NDC */
-static
-double  xgw_min, xgw_max,
-    ygw_min, ygw_max;  /* boundary of graph in input coords */
-static
-double  xgn_min, xgn_max,
-    ygn_min, ygn_max;  /* boundy of graph in NDC */
-static
-double xt_min, xt_max,
-    yt_min, yt_max;            /* boundary of axis ticks */
 
-static
-double  xl_min, xl_max,
-    yl_min, yl_max;            /* boundary of legend box */
+void 
+EZPlot::addCurve (const float *y, int n)
+{
+  double* yDouble = new double [n];
 
-static  double title_row;      /* y-coord of title row */
+  for (int i = 0; i < n; i++)
+    yDouble[i] = y[i];
 
-static  double xtl_ofs;                /* Offset y-coord of x tick labels from axis */
-static double ytl_ofs;         /* Offset x-coord of y tick labels from axis */
+  addCurve (yDouble, n);
+  delete yDouble;
+}
 
-static double xlbl_row;        /* row of x label in world coord */
-static double ylbl_col;        /* column of y label in world coord */
 
-static
-double xw_tickinc, yw_tickinc; /* increment between major ticks in WC */
+void
+EZPlot::addCurve (const float x[], const double y[], int num)
+{
+  double* dx = new double [num];
 
-static
-double xn_tickinc, yn_tickinc; /* increment between major ticks in NDC */
+  for (int i = 0; i < num; i++)
+    dx[i] = x[i];
 
-static int x_nint, y_nint;     /* number of intervals along x & y axes */
-static int x_fldwid, x_frac;   /* numeric field sizes & number of digits   */
-static int y_fldwid, y_frac;   /* in fraction of number, used for printf() */
+  addCurve (dx, y, num);
+  delete dx;
+}
 
-static double xtl_wid, ytl_wid;        /* length of ticks labels in NDC */
-static double tl_height;       /* height of tick labels in NDC */
+void
+EZPlot::addCurve (const double x[], const float y[], int num)
+{
+  double* dy = new double [num];
 
-static char x_numfmt[20];      /* format to print x tick labels */
-static char y_numfmt[20];      /* format to print y tick labels */
+  for (int i = 0; i < num; i++)
+    dy[i] = y[i];
 
+  addCurve (x, dy, num);
 
-/*----------------------------------------------------------------------
- * FUNCTION IDENTICIFATION
- *
- *     Name:           EZPLOT
- *     Programmer:     Kevin Rosenberg
- *     Date:            5-83 Version 1
- *                     11-84 Version 2
- *
- * SYNOPSIS
- *     ezplot (x, y, n)
- *     double x[]      x-coordinates of point  makeing up a curve 
- *     double y[]      y-coordinates of points makeing up a curve
- *     int    n        Number of points in curve
- *
- * DESCRIPTION
- *         This is a sophisticated plotting program.
- *
- *----------------------------------------------------------------------*/
+  delete dy;
+}
 
 
-SGP_ID 
-ezplot (float x[], double y[], int num)
+void
+EZPlot::addCurve (const double x[], const double y[], int num)
 {
-  double dx [num];
-
-  for (int i = 0; i < num; i++)
-    dx[i] = x[i];
+  if (num < 1)
+    return;
 
-  ezplot (dx, y, num);
+  EZPlotCurve* pCurve = new EZPlotCurve (x, y, num, o_color, o_linestyle, o_symbol, o_symfreq, c_legend);
+  m_vecCurves.push_back (pCurve);
 }
 
 
-SGP_ID
-ezplot (double x[], double y[], int num)
+EZPlot::~EZPlot ()
 {
-    unsigned int size, i;
-    SGP_ID gid = NULL;
-
-    if (ez.i_plotimmediate == TRUE) {
-       plot (&gid);
-       return (gid);
-    }
-
-    if (num < 1)
-       return (NULL);
+  for (EZPlotCurveIterator i = m_vecCurves.begin(); i != m_vecCurves.end(); i++)
+    delete *i;
+}
 
-    if (ezplot_firstcall == TRUE)
-       ezinit();
+void
+EZPlot::clearCurves ()
+{
+  for (EZPlotCurveIterator i = m_vecCurves.begin(); i != m_vecCurves.end(); i++)    
+    delete *i;
+  m_vecCurves.erase (m_vecCurves.begin(), m_vecCurves.end());
+  initPlotSettings();
+}
 
-    if (ez.o_unknowncurves == FALSE && ez.i_numcurves >= ez.o_reqcurves)
-       ezclear ();
 
-    if (ez.i_numcurves < MAXCURVES &&
-       (ez.o_unknowncurves == TRUE || ez.i_numcurves < ez.o_reqcurves)) {
-       size = num * sizeof(double);
-       ez.curve[ez.i_numcurves].x = new double [size];
-       ez.curve[ez.i_numcurves].y = new double [size];
-       for (i = 0; i < num; i++) {
-           ez.curve[ez.i_numcurves].x[i] = x[i];
-           ez.curve[ez.i_numcurves].y[i] = y[i];
-       }
-       ez.curve[ez.i_numcurves].numpts = num;
-       ez.curve[ez.i_numcurves].color = ez.o_color;
-       ez.curve[ez.i_numcurves].linestyle = ez.o_linestyle;
-       ez.curve[ez.i_numcurves].symbol = ez.o_symbol;
-       ez.curve[ez.i_numcurves].symfreq = ez.o_symfreq;
-       strncpy (ez.curve[ez.i_numcurves].legend, ez.c_legend, MAXLEGEND);
-       ++ez.i_numcurves;
-    }
-    
-    if (ez.o_unknowncurves == FALSE && ez.i_numcurves >= ez.o_reqcurves) {
-       plot (&gid);
-       ezclear ();
-    }
+EZPlot::EZPlot (SGP& sgp)
+  : rSGP (sgp)
+{
+    initPlotSettings();
+}
 
-    return (gid);
+void
+EZPlot::initPlotSettings ()
+{
+  charheight = rSGP.getCharHeight();
+  charwidth = rSGP.getCharWidth();
+
+  c_xlabel = "";
+  c_ylabel =  "";
+  c_title = "";
+  c_legend = "";
+  
+  o_xporigin = 0.0;
+  o_yporigin = 0.0;
+  o_xlength  = 1.0;
+  o_ylength  = 1.0;
+  
+  o_xaxis = LINEAR;
+  o_yaxis = LINEAR;
+  
+  o_grid = FALSE;
+  o_box = FALSE;
+  
+  o_xmajortick = 10;
+  o_ymajortick =  8;
+  o_xminortick =  4;
+  o_yminortick =  4;
+  
+  o_color = DEF_CURVE_CLR;
+  o_symfreq = 1;
+  o_symbol = -1;
+  o_linestyle = SGP::LS_SOLID;
+  
+  o_xtlabel = TRUE;
+  o_ytlabel = TRUE;
+  o_xticks = BELOW;
+  o_yticks = LEFT;
+  
+  o_legendbox = INSIDE;
+  o_tag = FALSE;
+  
+  s_xtitle   = FALSE;
+  s_ytitle   = FALSE;
+  s_xcross   = FALSE;
+  s_ycross   = FALSE;
+  s_lxfrac   = FALSE;
+  s_lyfrac   = FALSE;
+  s_xlegend  = FALSE;
+  s_ylegend  = FALSE;
+  s_textsize = FALSE;
+  
+  clr_axis   = C_BLACK;                // set fixed colors 
+  clr_title  = C_CYAN;
+  clr_label  = C_CYAN;
+  clr_legend = C_RED;
+  clr_number = C_GREEN;
+  clr_grid   = C_LTGRAY;
 }
 
 
 /* NAME
- *   plot              INTERNAL: Plots all curves collected by ezplot()
+ *   plot              Plots all curves collected by addCurves ()
  *
  * SYNOPSIS
  *   plot()
  *
  * DESCRIPTION
- *   This routine plots the curves that have stored by ezplot().
- *
- * CALLED BY
- *   EZPLOT() only
+ *   This routine plots the curves that have stored by addCurves().
  *
  * CALLS
- *   drawaxis() & make_numfmt()
+ *   drawAxes() & make_numfmt()
  */
 
-static int plot (SGP_ID *gid)
+void
+EZPlot::plot ()
 {
-    double xmin, xmax;         /* extend of curves in world coord  */
-    double ymin, ymax;
-    double x_added_ticks;              /* number of tick spaces added to axis */
-    double y_added_ticks;
-    double symwidth, symheight;        /* size of symbol in NDC */
-    double leg_width, leg_height;      /* size of legend box */
-    int num_leg;                       /* number of legend titles */
-    int max_leg;                       /* longest legend in characters */
-    int i, j, ip, ic, n;
-
-    if (ez.i_numcurves <= 0)
-       return (FALSE);
-
-    if (ez.o_ustart == FALSE && *gid == NULL) {
-       *gid = sgp2_init (0, 0, "Ezplot");
-    }
-    
-    if (ez.s_textsize == TRUE)
-       charheight = ez.v_textsize;
-    else
-       charheight = DEF_CHARHEIGHT;
-    
-    gp_set_aspect (CRTDEV, 1.0);
+  if (m_vecCurves.size() <= 0)
+    return;
+
+  rSGP.setWindow (0., 0., 1., 1.);
+
+  if (s_textsize == TRUE) {
+    charheight = v_textsize;
+    charwidth = rSGP.getCharWidth();
+  } else {
+    charheight = rSGP.getCharHeight();
+    charwidth = rSGP.getCharWidth();
+  }
+  
+  const EZPlotCurve& firstCurve = *m_vecCurves[0];
+  double xmin = firstCurve.x[0];   // extent of curves in world coord
+  double xmax = xmin;       
+  double ymin = firstCurve.y[0];
+  double ymax = ymin;
+  
+  for (EZPlotCurveConstIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) {
+    const EZPlotCurve& curve = **iterCurve;
     
-    xmin = xmax = ez.curve[0].x[0];
-    ymin = ymax = ez.curve[0].y[0];
-    
-    for (ic = 0; ic < ez.i_numcurves; ic++) {
-       for (ip = 0; ip < ez.curve[ic].numpts; ip++) {
-           if (ez.curve[ic].x[ip] > xmax)
-               xmax = ez.curve[ic].x[ip];
-           else if (ez.curve[ic].x[ip] < xmin)
-               xmin = ez.curve[ic].x[ip];
-           if (ez.curve[ic].y[ip] > ymax)
-               ymax = ez.curve[ic].y[ip];
-           else if (ez.curve[ic].y[ip] < ymin)
-               ymin = ez.curve[ic].y[ip];
-       }
+    for (int ip = 0; ip < curve.m_iPointCount; ip++) {
+      if (curve.x[ip] > xmax)
+       xmax = curve.x[ip];
+      else if (curve.x[ip] < xmin)
+       xmin = curve.x[ip];
+      if (curve.y[ip] > ymax)
+       ymax = curve.y[ip];
+      else if (curve.y[ip] < ymin)
+       ymin = curve.y[ip];
     }
+  }
+  
+  // extend graph limits for user defined axis cross positions 
+  if (s_xcross == TRUE) {
+    if (v_xcross < xmin)
+      xmin = v_xcross;
+    else if (v_xcross > xmax)
+      xmax = v_xcross;
+  }
     
-    /* extend graph limits for user defined axis cross positions */
+  if (s_ycross == TRUE) {
+    if (v_ycross < ymin)
+      ymin = v_ycross;
+    else if (v_ycross > ymax)
+      ymax = v_ycross;
+  }
     
-    if (ez.s_xcross == TRUE)
-       {
-           if (ez.v_xcross < xmin)
-               xmin = ez.v_xcross;
-           else if (ez.v_xcross > xmax)
-               xmax = ez.v_xcross;
-       }
+  // find nice endpoints for axes 
+  if (! axis_scale (xmin, xmax, o_xmajortick - 1, &xgw_min, &xgw_max, &x_nint) || ! axis_scale (ymin, ymax, o_ymajortick - 1, &ygw_min, &ygw_max, &y_nint))
+    return;
     
-    if (ez.s_ycross == TRUE)
-       {
-           if (ez.v_ycross < ymin)
-               ymin = ez.v_ycross;
-           else if (ez.v_ycross > ymax)
-               ymax = ez.v_ycross;
-       }
+  // check if user set x-axis extents 
+  if (s_xmin == TRUE) {
+    xgw_min = v_xmin;
+    x_nint = o_xmajortick - 1;
+  }
+  if (s_xmax == TRUE) {
+    xgw_max = v_xmax;
+    x_nint = o_xmajortick - 1;
+  }
+  
+  // check if user set y-axis extents 
+  if (s_ymin == TRUE) {
+    ygw_min = v_ymin;
+    y_nint = o_ymajortick - 1;
+  }
+  if (s_ymax == TRUE) {
+    ygw_max = v_ymax;
+    y_nint = o_ymajortick - 1;
+  }
     
-    /* find nice endpoints for axes */
-
-    axis_scale (xmin, xmax, ez.o_xmajortick - 1, &xgw_min, &xgw_max, &x_nint);
-    axis_scale (ymin, ymax, ez.o_ymajortick - 1, &ygw_min, &ygw_max, &y_nint);
+  // calculate increment between major axis in world coordinates 
+  xw_tickinc = (xgw_max - xgw_min) / x_nint;
+  yw_tickinc = (ygw_max - ygw_min) / y_nint;
     
-    /* check if user set x-axis extents */
+  // we have now calcuated xgw_min, xyw_max, ygw_min, & ygw_max 
+  
+  // set the number of decimal point to users' setting or default 
+  // Two formats for numbers: Fixed:    -nnn.f and  Exponent: -n.fffE+eee
+  if (s_lxfrac == TRUE)
+    x_frac = v_lxfrac;
+  else
+    x_frac = -1;
     
-    if (ez.s_xmin == TRUE) {
-       xgw_min = ez.v_xmin;
-       x_nint = ez.o_xmajortick - 1;
-    }
-    if (ez.s_xmax == TRUE) {
-       xgw_max = ez.v_xmax;
-       x_nint = ez.o_xmajortick - 1;
-    }
+  if (s_lyfrac == TRUE)
+    y_frac = v_lyfrac;
+  else
+    y_frac = -1;
     
-    /* check if user set y-axis extents */
+  make_numfmt (x_numfmt, &x_fldwid, &x_frac, xgw_min, xgw_max, x_nint);
+  make_numfmt (y_numfmt, &y_fldwid, &y_frac, ygw_min, ygw_max, y_nint);
     
-    if (ez.s_ymin == TRUE) {
-       ygw_min = ez.v_ymin;
-       y_nint = ez.o_ymajortick - 1;
-    }
-    if (ez.s_ymax == TRUE) {
-       ygw_max = ez.v_ymax;
-       y_nint = ez.o_ymajortick - 1;
+  xtl_wid = x_fldwid * charwidth;              // calc size of tick labels 
+  ytl_wid = y_fldwid * charwidth;
+  tl_height = charheight;
+
+  // calculate the extent of the plot frame 
+  xp_min = o_xporigin;
+  yp_min = o_yporigin;
+  xp_max = xp_min + o_xlength;
+  yp_max = yp_min + o_ylength;
+
+  xp_min = clamp (xp_min, 0., 1.);
+  xp_max = clamp (xp_max, 0., 1.);
+  yp_min = clamp (yp_min, 0., 1.);
+  yp_max = clamp (yp_max, 0., 1.);
+  
+  xa_min = xp_min;             // extent of axes 
+  xa_max = xp_max;
+  ya_min = yp_min;
+  ya_max = yp_max;
+
+  // adjust frame for title 
+  if (c_title.length() > 0)
+    ya_max -= 2 * charheight;
+  title_row = ya_max + 2 * charheight;
+
+  // calculate legend box boundaries 
+  int max_leg = 0;                     // longest legend in characters 
+  int num_leg = 0;                     // number of legend titles 
+  for (EZPlotCurveConstIterator iterCurve2 = m_vecCurves.begin(); iterCurve2 != m_vecCurves.end(); iterCurve2++) {
+    const EZPlotCurve& curve = **iterCurve2;
+    int nLegend = curve.m_sLegend.length();
+    if (nLegend > 0) {
+      ++num_leg;
+      if (nLegend > max_leg)\r
+               nLegend = max_leg;
     }
+  }
+
+  if (num_leg > 0 && o_legendbox != NOLEGEND) {
+    double leg_width  = (max_leg + 2) * charwidth;     // size of legend box 
+    double leg_height = num_leg * 3 * charheight;
     
-    /* calculate increment between major axis in world coordinates */
-    
-    xw_tickinc = (xgw_max - xgw_min) / x_nint;
-    yw_tickinc = (ygw_max - ygw_min) / y_nint;
-    
-    /* we have now calcuated xgw_min, xyw_max, ygw_min, & ygw_max */
-    
-    /* set the number of decimal point to users' setting or default */
-    /* Two formats for numbers
-       Fixed:    -nnn.f
-       Exponent: -n.fffE+eee
-    */
-    
-    if (ez.s_lxfrac == TRUE)
-       x_frac = ez.v_lxfrac;
-    else
-       x_frac = -1;
+    if (s_xlegend == TRUE)
+      xl_max = v_xlegend;
+    else {
+      xl_max = xa_max;
+      if (o_legendbox == OUTSIDE)
+       xa_max -= (leg_width + 0.5 * charwidth);
+    }
+    xl_min = xl_max - leg_width;
     
-    if (ez.s_lyfrac == TRUE)
-       y_frac = ez.v_lyfrac;
+    if (s_ylegend == TRUE)
+      yl_max = v_ylegend;
     else
-       y_frac = -1;
-    
-    make_numfmt (x_numfmt, &x_fldwid, &x_frac, xgw_min, xgw_max, x_nint);
-    make_numfmt (y_numfmt, &y_fldwid, &y_frac, ygw_min, ygw_max, y_nint);
-    
-    xtl_wid = x_fldwid * charwidth;            /* calc size of tick labels */
-    ytl_wid = y_fldwid * charwidth;
-    tl_height = charheight;
-    
-    /* calculate the extent of the plot frame */
-    
-    xp_min = ez.o_xporigin;
-    yp_min = ez.o_yporigin;
-    xp_max = xp_min + ez.o_xlength;
-    yp_max = yp_min + ez.o_ylength;
-
-    xp_min = clamp (xp_min, 0., 1.);
-    xp_max = clamp (xp_max, 0., 1.);
-    yp_min = clamp (yp_min, 0., 1.);
-    yp_max = clamp (yp_max, 0., 1.);
-    
-    xa_min = xp_min;           /* extent of axes */
-    xa_max = xp_max;
-    ya_min = yp_min;
-    ya_max = yp_max;
-    
-    /* adjust frame for title */
-    
-    if (strlen(ez.c_title) != 0)
-       ya_max -= 2.5 * charheight;
-    title_row = ya_max + 0.5 * charheight;
+      yl_max = ya_max;
     
-    /* calculate legend box boundaries */
-    
-    max_leg = 0;                       /* longest legend in characters */
-    num_leg = 0;                       /* number of legend titles */
-    for (i = 0; i < ez.i_numcurves; i++)
-       if ((n = strlen(ez.curve[i].legend)) > 0) {
-           ++num_leg;
-           max_leg = max(max_leg, n);
-       }
-    
-    if (num_leg > 0 && ez.o_legendbox != NOLEGEND) {
-       leg_width  = (max_leg + 2) * charwidth;
-       leg_height = num_leg * 3 * charheight;
-       
-       if (ez.s_xlegend == TRUE)
-           xl_max = ez.v_xlegend;
-       else {
-           xl_max = xa_max;
-           if (ez.o_legendbox == OUTSIDE)
-               xa_max -= (leg_width + 0.5 * charwidth);
-       }
-       xl_min = xl_max - leg_width;
-
-       if (ez.s_ylegend == TRUE)
-           yl_max = ez.v_ylegend;
-       else
-           yl_max = ya_max;
-
-       yl_min = yl_max - leg_height;
-
-       sgp2_window  (xl_min, yl_min, xl_max, yl_max);
-       sgp2_viewport (xl_min, yl_min, xl_max, yl_max);
-
-       sgp2_color (ez.clr_legend);
-       sgp2_draw_rect (xl_min, yl_min, xl_max, yl_max);
-
-       n = 0;                  /* current legend position */
-       for (i = 0; i < ez.i_numcurves; i++) {
-           double xmin, xmax, xinc, y;
-
-           if (strlen(ez.curve[i].legend) == 0)
-               continue;
-
-           xmin = xl_min + 1.0 * charwidth;
-           xmax = xl_max - 1.0 * charwidth;
-           y = yl_max - (2.0 + n * 3) * charheight;
-
-           sgp2_move_abs (xmin, y + 0.5 * charheight);
-           sgp2_draw_text (ez.curve[i].legend);
-           sgp2_color (ez.curve[i].color);
-           if (ez.curve[i].linestyle != LS_NOLINE) {
-               sgp2_line_style (ez.curve[i].linestyle);
-               sgp2_move_abs (xmin, y);
-               sgp2_line_abs (xmax, y);
-           }
-           if (ez.curve[i].symbol > 0) {
-               xinc = (xmax - xmin) / (5 - 1);
-               sgp2_line_style (LS_SOLID);
-               for (j = 0; j < 5; j++) {
-                   sgp2_move_abs (xmin + j * xinc, y);
-                   symbol(ez.curve[i].symbol,
-                          0.5 * charwidth, 0.5 * charheight);
-               }
-           }
-           ++n;                /* move to next legend position */
-       }
-    }   /* end legend printing */
-
-    /* calculate the extent of the axes */
-
-    /*-------------------------*/
-    /* adjust frame for labels */
-    /*-------------------------*/
-
-    /* x-label */
-
-    if (strlen(ez.c_xlabel) > 0)
-       ya_min += 3.0 * charheight;
-    xlbl_row = xp_min;         /* put x-label on bottom of plot frame */
-
-    /* y-label */
+    yl_min = yl_max - leg_height;
 
-    if (strlen(ez.c_ylabel) > 0)
-       xa_min += 3.0 * charwidth;      /* reverse charsize because writing */
-    /* text sideways */
-    ylbl_col = xp_min + 2 * charwidth;
+    rSGP.setColor (clr_legend);
+    rSGP.drawRect (xl_min, yl_min, xl_max, yl_max);
 
-    /*------------------------------*/
-    /* adjust frame for tick labels */
-    /*------------------------------*/
-
-    /* calc offset of tick labels from axes */
-
-    if (ez.o_xaxis == NOAXIS || ez.o_xtlabel == FALSE)
-       xtl_ofs = 0.0;
-    else if (ez.o_xticks == BELOW)
-       xtl_ofs = -2.5 * charheight;
-    else if (ez.o_xticks == ABOVE)
-       xtl_ofs = 1.5 * charheight;
-
-    if (ez.o_yaxis == NOAXIS || ez.o_ytlabel == FALSE)
-       ytl_ofs = 0.0;
-    else if (ez.o_yticks == LEFT)
-       ytl_ofs = -(1 + y_fldwid) * charwidth;
-    else if (ez.o_yticks == RIGHT)
-       ytl_ofs = 1.5 * charwidth;
-
-    /* see if need to shrink axis extents and/or tick extents */
+    int iLegend = 0;                   // current legend position 
+    for (EZPlotCurveIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) {
+       const EZPlotCurve& curve = **iterCurve;
+       
+       if (curve.m_sLegend.length() == 0)
+           continue;
 
-    if (xtl_ofs != 0.0 && ez.s_ycross == FALSE) {
-       if (ez.o_xticks == BELOW) {
-           ya_min += 2.5 * charheight;
-           yt_min = ya_min;
-       } else if (ez.o_xticks == ABOVE) {
-           ya_min += 0.0;
-           yt_min = ya_min + 2.5 * charheight;
+       double xmin = xl_min + 1.0 * charwidth;
+       double xmax = xl_max - 1.0 * charwidth;
+       double y = yl_max - (2.0 + iLegend * 3) * charheight;
+       
+       rSGP.moveAbs (xmin, y + 0.5 * charheight);
+       rSGP.drawText (curve.m_sLegend);
+       rSGP.setColor (curve.m_iColor);
+       if (curve.m_iLineStyle != SGP::LS_NOLINE) {
+           rSGP.setLineStyle (curve.m_iLineStyle);
+           rSGP.moveAbs (xmin, y);
+           rSGP.lineAbs (xmax, y);
        }
-    } else                     /* noaxis, no t-labels, or user set cross */
-       yt_min = ya_min;
-
-    if (ytl_ofs != 0.0 && ez.s_xcross == FALSE) {
-       if (ez.o_yticks == LEFT) {
-           xa_min += (1 + y_fldwid) * charwidth;
-           xt_min = xa_min;
-       } else if (ez.o_yticks == RIGHT) {
-           xa_min += 0.0;
-           xt_min = xa_min + ytl_ofs + y_fldwid * charwidth;
+       if (curve.m_iSymbol > 0) {
+           double xinc = (xmax - xmin) / (5 - 1);
+           rSGP.setLineStyle (SGP::LS_SOLID);
+           for (int j = 0; j < 5; j++) {
+             rSGP.moveAbs (xmin + j * xinc, y);
+             symbol(curve.m_iSymbol, 0.5 * charwidth, 0.5 * charheight);
+           }
        }
-    } else
-       xt_min = xa_min;
-
-    xt_max = xa_max;
-    yt_max = ya_max;
-
-    /* decrease size of graph, if necessary, to accommadate space */
-    /* between axis boundary and boundary of ticks */
-
-    x_added_ticks = -1;
-    y_added_ticks = -1;
-
-    if (ez.o_xaxis == NOAXIS || ez.o_xtlabel == FALSE)
-       x_added_ticks = 0;
-    if (ez.o_yaxis == NOAXIS || ez.o_ytlabel == FALSE)
-       y_added_ticks = 0;
-
-    if (ez.o_grid == TRUE) {
-       if (x_added_ticks < 0)
-           x_added_ticks = 2;
-       if (y_added_ticks < 0)
-           y_added_ticks = 2;
+       ++iLegend;      // move to next legend position 
     }
-
+  }   // end legend printing 
+
+  // calculate the extent of the axes 
+
+  /*-------------------------*/
+  /* adjust frame for labels */
+  /*-------------------------*/
+  
+  // X-Label 
+  if (c_xlabel.length() > 0)
+    ya_min += 3.0 * charheight;
+  xlbl_row = xp_min;           // put x-label on bottom of plot frame 
+
+  // Y-Label 
+  if (c_ylabel.length() > 0)
+    xa_min += 3.0 * charwidth; // reverse rSGP.setTextSize because writing text sideways 
+  ylbl_col = xp_min + 2 * charwidth;
+
+  /*------------------------------*/
+  /* adjust frame for tick labels */
+  /*------------------------------*/
+
+  // Calc offset of tick labels from axes 
+  if (o_xaxis == NOAXIS || o_xtlabel == FALSE)
+    xtl_ofs = 0.0;
+  else if (o_xticks == BELOW)
+    xtl_ofs = -1.5 * charheight;  // kr
+  else if (o_xticks == ABOVE)
+    xtl_ofs = 1.5 * charheight;
+  
+  if (o_yaxis == NOAXIS || o_ytlabel == FALSE)
+    ytl_ofs = 0.0;
+  else if (o_yticks == LEFT)
+    ytl_ofs = -(1 + y_fldwid) * charwidth;
+  else if (o_yticks == RIGHT)
+    ytl_ofs = 1.5 * charwidth;
+
+  xt_min = xa_min;
+  yt_min = ya_min;
+  xt_max = xa_max;
+  yt_max = ya_max;
+
+  // see if need to shrink axis extents and/or tick extents 
+  if (xtl_ofs != 0.0 && s_ycross == FALSE) {
+    if (o_xticks == BELOW) {
+      ya_min += 2.5 * charheight;
+      yt_min = ya_min;
+    } else if (o_xticks == ABOVE) {
+      ya_min += 0.0;
+      yt_min = ya_min + 2.5 * charheight;
+    }
+  } else   // noaxis, no t-labels, or user set cross 
+    yt_min = ya_min;
+  
+  if (ytl_ofs != 0.0 && s_xcross == FALSE) {
+    if (o_yticks == LEFT) {
+      xa_min += (1 + y_fldwid) * charwidth;
+      xt_min = xa_min;
+    } else if (o_yticks == RIGHT) {
+      xa_min += 0.0;
+      xt_min = xa_min + ytl_ofs + y_fldwid * charwidth;
+    }
+  } else
+    xt_min = xa_min;
+
+  // decrease size of graph, if necessary, to accommadate space 
+  // between axis boundary and boundary of ticks 
+  double x_added_ticks = -1; // number of tick spaces added to axis 
+  double y_added_ticks = -1;
+  if (o_xaxis == NOAXIS || o_xtlabel == FALSE)
+    x_added_ticks = 0;
+  if (o_yaxis == NOAXIS || o_ytlabel == FALSE)
+    y_added_ticks = 0;
+  
+  if (o_grid == TRUE) {
     if (x_added_ticks < 0)
-       {
-           if (ez.o_yticks == LEFT || ez.s_ycross)
-               x_added_ticks = 1;
-           else
-               x_added_ticks = 2;
-       }
-
+      x_added_ticks = 2;
     if (y_added_ticks < 0)
-       {
-           if (ez.o_xticks == BELOW || ez.s_xcross)
-               y_added_ticks = 1;
-           else
-               y_added_ticks = 2;
+      y_added_ticks = 2;
+  }
+  
+  if (x_added_ticks < 0) {
+    if (o_yticks == LEFT || s_ycross)
+      x_added_ticks = 1;
+    else
+      x_added_ticks = 2;
+  }
+  
+  if (y_added_ticks < 0) {
+    if (o_xticks == BELOW || s_xcross)
+      y_added_ticks = 1;
+    else
+      y_added_ticks = 2;
+  }
+  
+  xn_tickinc = (xt_max - xt_min) / (x_nint + x_added_ticks);
+  yn_tickinc = (yt_max - yt_min) / (y_nint + y_added_ticks);
+  
+  xt_min += 0.5 * x_added_ticks * xn_tickinc;
+  xt_max -= 0.5 * x_added_ticks * xn_tickinc;
+  yt_min += 0.5 * y_added_ticks * yn_tickinc;
+  yt_max -= 0.5 * y_added_ticks * yn_tickinc;
+  
+  xgn_min = xt_min;
+  xgn_max = xt_max;
+  ygn_min = yt_min;
+  ygn_max = yt_max;
+
+  //------------------------------------------------------------------------
+  
+  m_xWorldScale = (xgn_max - xgn_min) / (xgw_max - xgw_min);
+  m_yWorldScale = (ygn_max - ygn_min) / (ygw_max - ygw_min);
+
+  // PLOT CURVES 
+  
+  rSGP.setLineStyle (SGP::LS_SOLID);
+  drawAxes();
+
+  // size of symbol in NDC 
+  double symwidth = charwidth;
+  double symheight = charheight;
+  
+  for (EZPlotCurveIterator iterCurve3 = m_vecCurves.begin(); iterCurve3 != m_vecCurves.end(); iterCurve3++) {
+      const EZPlotCurve& curve = **iterCurve3;
+
+      rSGP.setColor (curve.m_iColor);
+
+      if (curve.m_iLineStyle != SGP::LS_NOLINE) {
+       rSGP.setLineStyle (curve.m_iLineStyle);
+       double x = convertWorldToNDC_X (curve.x[0]);
+       double y = convertWorldToNDC_Y (curve.y[0]);
+       rSGP.moveAbs (x, y);
+       for (int i = 1; i < curve.m_iPointCount; i++) {
+           x = convertWorldToNDC_X (curve.x[i]);
+           y = convertWorldToNDC_Y (curve.y[i]);
+           rSGP.lineAbs (x, y);
        }
+      }
+      if (curve.m_iSymbol > 0) {
+       rSGP.setLineStyle (SGP::LS_SOLID);
+       double x = convertWorldToNDC_X (curve.x[0]);
+       double y = convertWorldToNDC_Y (curve.y[0]);
+       rSGP.moveAbs (x, y);
+       symbol (curve.m_iSymbol, symwidth, symheight);
+       for (int i = 1; i < curve.m_iPointCount; i++)
+         if (i % curve.m_iSymbolFreq == 0 || i == curve.m_iPointCount - 1) {
+           x = convertWorldToNDC_X (curve.x[i]);
+           y = convertWorldToNDC_Y (curve.y[i]);
+           rSGP.moveAbs (x, y);
+           symbol (curve.m_iSymbol, symwidth, symheight);
+         }
+      }
+  }
 
-    xn_tickinc = (xt_max - xt_min) / (x_nint + x_added_ticks);
-    yn_tickinc = (yt_max - yt_min) / (y_nint + y_added_ticks);
-
-    xt_min += 0.5 * x_added_ticks * xn_tickinc;
-    xt_max -= 0.5 * x_added_ticks * xn_tickinc;
-    yt_min += 0.5 * y_added_ticks * yn_tickinc;
-    yt_max -= 0.5 * y_added_ticks * yn_tickinc;
-
-    xgn_min = xt_min;
-    xgn_max = xt_max;
-    ygn_min = yt_min;
-    ygn_max = yt_max;
-
-    /*---------------------------------------------------------------------------*/
-
-    /* PLOT CURVES */
-
-    sgp2_line_style (LS_SOLID);
-    drawaxis();
-
-    /* Convert WC in graph boundary to axis boundary */
-    {
-       double xmin, xmax, ymin, ymax;
-
-       sgp2_window  (xgw_min, ygw_min, xgw_max, ygw_max);      /* Graph boundary */
-       sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
-
-       ndc_to_wc (xa_min, ya_min, &xmin, &ymin);       /* calc WC of axis */
-       ndc_to_wc (xa_max, ya_max, &xmax, &ymax);       /* boundaries */
-
-       sgp2_window  (xmin, ymin, xmax, ymax);          /* Set window to axis */
-       sgp2_viewport (xa_min, ya_min, xa_max, ya_max); /* boundaries */
-    }
-    symwidth = charwidth * (xgw_max - xgw_min);
-    symheight = charheight * (ygw_max - ygw_min);
-
-    for (ic = 0; ic < ez.i_numcurves; ic++) {
-       sgp2_color (ez.curve[ic].color);
-       if (ez.curve[ic].linestyle != LS_NOLINE) {
-           sgp2_line_style (ez.curve[ic].linestyle);
-           sgp2_polyline_abs (ez.curve[ic].x, ez.curve[ic].y, ez.curve[ic].numpts);
-       }
-       if (ez.curve[ic].symbol > 0) {
-           sgp2_line_style(LS_SOLID);
-           sgp2_move_abs (ez.curve[ic].x[0], ez.curve[ic].y[0]);
-           symbol (ez.curve[ic].symbol, symwidth, symheight);
-           for (i = 1; i < ez.curve[ic].numpts; i++)
-               if (i % ez.curve[ic].symfreq == 0 || i == ez.curve[ic].numpts - 1) {
-                   sgp2_move_abs (ez.curve[ic].x[i], ez.curve[ic].y[i]);
-                   symbol (ez.curve[ic].symbol, symwidth, symheight);
-               }
-       }
-    }
-    if (ez.o_ufinish == FALSE)
-       termgrf2 ();
-    return (TRUE);
 }
 
 
 /* NAME
- *   drawaxis                  INTERNAL routine to draw axis & label them
+ *   drawAxes                  INTERNAL routine to draw axis & label them
  *
  * SYNOPSIS
- *   drawaxis()
+ *   drawAxes()
  */
 
-static void drawaxis(void)
+
+void 
+EZPlot::drawAxes()
 {
-    double xticklen = 0, yticklen = 0; /* length of ticks in NDC */
-    double minorinc;           /* increment between minor axes */
-    double xaxispos, yaxispos; /* crossing of axes */
-    double x, y, x2, y2;
-    bool axis_near;                    /* TRUE if axis too close to print t-label */
-    int i, j;
-    char str[100];
-    char *numstr;
-
-    charsize (charwidth, charheight);
-    settextclr (1, -1);
-
-    if (ez.o_xticks == ABOVE)
-       xticklen = charheight;
-    else if (ez.o_xticks == BELOW)
-       xticklen = -charheight;
-
-    if (ez.o_yticks == RIGHT)
-       yticklen = charwidth;
-    else if (ez.o_yticks == LEFT)
-       yticklen = -charwidth;
-
-    sgp2_window  (xp_min, yp_min, xp_max, yp_max);
-    sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
-
-    if (strlen (ez.c_title) != 0) {
-       sgp2_move_abs (xa_min + (xa_max-xa_min)/2 - strlen(ez.c_title)*charwidth, title_row);
-       charsize (charwidth * 2.0, charheight * 2.0);
-       settextclr (ez.clr_title, -1);
-       sgp2_draw_text (ez.c_title);
-       charsize (charwidth, charheight);
+  double xticklen = 0, yticklen = 0; // length of ticks in NDC 
+  double minorinc;             // increment between minor axes 
+  double xaxispos, yaxispos;   // crossing of axes
+  double x, y, x2, y2;
+  bool axis_near;      // TRUE if axis too close to print t-label 
+  int i, j;
+  char str[256];
+  char *numstr;
+  
+  rSGP.setTextSize (charheight);
+  rSGP.setTextColor (1, -1);
+  
+  if (o_xticks == ABOVE)
+    xticklen = charheight;
+  else if (o_xticks == BELOW)
+    xticklen = -charheight;
+  
+  if (o_yticks == RIGHT)
+    yticklen = charwidth;
+  else if (o_yticks == LEFT)
+    yticklen = -charwidth;
+  
+  if (c_title.length() > 0) {
+    double wText, hText;
+    rSGP.setTextSize (charheight * 2.0);
+    rSGP.getTextExtent (c_title.c_str(), &wText, &hText);
+    rSGP.moveAbs (xa_min + (xa_max-xa_min)/2 - wText/2, title_row);
+    rSGP.setTextColor (clr_title, -1);
+    rSGP.drawText (c_title);
+    rSGP.setTextSize (charheight);
+  }
+  
+  if (o_grid == TRUE || o_box == TRUE) {
+    rSGP.setColor (clr_axis);
+    rSGP.moveAbs (xa_min, ya_min);
+    rSGP.lineAbs (xa_max, ya_min);
+    rSGP.lineAbs (xa_max, ya_max);
+    rSGP.lineAbs (xa_min, ya_max);
+    rSGP.lineAbs (xa_min, ya_min);
+  }
+  
+  // calculate position of axes 
+  
+  // x-axis 
+  if (s_ycross == TRUE) {      // convert users' world-coord 
+    xaxispos = convertWorldToNDC_Y (v_ycross);// axis to its position in NDC 
+    x = convertWorldToNDC_X (xgw_min);
+  } else
+    xaxispos = ya_min;
+  
+  // y-axis 
+  if (s_xcross == TRUE) {      // convert users' world-coord 
+    yaxispos = convertWorldToNDC_X (v_xcross);// axis to its NDC position 
+    y = convertWorldToNDC_Y (ygw_min);
+  } else
+    yaxispos = xa_min;
+  
+  /*-------------*/
+  /* draw x-axis */
+  /*-------------*/
+  
+  if (o_xaxis == LINEAR) {
+    // draw axis line 
+    
+    rSGP.setColor (clr_axis);
+    if (o_tag && !o_grid && !o_box && s_xcross) {
+      rSGP.moveAbs (xa_min, xaxispos - charheight);
+      rSGP.lineAbs (xa_min, xaxispos + charheight);
     }
-
-    if (ez.o_grid == TRUE || ez.o_box == TRUE) {
-       sgp2_color (ez.clr_axis);
-       sgp2_move_abs (xa_min, ya_min);
-       sgp2_line_abs (xa_max, ya_min);
-       sgp2_line_abs (xa_max, ya_max);
-       sgp2_line_abs (xa_min, ya_max);
-       sgp2_line_abs (xa_min, ya_min);
+    rSGP.moveAbs (xa_min, xaxispos);
+    rSGP.lineAbs (xa_max, xaxispos);
+    if (o_tag && !o_grid && !o_box) {
+      rSGP.moveAbs (xa_max, xaxispos - charheight);
+      rSGP.lineAbs (xa_max, xaxispos + charheight);
     }
-
-    /* calculate position of axes */
-
-    /* x-axis */
-    if (ez.s_ycross == TRUE) { /* convert users' world-coord */
-       xaxispos = ez.v_ycross; /* axis to its position in NDC */
-       sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
-       sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
-       x = xgw_min;
-       wc_to_ndc (x, xaxispos, &x, &xaxispos);
-    } else
-       xaxispos = ya_min;
-
-    /* y-axis */
-    if (ez.s_xcross == TRUE) { /* convert users' world-coord */
-       yaxispos = ez.v_xcross; /* axis to its NDC position */
-       sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
-       sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
-       y = ygw_min;
-       wc_to_ndc (yaxispos, y, &yaxispos, &y);
-    } else
-       yaxispos = xa_min;
-
-    /*-------------*/
-    /* draw x-axis */
-    /*-------------*/
-
-    if (ez.o_xaxis == LINEAR) {
-       sgp2_window (xp_min, yp_min, xp_max, yp_max);
-       sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
-
-       /* draw axis line */
-
-       sgp2_color (ez.clr_axis);
-       if (ez.o_tag && !ez.o_grid && !ez.o_box && ez.s_xcross) {
-           sgp2_move_abs (xa_min, xaxispos - charheight);
-           sgp2_line_abs (xa_min, xaxispos + charheight);
-       }
-       sgp2_move_abs (xa_min, xaxispos);
-       sgp2_line_abs (xa_max, xaxispos);
-       if (ez.o_tag && !ez.o_grid && !ez.o_box) {
-           sgp2_move_abs (xa_max, xaxispos - charheight);
-           sgp2_line_abs (xa_max, xaxispos + charheight);
-       }
-
-       if (ez.o_grid == TRUE) {
-           sgp2_color (ez.clr_grid);
-           for (i = 0; i <= x_nint; i++) {
-               sgp2_move_abs (xt_min + xn_tickinc * i, ya_max);
-               sgp2_line_abs (xt_min + xn_tickinc * i, ya_min);
-           }
+    
+    if (o_grid == TRUE) {
+      rSGP.setColor (clr_grid);
+      for (i = 0; i <= x_nint; i++) {
+       rSGP.moveAbs (xt_min + xn_tickinc * i, ya_max);
+       rSGP.lineAbs (xt_min + xn_tickinc * i, ya_min);
+      }
+    }
+    rSGP.moveAbs (xa_min + (xa_max-xa_min)/2 - c_xlabel.length()*charwidth, xlbl_row);
+    rSGP.setTextSize (charheight * 2.0);
+    rSGP.setTextColor (clr_label, -1);
+    rSGP.drawText (c_xlabel);
+    rSGP.setTextSize (charheight);
+    minorinc = xn_tickinc / (o_xminortick + 1);
+
+    for (i = 0; i <= x_nint; i++) {
+      x = xt_min + xn_tickinc * i;
+      rSGP.setColor (clr_axis);
+      rSGP.moveAbs (x, xaxispos);
+      rSGP.lineAbs (x, xaxispos + xticklen);
+      if (i != x_nint)
+       for (j = 1; j <= o_xminortick; j++) {
+         x2 = x + minorinc * j;
+         rSGP.moveAbs (x2, xaxispos);
+         rSGP.lineAbs (x2, xaxispos + TICKRATIO * xticklen);
        }
-       sgp2_move_abs (xa_min + (xa_max-xa_min)/2 - strlen(ez.c_xlabel)*charwidth, xlbl_row);
-       charsize (charwidth * 2.0, charheight * 2.0);
-       settextclr (ez.clr_label, -1);
-       sgp2_draw_text (ez.c_xlabel);
-       charsize (charwidth, charheight);
-       minorinc = xn_tickinc / (ez.o_xminortick + 1);
-
-       for (i = 0; i <= x_nint; i++) {
-           x = xt_min + xn_tickinc * i;
-           sgp2_color (ez.clr_axis);
-           sgp2_move_abs (x, xaxispos);
-           sgp2_line_abs (x, xaxispos + xticklen);
-           if (i != x_nint)
-               for (j = 1; j <= ez.o_xminortick; j++) {
-                   x2 = x + minorinc * j;
-                   sgp2_move_abs (x2, xaxispos);
-                   sgp2_line_abs (x2, xaxispos + TICKRATIO * xticklen);
-               }
-           axis_near = FALSE;
-           if (xaxispos + xtl_ofs > ya_min && ez.o_yaxis != NOAXIS) {
-               double xw, x, y, d;
-
-               xw = xgw_min + i * xw_tickinc;
-               sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
-               sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
-               wc_to_ndc (xw, y, &x, &y);
-               sgp2_window (xp_min, yp_min, xp_max, yp_max);
-               sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
-               d = x - yaxispos;
-               if (ez.o_yticks == RIGHT && d >= 0  && d < 0.9 * xn_tickinc)
-                   axis_near = TRUE;
-               if (ez.o_yticks == LEFT && d <= 0 && d > -0.9 * xn_tickinc)
-                   axis_near = TRUE;
-           }
-
-           if (ez.o_xtlabel == TRUE && axis_near == FALSE) {
-               snprintf (str, sizeof(str), x_numfmt, xgw_min + xw_tickinc * i);
-               numstr = str_skip_head (str, " ");
-               sgp2_move_abs (x-strlen(numstr)*charwidth/2,xaxispos + xtl_ofs);
-               settextclr (ez.clr_number, -1);
-               sgp2_draw_text (numstr);
-           }
+      axis_near = FALSE;
+      if (xaxispos + xtl_ofs > ya_min && o_yaxis != NOAXIS) {
+       double xw = xgw_min + i * xw_tickinc;
+       double x = convertWorldToNDC_X (xw);
+       double d = x - yaxispos;
+       if (o_yticks == RIGHT && d >= 0  && d < 0.9 * xn_tickinc)
+         axis_near = TRUE;
+       if (o_yticks == LEFT && d <= 0 && d > -0.9 * xn_tickinc)
+         axis_near = TRUE;
+      }
+
+      if (o_xtlabel == TRUE && axis_near == FALSE) {
+       snprintf (str, sizeof(str), x_numfmt, xgw_min + xw_tickinc * i);
+       numstr = str_skip_head (str, " ");
+       rSGP.moveAbs (x-strlen(numstr)*charwidth/2, xaxispos + xtl_ofs);
+       rSGP.setTextColor (clr_number, -1);
+       rSGP.drawText (numstr);
+      }
+    }
+  }            // X - Axis 
+  
+  
+  /*--------*/
+  /* y-axis */
+  /*--------*/
+  
+  if (o_yaxis == LINEAR) {
+    
+    rSGP.setColor (clr_axis);
+    if (o_tag && !o_grid && !o_box && s_ycross) {
+      rSGP.moveAbs (yaxispos - charwidth, ya_min);
+      rSGP.lineAbs (yaxispos + charwidth, ya_min);
+    }
+    rSGP.moveAbs (yaxispos, ya_min);
+    rSGP.lineAbs (yaxispos, ya_max);
+    if (o_tag && !o_grid && !o_box) {
+      rSGP.moveAbs (yaxispos - charwidth, ya_max);
+      rSGP.lineAbs (yaxispos + charwidth, ya_max);
+    }
+    
+    if (o_grid == TRUE) {
+      rSGP.setColor (clr_grid);
+      for (i = 0; i <= y_nint; i++) {
+       y = yt_min + yn_tickinc * i;
+       rSGP.moveAbs (xa_max, y);
+       rSGP.lineAbs (xa_min, y);
+      }
+    }
+    rSGP.moveAbs (ylbl_col, ya_min + (ya_max-ya_min)/2 - c_ylabel.length()*charheight);
+    rSGP.setTextAngle (HALFPI);
+    rSGP.setTextSize (2 * charheight);
+    rSGP.setTextColor (clr_label, -1);
+    rSGP.drawText (c_ylabel);
+    rSGP.setTextAngle (0.0);
+    rSGP.setTextSize (charheight);
+    minorinc = yn_tickinc / (o_yminortick + 1);
+    
+    for (i = 0; i <= y_nint; i++) {
+      y = yt_min + yn_tickinc * i;
+      rSGP.setColor (clr_axis);
+      rSGP.moveAbs (yaxispos, y);
+      rSGP.lineAbs (yaxispos + yticklen, y);
+      if (i != y_nint)
+       for (j = 1; j <= o_yminortick; j++) {
+         y2 = y + minorinc * j;
+         rSGP.moveAbs (yaxispos, y2);
+         rSGP.lineAbs (yaxispos + TICKRATIO * yticklen, y2);
        }
-    }          /* x - axis */
-
+      axis_near = FALSE;
+      if (yaxispos + ytl_ofs > xa_min && o_xaxis != NOAXIS) {
+       double yw = ygw_min + i * yw_tickinc;
+       double y = convertWorldToNDC_Y (yw);
+       double d = y - xaxispos;
+       if (o_xticks == ABOVE && d >= 0 && d < 0.9 * yn_tickinc)
+         axis_near = TRUE;
+       if (o_xticks == BELOW && d <= 0 && d > -0.9 * yn_tickinc)
+         axis_near = TRUE;
+      }
+      if (o_ytlabel == TRUE && axis_near == FALSE) {
+       snprintf (str, sizeof(str), y_numfmt, ygw_min + yw_tickinc * i);
+       rSGP.moveAbs (yaxispos + ytl_ofs, y + 0.5 * charheight);
+       rSGP.setTextColor (clr_number, -1);\r
+       rSGP.drawText (str);
+      }
+    }
+  }            // Y - Axis
+}
 
-    /*--------*/
-    /* y-axis */
-    /*--------*/
 
-    if (ez.o_yaxis == LINEAR) {
-       sgp2_window  (xp_min, yp_min, xp_max, yp_max);
-       sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
+void 
+EZPlot::symbol (int sym, double symwidth, double symheight)
+{
+  if (sym <= 0)
+    return;
+  
+  if (sym == SB_CROSS) {
+    rSGP.moveRel (-0.5 * symwidth, -0.5 * symheight);
+    rSGP.lineRel (symwidth, symheight);
+    rSGP.moveRel (-symwidth, 0.0);
+    rSGP.lineRel (symwidth, -symheight);
+    rSGP.moveRel (-0.5 * symwidth, 0.5 * symheight);
+  } else if (sym == SB_PLUS) {
+    rSGP.moveRel (-0.5 * symwidth, 0.0);
+    rSGP.lineRel (symwidth, 0.0);
+    rSGP.moveRel (-0.5 * symwidth, -0.5 * symheight);
+    rSGP.lineRel (0.0, symheight);
+    rSGP.moveRel (0.0, -0.5 * symheight);
+  } else if (sym == SB_BOX) {
+    rSGP.moveRel (-0.5 * symwidth, -0.5 * symheight);
+    rSGP.lineRel (symwidth, 0.0);
+    rSGP.lineRel (0.0, symheight);
+    rSGP.lineRel (-symwidth, 0.0);
+    rSGP.lineRel (0.0, -symheight);
+    rSGP.moveRel (0.5 * symwidth, 0.5 * symheight);
+  } else if (sym == SB_CIRCLE) {
+    rSGP.drawCircle (symwidth);
+  } else if (sym == SB_ERRORBAR) {
+    rSGP.moveRel (-0.5 * symwidth, 0.5 * symheight);
+    rSGP.lineRel (symwidth, 0.0);
+    rSGP.moveRel (-0.5 * symwidth, 0.0);
+    rSGP.lineRel (0.0, -symheight);
+    rSGP.moveRel (-0.5 * symwidth, 0.0);
+    rSGP.lineRel (symwidth, 0.0);
+    rSGP.moveRel (-0.5 * symwidth, 0.5 * symheight);
+  }
+}
 
-       sgp2_color (ez.clr_axis);
-       if (ez.o_tag && !ez.o_grid && !ez.o_box && ez.s_ycross) {
-           sgp2_move_abs (yaxispos - charwidth, ya_min);
-           sgp2_line_abs (yaxispos + charwidth, ya_min);
-       }
-       sgp2_move_abs (yaxispos, ya_min);
-       sgp2_line_abs (yaxispos, ya_max);
-       if (ez.o_tag && !ez.o_grid && !ez.o_box) {
-           sgp2_move_abs (yaxispos - charwidth, ya_max);
-           sgp2_line_abs (yaxispos + charwidth, ya_max);
-       }
 
-       if (ez.o_grid == TRUE) {
-           sgp2_color (ez.clr_grid);
-           for (i = 0; i <= y_nint; i++) {
-               y = yt_min + yn_tickinc * i;
-               sgp2_move_abs (xa_max, y);
-               sgp2_line_abs (xa_min, y);
-           }
-       }
-       sgp2_move_abs (ylbl_col,ya_min + (ya_max-ya_min)/2 - strlen(ez.c_ylabel)*charheight);
-       textangle (HALFPI);
-       charsize (2 * charheight, 2 * charwidth);       /* axis reversed */
-       settextclr (ez.clr_label, -1);
-       sgp2_draw_text (ez.c_ylabel);
-       textangle (0.0);
-       charsize (charwidth, charheight);
-       minorinc = yn_tickinc / (ez.o_yminortick + 1);
-
-       for (i = 0; i <= y_nint; i++) {
-           y = yt_min + yn_tickinc * i;
-           sgp2_color (ez.clr_axis);
-           sgp2_move_abs (yaxispos, y);
-           sgp2_line_abs (yaxispos + yticklen, y);
-           if (i != y_nint)
-               for (j = 1; j <= ez.o_yminortick; j++) {
-                   y2 = y + minorinc * j;
-                   sgp2_move_abs (yaxispos, y2);
-                   sgp2_line_abs (yaxispos + TICKRATIO * yticklen, y2);
-               }
-           axis_near = FALSE;
-           if (yaxispos + ytl_ofs > xa_min && ez.o_xaxis != NOAXIS) {
-               double yw, x, y, d;
-
-               yw = ygw_min + i * yw_tickinc;
-               sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
-               sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
-               wc_to_ndc (x, yw, &x, &y);
-               sgp2_window (xp_min, yp_min, xp_max, yp_max);
-               sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
-               d = y - xaxispos;
-               if (ez.o_xticks == ABOVE && d >= 0 && d < 0.9 * yn_tickinc)
-                   axis_near = TRUE;
-               if (ez.o_xticks == BELOW && d <= 0 && d > -0.9 * yn_tickinc)
-                   axis_near = TRUE;
-           }
-           if (ez.o_ytlabel == TRUE && axis_near == FALSE) {
-               snprintf (str, sizeof(str), y_numfmt, ygw_min + yw_tickinc * i);
-               sgp2_move_abs (yaxispos + ytl_ofs, y - 0.5 * charheight);
-               settextclr (ez.clr_number, -1);
-               sgp2_draw_text (str);
-           }
-       }
-    }          /* y - axis */
-}
 
+/* 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
+ */
 
-static void 
-symbol (int sym, double symwidth, double symheight)
+int 
+EZPlot::axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp)
 {
-    if (sym <= 0)
-       return;
-
-    if (sym == SB_CROSS) {
-       sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight);
-       sgp2_line_rel (symwidth, symheight);
-       sgp2_move_rel (-symwidth, 0.0);
-       sgp2_line_rel (symwidth, -symheight);
-       sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight);
-    } else if (sym == SB_PLUS) {
-       sgp2_move_rel (-0.5 * symwidth, 0.0);
-       sgp2_line_rel (symwidth, 0.0);
-       sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight);
-       sgp2_line_rel (0.0, symheight);
-       sgp2_move_rel (0.0, -0.5 * symheight);
-    } else if (sym == SB_BOX) {
-       sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight);
-       sgp2_line_rel (symwidth, 0.0);
-       sgp2_line_rel (0.0, symheight);
-       sgp2_line_rel (-symwidth, 0.0);
-       sgp2_line_rel (0.0, -symheight);
-       sgp2_move_rel (0.5 * symwidth, 0.5 * symheight);
-    } else if (sym == SB_CIRCLE) {
-       sgp2_draw_circle (symwidth);
-    } else if (sym == SB_ERRORBAR) {
-       sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight);
-       sgp2_line_rel (symwidth, 0.0);
-       sgp2_move_rel (-0.5 * symwidth, 0.0);
-       sgp2_line_rel (0.0, -symheight);
-       sgp2_move_rel (-0.5 * symwidth, 0.0);
-       sgp2_line_rel (symwidth, 0.0);
-       sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight);
-    }
+  if (min >= max || nint < 1) {
+    sys_error (ERR_WARNING, "Invalid params: min=%lf, max=%lf, num intervals=%d [axis_scale]", min, max, nint);
+    return (FALSE);
+  }
+  
+  double eps = 0.025;
+  double a = fabs(min);
+  if (fabs(min) < fabs(max))
+    a = fabs(max);
+  double scale = pow (10.0, floor(log10(a)));
+ loop:
+  double mina = min / scale;
+  double maxa = max / scale;
+  double d = (maxa - mina) / nint;
+  double j = d * eps;
+  double e = floor (log10(d));
+  double f = d / pow (10.0, e);
+  double 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;
+  double wdt = v * pow (10.0, e);
+  double g = floor (mina / wdt);
+    if (fabs(g + 1 - mina / wdt) < j)
+      g = g + 1;
+#if 1
+    g++;
+#endif
+  *minp = wdt * g;
+  double h = floor (maxa / wdt) + 1.0;
+  if (fabs(maxa / wdt + 1 - h) < j)
+     h = h - 1;
+#if 1
+    h--;
+#endif
+  *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);
 }
 
 
-void ezinit(void)
+/* 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)
 {
-    /* EZPLOT Variables */
-
-    charwidth = DEF_CHARWIDTH; /* KR_FIX: Make these ez.o_ variables */
-    charheight = DEF_CHARHEIGHT;
-
-    /* EZPLOT & EZSET Variables */
-
-    strcpy (ez.c_xlabel, "X axis");
-    strcpy (ez.c_ylabel, "Y axis");
-    strcpy (ez.c_title, "");
-    strcpy (ez.c_legend, "");
-
-    ezplot_firstcall = FALSE;
-
-    ez.i_numcurves = 0;
-    ez.i_plotimmediate = FALSE;
-
-    ez.o_reqcurves = 1;
-    ez.o_unknowncurves = FALSE;
-
-    ez.o_ustart = FALSE;
-    ez.o_ufinish = FALSE;
-
-    ez.o_xporigin = 0.0;
-    ez.o_yporigin = 0.0;
-    ez.o_xlength  = 1.0;
-    ez.o_ylength  = 1.0;
-
-    ez.o_xaxis = LINEAR;
-    ez.o_yaxis = LINEAR;
-
-    ez.o_grid = FALSE;
-    ez.o_box = FALSE;
-
-    ez.o_xmajortick = 10;
-    ez.o_ymajortick =  8;
-    ez.o_xminortick =  4;
-    ez.o_yminortick =  4;
-
-    ez.o_color = DEF_CURVE_CLR;
-    ez.o_symfreq = 1;
-    ez.o_symbol = -1;
-    ez.o_linestyle = LS_SOLID;
-
-    ez.o_xtlabel = TRUE;
-    ez.o_ytlabel = TRUE;
-    ez.o_xticks = BELOW;
-    ez.o_yticks = LEFT;
-
-    ez.o_legendbox = INSIDE;
-    ez.o_tag = FALSE;
-
-    ez.s_xtitle   = FALSE;
-    ez.s_ytitle   = FALSE;
-    ez.s_xcross   = FALSE;
-    ez.s_ycross   = FALSE;
-    ez.s_lxfrac   = FALSE;
-    ez.s_lyfrac   = FALSE;
-    ez.s_xlegend  = FALSE;
-    ez.s_ylegend  = FALSE;
-    ez.s_textsize = FALSE;
-
-    ez.d_usecrt = TRUE;
-    ez.d_useprt = FALSE;
-    ez.d_crtmode = DEF_CRTMODE;
-    ez.d_prtmode = PRTMODE_DEF;
-    ez.d_xprtbuf = XBUF_DEF;
-    ez.d_yprtbuf = YBUF_DEF;
-
-    ez.clr_axis   = C_WHITE;           /* set fixed colors */
-    ez.clr_title  = (C_CYAN+8);
-    ez.clr_label  = (C_CYAN+8);
-    ez.clr_legend = (C_RED+8);
-    ez.clr_number = (C_GREEN+8);
-    ez.clr_grid   = (C_BLACK+8);
+  double integer;
+  
+  modf (x, &integer);
+  
+  return (integer);
 }
 
-void ezfree(void)
+void 
+EZPlot::make_numfmt (char *fmtstr, int *fldwid, int *nfrac, double minval, double maxval, int nint)
 {
-    static char errmsg[] = "EZFREE in EZPLOT";
-    int i;
+  int wid, frac, expon;
+
+  double delta = (maxval - minval) / nint;
+  double absmin = fabs(minval);
+  double absmax = fabs(maxval);\r
+  if (absmin > absmax)\r
+       absmax = absmin;
+  double logt = log10( absmax );
+
+  if (fabs(logt) >= 6) {               // use exponential format 
+    if (fabs(logt) > 99)
+      expon = 5;               //  E+102 
+    else
+      expon = 4;               //  E+00 
     
-    for (i = 0; i < ez.i_numcurves; i++) {
-       delete ez.curve[i].x;
-       delete ez.curve[i].y;
-    }
-    ez.i_numcurves = 0;
-}
+    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;
+    sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "g");
+  } 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;
+    sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "f");
+  }
 
-void ezclear(void)
-{
-    ezfree();
-    ezinit();
+  *fldwid = wid;
+  *nfrac = frac;
 }
+