$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: pbristow_at_[hidden]
Date: 2007-12-20 07:14:06
Author: pbristow
Date: 2007-12-20 07:14:05 EST (Thu, 20 Dec 2007)
New Revision: 42201
URL: http://svn.boost.org/trac/boost/changeset/42201
Log:
Some improvements to layout of legend box.
Text files modified: 
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp |  4100 ++++++++++++++++++++------------------- 
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp            |    10                                         
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp            |  3203 +++++++++++++++---------------          
   3 files changed, 3669 insertions(+), 3644 deletions(-)
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp	2007-12-20 07:14:05 EST (Thu, 20 Dec 2007)
@@ -23,2231 +23,2249 @@
 
 namespace boost
 {
-namespace svg
-{
-namespace detail
-{
-
-  template <class Derived>
-  class axis_plot_frame
+  namespace svg
   {
-    // axis_plot_frame is used as base class, for example:
-    // class svg_1d_plot : public detail::axis_plot_frame<svg_1d_plot>
-    // class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
-  //protected:
-  public:
-    // --------------------------------------------------------------------
-    // We don't use the SVG coordinate transform because then text would
-    // be flipped. I'm considering using it to scale the image for resizes.
-    // --------------------------------------------------------------------
-
-    // protected member functions (defined below):
-
-    // void transform_point(double &x, double &y);
-    // void transform_x(double &x);
-    // void transform_y(double &y);
-    // void draw_x_minor_ticks(double j, path_element& tick_path, path_element& grid_path); // (& grid).
-    // void draw_x_major_ticks(double i, path_element& tick_path, path_element& grid_path); // (& grid).
-    // void draw_x_axis();
-    // void draw_legend();
-    // void draw_title();
-    // void adjust_limits(double& x, double& y);
-    // void draw_plot_point(double x, double y, g_element& g_ptr, const plot_point_style& sty);
-
-    // Clear functions.
-    // void clear_all(); // Calls all the other clear_* functions.
-    // void clear_legend();
-    // void clear_background();
-    // void clear_x_axis();
-    // void clear_y_axis();
-    // void clear_title();
-    // void clear_points();
-    // void clear_plot_background();
-    // void clear_grids();
-
-    const std::string strip(std::string s)
-    { // Ugly hack to remove unwanted sign and leading zero in exponent.
-      // TODO It alters the layout because space
-      // is still allowed for the longest string.
-      // Would need to work out the longest value label before calculate_plot_window.
-      // But should be useful for values that spill over into exponent format
-      // 'by accident' - when leading zeros are likely.
-      using std::string;
-      size_t j = s.find("e+000");
-      if (j != string::npos)
-      {
-        s.erase(j, 5); // remove "e+000"
-        goto ret;
-      }
-      j = s.find("e-000");
-      if (j != string::npos)
-      {
-        s.erase(j, 5); // remove "e-000"
-        goto ret;
-      }
-      j = s.find("e+00");
-      if (j != string::npos)
-      {
-        s.erase(j + 1, 3); // remove "+00"
-        goto ret;
-      }
 
-      j = s.find("e-00");
-      if (j != string::npos)
-      {
-        s.erase(j+2, 2); // remove "00", leave "-"
-        goto ret;
-      }
-      j = s.find("e+0");
-      if (j != string::npos)
-      {
-        s.erase(j + 1, 2); // remove "+0"
-        goto ret;
-      }
-      j = s.find("e-0");
-      if (j != string::npos)
-      {
-        s.erase(j+2, 1); // remove "0", leave "-"
-        goto ret;
-      }
-    ret:
-      return s;
-    } // const std::string strip(double d)
-
-    void transform_point(double& x, double& y)
-    { // Scale & shift both x & y to graph coordinate.
-      x = derived().x_scale * x + derived().x_shift;
-      y = derived().y_scale * y + derived().y_shift;
-      adjust_limits(x, y); // In case either hits max, min, infinity or NaN.
-    }
-    // TODO do we need to adjust_limit(x); // In case hits max, min, infinity or NaN?
-    // This implies that user's choice of X-axis range is wrong?
-    // So more drastic action like throwing might be least worst action?
-
-    void transform_x(double & x)
-    { // Scale and shift x only.
-      x = derived().x_scale * x + derived().x_shift;
-    }
-
-    void transform_y(double & y)
-    { // Scale and shift y only.
-      y = derived().y_scale * y + derived().y_shift;
-    }
-
-    void draw_x_minor_ticks(double value, path_element& tick_path, path_element& grid_path)
-    { // Draw X-axis minor ticks, and optional grid.
-      // Value is NOT (yet) shown beside the minor tick.
-      double x1(value);
-      transform_x(x1);
-      double y1(0.); // Start on the horizontal X-axis line.
-      double y2(derived().image.y_size());
+    enum legend_places
+    {  // Placing of legend box, if requested by legend_on(true).
+      inside = 0,  // Default place for inside is top left of plot window,
+      // exact location controlled by legend_top_left().
+      outside_left = -1, // Outside 
+      outside_right = +1,  // Default for outside.
+      outside_top = +2,
+      outside_bottom = -2
+    };
+
+    namespace detail
+    {
 
-      // Draw the minor grid, if wanted.
-      if(derived().use_x_minor_grid_)
+      template <class Derived>
+      class axis_plot_frame
       {
-        if(!derived().use_plot_window_)
-        {  // Use whole image.
-           // Make space for title and X-axis labels.
-          if(derived().use_title)
-          { // Allow text_margin_ * font_size around text (pixels).
-            y1 += derived().title_info.font_size() * derived().text_margin_;
+        // axis_plot_frame is used as base class, for example:
+        // class svg_1d_plot : public detail::axis_plot_frame<svg_1d_plot>
+        // class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
+        //protected:
+      public:
+        // --------------------------------------------------------------------
+        // We don't use the SVG coordinate transform because then text would
+        // be flipped. I'm considering using it to scale the image for resizes.
+        // --------------------------------------------------------------------
+
+        // protected member functions (defined below):
+
+        // void transform_point(double &x, double &y);
+        // void transform_x(double &x);
+        // void transform_y(double &y);
+        // void draw_x_minor_ticks(double j, path_element& tick_path, path_element& grid_path); // (& grid).
+        // void draw_x_major_ticks(double i, path_element& tick_path, path_element& grid_path); // (& grid).
+        // void draw_x_axis();
+        // void draw_legend();
+        // void draw_title();
+        // void adjust_limits(double& x, double& y);
+        // void draw_plot_point(double x, double y, g_element& g_ptr, const plot_point_style& sty);
+
+        // Clear functions.
+        // void clear_all(); // Calls all the other clear_* functions.
+        // void clear_legend();
+        // void clear_background();
+        // void clear_x_axis();
+        // void clear_y_axis();
+        // void clear_title();
+        // void clear_points();
+        // void clear_plot_background();
+        // void clear_grids();
+
+        const std::string strip(std::string s)
+        { // Ugly hack to remove unwanted sign and leading zero in exponent.
+          // TODO It alters the layout because space
+          // is still allowed for the longest string.
+          // Would need to work out the longest value label before calculate_plot_window.
+          // But should be useful for values that spill over into exponent format
+          // 'by accident' - when leading zeros are likely.
+          using std::string;
+          size_t j = s.find("e+000");
+          if (j != string::npos)
+          {
+            s.erase(j, 5); // remove "e+000"
+            goto ret;
           }
-          if(derived().use_x_label)
+          j = s.find("e-000");
+          if (j != string::npos)
           {
-            y2 -= derived().x_label_info.font_size() * derived().text_margin_;
+            s.erase(j, 5); // remove "e-000"
+            goto ret;
+          }
+          j = s.find("e+00");
+          if (j != string::npos)
+          {
+            s.erase(j + 1, 3); // remove "+00"
+            goto ret;
           }
-        }
-        else
-        { // use_plot_window_ == true.
-          y1 = derived().plot_y1 + 1; // Top. Why +1 and -1?
-          y2 = derived().plot_y2 - 1; // Bottom. Ensure *inside* window?
-        }
-        // Make sure that we are drawing inside the allowed window.
-        if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // allow = too?
-        {
-          //std::cerr << "Writing draw_x_minor_ticks grid inside plot window: x1 = "
-          //  << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
-          grid_path.M(x1, y1).L(x1, y2);
-        }
-        else
-        { // This will happen but is designed to be ignored!
-          // TODO check this is best. See comment in draw_x_axis
-           std::cerr << "Writing draw_x_minor_ticks grid OUTside plot window: x1 = "
-             << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
-        }
-      } // use_x_minor_grid
 
-      double x_tick_length = derived().x_minor_tick_length_;
-      if(derived().use_x_ticks_on_plot_window_)
-      { // Put minor ticks on the plot window border.
-        y1 = derived().plot_y2; // on the window line.
-        y2 = derived().plot_y2; // y1 = upper, y2 = lower end of tick.
-        if(derived().use_up_ticks)
-        { //
-          y1 -= x_tick_length; // up.
-        }
-        if (derived().use_down_ticks)
-        {
-          y2 += x_tick_length; // down.
-        }
-      }
-      else
-      { // Internal style, draw tick up and/or down from the X-axis line.
-        y1 = derived().x_axis; // X-axis horizontal line.
-        y2 = derived().x_axis;
-        if(derived().use_up_ticks)
-        {
-          y1 -=  x_tick_length; // up
-        }
-        if (derived().use_down_ticks)
-        {
-          y2 += x_tick_length; // down.
-        }
-      }
-      // Make sure that we are drawing inside the allowed window.
-      if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // TODO allow < or <=
-      {
-         //std::cerr << "Writing draw_x_minor_ticks inside plot window: x1 = "
-         // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
-        tick_path.M(x1, y1).L(x1, y2);
-        // No value labels on minor ticks, at present.
-      }
-      else
-      { // This will happen but is designed to be ignored!
-        //  TODO check this is best. See comment in draw_x_axis
-         //std::cerr << "Writing draw_x_minor_ticks OUTside plot window: x1 = "
-         // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
-      }
-    } // void draw_x_minor_ticks
-
-  void draw_x_major_ticks(double value, path_element& tick_path, path_element& grid_path)
-  { // draw ticks - and grid too if wanted.
-    // If use_x_major_labels then value may be shown beside the major tick.
-    double x1(value); //
-    transform_x(x1);
-    double y1(0.); // // y1 = upper,
-    double y2(derived().image.x_size()); // y2 = lower end of tick.
-    if(derived().use_x_major_grid_)
-    { // Draw major grid vertical line.
-      if(!derived().use_plot_window_)
-      { // Allow a modest margin around text of title and X-axis labels, if in use.
-        if(derived().use_title)
-        {
-          y1 += derived().title_info.font_size() * derived().text_margin_;
-        }
-        if(derived().use_x_label)
-        { // If use_x_major_labels then value may be shown beside the major tick.
-          y2 -= derived().x_label_info.font_size() * derived().text_margin_;
-        }
-      }
-      else
-      { // use_plot_window_ == true
-        y1 = derived().plot_y1; // Bottom of plot window.
-        y2 = derived().plot_y2; // Top of plot window.
-      }
-      grid_path.M(x1, y1).L(x1, y2); // Vertical grid line.
-    } // use_x_major_grid
-
-    // Draw major tick (perhaps as well as grid - ticks might be wider than grid).
-    // Make sure that we are drawing inside the allowed plot window.
-    if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // now <= 
-    {
-      double x_tick_length = derived().x_major_tick_length_;
-      if(derived().use_x_ticks_on_plot_window_)
-      { // Put the ticks on the plot window border (was external).
-        y1 = derived().plot_y2; // on the window line.
-        y2 = derived().plot_y2; // y1 = upper, y2 = lower.
-        if(derived().use_up_ticks)
-        {
-          y1 -= x_tick_length; // up
-        }
-        if (derived().use_down_ticks)
-        {
-          y2 += x_tick_length; // down.
-        }
-      }
-      else
-      { // Internal_style, draw tick from the central X axis line.
-        y1 = derived().x_axis; // X-axis line.
-        y2 = derived().x_axis;
-        if(derived().use_up_ticks)
+          j = s.find("e-00");
+          if (j != string::npos)
+          {
+            s.erase(j+2, 2); // remove "00", leave "-"
+            goto ret;
+          }
+          j = s.find("e+0");
+          if (j != string::npos)
+          {
+            s.erase(j + 1, 2); // remove "+0"
+            goto ret;
+          }
+          j = s.find("e-0");
+          if (j != string::npos)
+          {
+            s.erase(j+2, 1); // remove "0", leave "-"
+            goto ret;
+          }
+ret:
+          return s;
+        } // const std::string strip(double d)
+
+        void transform_point(double& x, double& y)
+        { // Scale & shift both x & y to graph coordinate.
+          x = derived().x_scale * x + derived().x_shift;
+          y = derived().y_scale * y + derived().y_shift;
+          adjust_limits(x, y); // In case either hits max, min, infinity or NaN.
+        }
+        // TODO do we need to adjust_limit(x); // In case hits max, min, infinity or NaN?
+        // This implies that user's choice of X-axis range is wrong?
+        // So more drastic action like throwing might be least worst action?
+
+        void transform_x(double & x)
+        { // Scale and shift x only.
+          x = derived().x_scale * x + derived().x_shift;
+        }
+
+        void transform_y(double & y)
+        { // Scale and shift y only.
+          y = derived().y_scale * y + derived().y_shift;
+        }
+
+        void draw_x_minor_ticks(double value, path_element& tick_path, path_element& grid_path)
+        { // Draw X-axis minor ticks, and optional grid.
+          // Value is NOT (yet) shown beside the minor tick.
+          double x1(value);
+          transform_x(x1);
+          double y1(0.); // Start on the horizontal X-axis line.
+          double y2(derived().image.y_size());
+
+          // Draw the minor grid, if wanted.
+          if(derived().use_x_minor_grid_)
+          {
+            if(!derived().use_plot_window_)
+            {  // Use whole image.
+              // Make space for title and X-axis labels.
+              if(derived().use_title)
+              { // Allow text_margin_ * font_size around text (pixels).
+                y1 += derived().title_info.font_size() * derived().text_margin_;
+              }
+              if(derived().use_x_label)
+              {
+                y2 -= derived().x_label_info.font_size() * derived().text_margin_;
+              }
+            }
+            else
+            { // use_plot_window_ == true.
+              y1 = derived().plot_y1 + 1; // Top. Why +1 and -1?
+              y2 = derived().plot_y2 - 1; // Bottom. Ensure *inside* window?
+            }
+            // Make sure that we are drawing inside the allowed window.
+            if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // allow = too?
+            {
+              //std::cerr << "Writing draw_x_minor_ticks grid inside plot window: x1 = "
+              //  << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+              grid_path.M(x1, y1).L(x1, y2);
+            }
+            else
+            { // This will happen but is designed to be ignored!
+              // TODO check this is best. See comment in draw_x_axis
+              //std::cerr << "Writing draw_x_minor_ticks grid OUTside plot window: x1 = "
+              //  << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+            }
+          } // use_x_minor_grid
+
+          double x_tick_length = derived().x_minor_tick_length_;
+          if(derived().use_x_ticks_on_plot_window_)
+          { // Put minor ticks on the plot window border.
+            y1 = derived().plot_y2; // on the window line.
+            y2 = derived().plot_y2; // y1 = upper, y2 = lower end of tick.
+            if(derived().use_up_ticks)
+            { //
+              y1 -= x_tick_length; // up.
+            }
+            if (derived().use_down_ticks)
+            {
+              y2 += x_tick_length; // down.
+            }
+          }
+          else
+          { // Internal style, draw tick up and/or down from the X-axis line.
+            y1 = derived().x_axis; // X-axis horizontal line.
+            y2 = derived().x_axis;
+            if(derived().use_up_ticks)
+            {
+              y1 -=  x_tick_length; // up
+            }
+            if (derived().use_down_ticks)
+            {
+              y2 += x_tick_length; // down.
+            }
+          }
+          // Make sure that we are drawing inside the allowed window.
+          if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // TODO allow < or <=
+          {
+            //std::cerr << "Writing draw_x_minor_ticks inside plot window: x1 = "
+            // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+            tick_path.M(x1, y1).L(x1, y2);
+            // No value labels on minor ticks, at present.
+          }
+          else
+          { // This will happen but is designed to be ignored!
+            //  TODO check this is best. See comment in draw_x_axis
+            //std::cerr << "Writing draw_x_minor_ticks OUTside plot window: x1 = "
+            // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+          }
+        } // void draw_x_minor_ticks
+
+        void draw_x_major_ticks(double value, path_element& tick_path, path_element& grid_path)
+        { // draw ticks - and grid too if wanted.
+          // If use_x_major_labels then value may be shown beside the major tick.
+          double x1(value); //
+          transform_x(x1);
+          double y1(0.); // // y1 = upper,
+          double y2(derived().image.x_size()); // y2 = lower end of tick.
+          if(derived().use_x_major_grid_)
+          { // Draw major grid vertical line.
+            if(!derived().use_plot_window_)
+            { // Allow a modest margin around text of title and X-axis labels, if in use.
+              if(derived().use_title)
+              {
+                y1 += derived().title_info.font_size() * derived().text_margin_;
+              }
+              if(derived().use_x_label)
+              { // If use_x_major_labels then value may be shown beside the major tick.
+                y2 -= derived().x_label_info.font_size() * derived().text_margin_;
+              }
+            }
+            else
+            { // use_plot_window_ == true
+              y1 = derived().plot_y1; // Bottom of plot window.
+              y2 = derived().plot_y2; // Top of plot window.
+            }
+            grid_path.M(x1, y1).L(x1, y2); // Vertical grid line.
+          } // use_x_major_grid
+
+          // Draw major tick (perhaps as well as grid - ticks might be wider than grid).
+          // Make sure that we are drawing inside the allowed plot window.
+          if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // now <= 
+          {
+            double x_tick_length = derived().x_major_tick_length_;
+            if(derived().use_x_ticks_on_plot_window_)
+            { // Put the ticks on the plot window border (was external).
+              y1 = derived().plot_y2; // on the window line.
+              y2 = derived().plot_y2; // y1 = upper, y2 = lower.
+              if(derived().use_up_ticks)
+              {
+                y1 -= x_tick_length; // up
+              }
+              if (derived().use_down_ticks)
+              {
+                y2 += x_tick_length; // down.
+              }
+            }
+            else
+            { // Internal_style, draw tick from the central X axis line.
+              y1 = derived().x_axis; // X-axis line.
+              y2 = derived().x_axis;
+              if(derived().use_up_ticks)
+              {
+                y1 -=  x_tick_length; // up
+              }
+              if (derived().use_down_ticks)
+              {
+                y2 += x_tick_length; // down.
+              }
+            }
+            tick_path.M(x1, y1).L(x1, y2);
+            // Leaving current position at the bottom end of the tick.
+
+            if(derived().use_x_major_labels)
+            { // Show value by the tick as "1.2" or "3.4e+000"...
+              std::stringstream label;
+              label.precision(derived().x_value_precision_);
+              label.flags(derived().x_value_ioflags_);
+              label << value; // "1.2" or "3.4e+000"...
+              if (derived().strip_e0s_)
+              { // remove unecessary e, +, leadings 0s
+                std::string v = strip(label.str());
+                label.str(v);
+              }
+              double y = y2; // bottom end of the tick.
+              align_style alignment = center_align;
+              if(derived().use_down_ticks)
+              {  // No need to shift if derived().use_up_ticks as labels are below the X-axis.
+                // y += derived().x_label_value.font_size();
+              }
+              if (derived().x_label_rotation_ == upward)
+              { // 
+                alignment = right_align;
+                //y += label.str().size() * derived().x_label_info.font_size();
+                // so the last digit will be by the tick.
+              }
+              else if((derived().x_label_rotation_ == downward)
+                || (derived().x_label_rotation_ == downhill))
+              { // start from tick and write down.
+                y += derived().x_label_value.font_size() * 0.5;
+                alignment = left_align;
+              }
+              else if(derived().x_label_rotation_ == horizontal)
+              {
+                y += derived().x_label_value.font_size() * 1.5;
+                alignment = center_align; // center on the tick.
+              }
+              else if(derived().x_label_rotation_ == uphill)
+              { // 45 slope up,
+                alignment = left_align; // Uphill to end at tick.
+                y += label.str().size() * derived().x_label_info.font_size() * 0.7;
+                // sloping up so need about sin(45) = 0.707 less space,
+                // so the last digit is by the tick.
+              }
+              else
+              { // 45 slope down.
+                alignment = left_align; // Assume downhill from tick,
+                // so no need for y adjustment.
+              }
+
+              { // ! use_x_ticks_on_plot_window_ = Internal - value labels just below horizontal X-axis.
+                if (derived().use_x_ticks_on_plot_window_ || ((value != 0) && derived().use_x_axis_lines_))
+                { // Avoid a "0" below the X-axis if it would be cut through by any internal vertical Y-axis line.
+                  derived().image.get_g_element(detail::PLOT_VALUE_LABELS).text(
+                    x1, y,
+                    label.str(),
+                    derived().x_label_value.font_size(), derived().x_label_value.font_family(),
+                    "", "", "", "", alignment, // center label on the tick.
+                    derived().x_label_rotation_);
+                }
+              }
+            } // use_x_major_labels
+          }
+          else
+          { // Outside plot window - so do nothing?  Warning?
+            //std::cerr << "Writing draw_x_major_ticks OUTside plot window: "
+            //  "x1 = " << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+          }
+        } // draw_x_major_ticks
+
+        void draw_x_axis()
         {
-          y1 -=  x_tick_length; // up
-        }
-        if (derived().use_down_ticks)
+          if(derived().use_x_axis_lines_)
+          { // Draw the horizontal X-axis line the full width of the plot window,
+            // perhaps including an addition in lieu of a major tick.
+            double xleft = derived().plot_x1;
+            double xright = derived().plot_x2;
+            if (derived().use_left_ticks && derived().use_x_ticks_on_plot_window_ 
+              && (derived().y_axis_position_ == y_intersect))
+            { // Extend the horizontal line left in lieu of longest tick.
+              xleft -= (std::max)(derived().y_minor_tick_length_, derived().y_major_tick_length_);
+            }
+            double y = derived().x_axis; // y = 0, (provided y range includes zero).
+            derived().image.get_g_element(PLOT_X_AXIS).line(
+              xleft, y,
+              xright, y);
+          }
+
+          // Access the paths for the ticks & grids, ready for additions.
+          path_element& minor_tick_path = derived().image.get_g_element(PLOT_X_MINOR_TICKS).path();
+          path_element& major_tick_path = derived().image.get_g_element(PLOT_X_MAJOR_TICKS).path();
+          path_element& minor_grid_path = derived().image.get_g_element(PLOT_X_MINOR_GRID).path();
+          path_element& major_grid_path = derived().image.get_g_element(PLOT_X_MAJOR_GRID).path();
+
+          // x_minor_jump is the interval between minor ticks.
+          double x_minor_jump = derived().x_major_interval_ /
+            (derived().x_num_minor_ticks_ + 1.);
+
+          // Draw the ticks on the positive side (right of zero).
+          for(double x = 0.; x <= derived().x_max; x += derived().x_major_interval_)
+          {
+            for(double j = x + x_minor_jump;
+              j < (x + derived().x_major_interval_) * (1. - 2 * std::numeric_limits<double>::epsilon());
+              j += x_minor_jump)
+              // Reduce test value by a few bits to avoid accumulated rounding error 
+              // that intermittently puts minor ticks *at same value as* major ticks.
+            { // This will output 'orphaned' minor ticks that are beyond the plot window,
+              // if the last major tick does not coincide with the plot window.
+              // These are just ignored in draw_x_minor_ticks.
+              // There might be 9 of them, so
+              // if you have the common 9 minor tick between major ticks!
+              // TODO this seems ugly - as does the negative ones below.
+              draw_x_minor_ticks(j, minor_tick_path, minor_grid_path);
+            } // for j
+            if ((x != 0. || !derived().use_y_axis_lines_) || derived().use_x_ticks_on_plot_window_)
+            { // Avoid a major tick at x == 0 where there *is* a vertical Y-axis line.
+              // (won't be Y-axis line for 1-D where the zero tick is always wanted).
+              draw_x_major_ticks(x, major_tick_path, major_grid_path);
+            }
+          }
+
+          // Draw the ticks on the negative side (left of zero).
+          for(double x = 0.; x >= derived().x_min; x -= derived().x_major_interval_)
+          {
+            // Draw minor ticks.
+            for(double j = x - x_minor_jump; 
+              j > (x - derived().x_major_interval_ + x_minor_jump) * (1. + 2 * std::numeric_limits<double>::epsilon());
+              // Increase test value by a few bits to avoid accumulated rounding error 
+              // that intermittently puts minor ticks *at same value as* major ticks.
+
+              j -= x_minor_jump)
+            {
+              if ((j != 0. || !derived().use_y_axis_lines_)  || derived().use_x_ticks_on_plot_window_)
+              { // Avoid a minor tick at x == 0 where there *is* a vertical Y-axis line.
+                // (won't be Y-axis line for 1-D where the zero tick is always wanted).
+                // But no tick means no value label 0 either unless on_plot_window.
+                draw_x_minor_ticks(j, minor_tick_path, minor_grid_path);
+              }
+            }
+            if ((x != 0. || !derived().use_y_axis_lines_) || derived().use_x_ticks_on_plot_window_)
+            { // Avoid a major tick at x == 0 where there *is* a vertical Y-axis line.
+              // (won't be Y-axis line for 1-D where the zero tick is always wanted).
+              // But no tick means no value label 0 either unless on_plot_window.
+              draw_x_major_ticks(x, major_tick_path, major_grid_path);
+            }
+          }
+        } // void draw_x_axis()
+
+        // --------------------------------------------------------------------
+        // Draw functions - legend & title (if any).
+        // --------------------------------------------------------------------
+
+        void draw_title()
         {
-          y2 += x_tick_length; // down.
-        }
-      }
-      tick_path.M(x1, y1).L(x1, y2);
-      // Leaving current position at the bottom end of the tick.
-
-      if(derived().use_x_major_labels)
-      { // Show value by the tick as "1.2" or "3.4e+000"...
-        std::stringstream label;
-        label.precision(derived().x_value_precision_);
-        label.flags(derived().x_value_ioflags_);
-        label << value; // "1.2" or "3.4e+000"...
-        if (derived().strip_e0s_)
-        { // remove unecessary e, +, leadings 0s
-           std::string v = strip(label.str());
-           label.str(v);
-        }
-        double y = y2; // bottom end of the tick.
-        align_style alignment = center_align;
-        if(derived().use_down_ticks)
-        {  // No need to shift if derived().use_up_ticks as labels are below the X-axis.
-          // y += derived().x_label_value.font_size();
-        }
-        if (derived().x_label_rotation_ == upward)
-        { // 
-          alignment = right_align;
-          //y += label.str().size() * derived().x_label_info.font_size();
-          // so the last digit will be by the tick.
-        }
-        else if((derived().x_label_rotation_ == downward)
-          || (derived().x_label_rotation_ == downhill))
-        { // start from tick and write down.
-          y += derived().x_label_value.font_size() * 0.5;
-          alignment = left_align;
-        }
-        else if(derived().x_label_rotation_ == horizontal)
+          // Update title_info with position.
+          derived().title_info.x(derived().image.x_size() / 2.); // Center of image.
+          // Assumes align = center_align.
+          double y;
+          if (derived().use_plot_window_)
+          {
+            y = derived().plot_y1; // plot_y1 IS now assigned in calculate_plot_window
+            // y is distance from top of image to top of plot window.
+            y /= derived().text_margin_; // Center the title in the space between.
+          }
+          else
+          { // Using all image.
+            y = derived().title_info.font_size() * derived().text_margin_; // Leave a linespace above.
+          }
+          derived().title_info.y(y);
+          derived().image.get_g_element(PLOT_TITLE).push_back(new text_element(derived().title_info));
+        } // void draw_title()
+
+        void size_legend_box()
+        { // Calculate how big the legend box needs to be.
+          // Store in legend_width_ and legend_height_
+          if(derived().use_legend == false)
+          { // No legend, so set values to show legend position invalid.
+            derived().legend_left_ = -1;
+            derived().legend_right_ = -1;
+            derived().legend_top_ = -1;
+            derived().legend_bottom_ = -1;
+            derived().legend_height_ = 0;
+            derived().legend_width_ = 0;
+            return;
+          }
+          else
+          { // use_legend == true
+            // Work out the size the legend box needs to be to hold the
+            // header, markers & text.
+            size_t num_series = derived().series.size(); // How many data series.
+            int font_size = derived().legend_header_.font_size();
+            int point_size =  derived().series[0].point_style.size();
+            // Use height of whichever is the biggest of point marker and font.
+            double spacing = (std::max)(font_size, point_size);
+            // std::cout << spacing <<  ' ' << font_size << ' ' << point_size << std::endl;
+            bool is_header = (derived().legend_header_.text() != "");
+
+            size_t longest = derived().legend_header_.text().size();
+            // 0 if no header.
+            for(unsigned int i = 0; i < num_series; ++i)
+            { // Find the longest text in all the data series.
+              std::string s = derived().series[i].title;
+              size_t siz = s.size();
+              if (siz > longest)
+              {
+                longest = siz;
+              }
+            } // for
+            std::cout.flags(std::ios_base::dec);
+            std::cout << "\nLongest legend header or data descriptor " << longest << " chars" << std::endl; // TODO remove.
+
+            const double wh = 0.7; // TODO share a common value?
+            // font_size is not exact because width varies but use 0.7.
+            derived().legend_width_ = (0 + longest) * wh * font_size;
+            // Allow for a leading space, longest 
+            // & trailing space before box margin.
+            if (derived().use_line)
+            { // colored line marker.
+              derived().legend_width_ += spacing * 2.;
+            }
+            if(derived().series[0].point_style.shape() != none)
+            { // colored data point marker, cross, round... & space
+              derived().legend_width_ += 2 * derived().series[0].point_style.size();
+            }
+            // else no point marker.
+
+            // legend_height must be *at least* enough for
+            // any legend header and text_margin_s around it
+            // (if any) plus a text_margin_ top and bottom.
+            // Add more height depending on the number of lines of text.
+            derived().legend_height_ = spacing; // At top
+            if (is_header) // is a legend header line.
+            {
+              derived().legend_height_ += 2 * font_size; // text & space after.
+            }
+            derived().legend_height_ += num_series * spacing * 2; // Space for the data point symbols & text.
+          } // use_legend == true
+
+          std::cout << "Legend width " << derived().legend_width_
+            << ", height " << derived().legend_height_ << std::endl;
+        } //  void size_legend_box()
+
+        void place_legend_box()
         {
-          y += derived().x_label_value.font_size() * 1.5;
-          alignment = center_align; // center on the tick.
-        }
-        else if(derived().x_label_rotation_ == uphill)
-        { // 45 slope up,
-          alignment = left_align; // Uphill to end at tick.
-          y += label.str().size() * derived().x_label_info.font_size() * 0.7;
-          // sloping up so need about sin(45) = 0.707 less space,
-          // so the last digit is by the tick.
-        }
-        else
-        { // 45 slope down.
-          alignment = left_align; // Assume downhill from tick,
-          // so no need for y adjustment.
-        }
+          if(derived().use_legend) // Legend box required.
+          {
+            derived().use_outside_legend_ = true; // Unless proves to be inside.
+            switch (derived().legend_place_)
+            {
+            case inside:
+              derived().use_outside_legend_ = false;
+              if (derived().legend_left_ == -1)
+              { // Legend box position NOT been set by legend_top_left.
+                // Default inside position is top left of plot window.
+                derived().legend_left_ = derived().plot_x1;
+                derived().legend_right_ = derived().plot_x1 + derived().legend_width_;
+                derived().plot_x1 = derived().legend_right_;
+                derived().legend_top_ = derived().plot_y1; // Level with top of plot window.
+                if (derived().use_title)
+                {
+                  derived().legend_top_ += derived().title_font_size() * 2.; // below title.
+                }
+                derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
+             }
+              else
+              { // Legend position has been specified by legend_top_left.
+                break;
+              }
+              break;
+                // If outside then reserve space for legend by reducing plot window.
+            case outside_right:
+              derived().legend_right_ = derived().plot_x2; // right image edge less border.
+              derived().legend_right_ -= derived().y_label_font_size() * 2.; // space from right edge.
+              derived().legend_left_ = derived().legend_right_ - derived().legend_width_;
+              derived().plot_x2 = derived().legend_left_; // Narrow plot window from left.
+              derived().plot_x2 -= derived().y_label_font_size() * 2.; // space.
+              derived().legend_top_ = derived().plot_y1; // Level with top of plot window.
+              derived().legend_top_ +=  derived().y_label_font_size() * 2.; // TODO ???
+              derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
+              break;
+            case outside_left:
+              // TODO implement.
+              break;
+            case outside_top:
+              break;
+            case outside_bottom:
+              break;
+              } // switch
+
+            std::cout << "Legend: left " << derived().legend_left_ 
+                << ", right " << derived().legend_right_
+                << ", top " << derived().legend_top_
+                << ", bottom " << derived().legend_bottom_
+                << std::endl;
+
+              // Check if the location requested will fit,
+              // now that we know the size of box needed.
+              if ( (derived().legend_left_ < 0) || (derived().legend_left_ > derived().image.x_size()))
+              { // left outside image?
+                std::cout << "Legend top left " << derived().legend_left_
+                  << " is outside image size = " << derived().image.x_size() << std::endl;
+              }
+              if ((derived().legend_right_ < 0) || (derived().legend_right_ > derived().image.x_size()))
+              { // right outside image?
+                std::cout << "Legend top right " << derived().legend_right_
+                  << " is outside image size = " << derived().image.x_size() << std::endl;
+              }
+              if ((derived().legend_top_ < 0) || (derived().legend_top_ > derived().image.y_size()))
+              { // top outside image?
+                std::cout << "Legend top " << derived().legend_top_
+                  << " outside image!" << derived().image.y_size() << std::endl;
+              }
+              if ((derived().legend_bottom_  < 0 ) || (derived().legend_bottom_ > derived().image.y_size()))
+              { // bottom outside image?
+                std::cout << "Legend bottom " << derived().legend_bottom_
+                  << " outside " << derived().image.y_size() << std::endl;
+              }
+
+              // Draw border box round legend.
+              g_element* g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_BACKGROUND));
+              g_ptr->push_back(new
+                rect_element(derived().legend_left_, derived().legend_top_, derived().legend_width_, derived().legend_height_));
+            } // if use_legend
+          } //  void calculate_legend_box()
+
+          void draw_legend()
+          {
+            // size_t num_points = derived().series.size();
+            int font_size = derived().legend_header_.font_size();
+            int point_size =  derived().series[0].point_style.size();
+            // Use whichever is the biggest of point marker and font.
+
+            double spacing = (std::max)(font_size, point_size);
+            // std::cerr << spacing <<  ' ' << font_size << ' ' << point_size << endl;
+            bool is_header = (derived().legend_header_.text() != "");
+
+            // TODO use saved version.
+            size_t longest = 0;
+            for(unsigned int i = 0; i < derived().series.size(); ++i)
+            { // Find the longest text in all the data series.
+              std::string s = derived().series[i].title;
+              size_t siz = s.size();
+              if (siz > longest)
+              {
+                longest = siz;
+              }
+            }
+            // Assume legend box position has already been sized by calculate_legend_box.
+            double legend_x_start = derived().legend_left_; // Saved box location.
+            double legend_width = derived().legend_width_;
+            double legend_y_start = derived().legend_top_; 
+            double legend_height = derived().legend_height_;
+
+            // Draw border box round legend.
+            g_element* g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_BACKGROUND));
+            g_ptr->push_back(new
+              rect_element(legend_x_start, legend_y_start, legend_width, legend_height));
+
+            double legend_y_pos = legend_y_start + derived().text_margin_ * spacing;
+            if (is_header)
+            { // Draw the legend header text "My Plot Legend".
+              derived().legend_header_.x(legend_x_start + legend_width / 2.); // / 2. to center in legend box.
+              derived().legend_header_.y(legend_y_pos);
+              derived().image.get_g_element(PLOT_LEGEND_TEXT).push_back(new
+                text_element(derived().legend_header_));
+              legend_y_pos += 2 * spacing;
+            }
+
+            g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_POINTS));
+            g_element* g_inner_ptr = g_ptr;
+            g_inner_ptr = &(derived().image.get_g_element(PLOT_LEGEND_TEXT));
+
+            for(unsigned int i = 0; i < derived().series.size(); ++i)
+            { // Show point marker, text info and perhaps line for all the data series.
+              double legend_x_pos = legend_x_start;
+              g_inner_ptr = &(g_ptr->add_g_element());
+              // Use both stroke colors from the point's style.
+              g_inner_ptr->style()
+                .stroke_color(derived().series[i].point_style.stroke_color_);
+              g_inner_ptr->style().stroke_width(2); // TODO create a global for this
+
+              if(derived().series[i].point_style.shape() != none)
+              {
+                draw_plot_point( // Plot point like circle, square...
+                  legend_x_start + spacing / 2, // space before point marker.
+                  legend_y_pos,
+                  *g_inner_ptr,
+                  derived().series[i].point_style);
+                legend_x_pos += 1.0 * spacing;
+              }
+
+              // Line markers  - only really applicable to 2-D sets plot_line_style,
+              if (derived().use_line)
+              { // Need to draw a short line to show color for that data series.
+                g_inner_ptr->style() // Use fill & stroke colors from line style.
+                  .stroke_color(derived().series[i].line_style.color);
+                g_inner_ptr->push_back(new line_element(
+                  legend_x_pos + spacing /2., // half space leading space
+                  legend_y_pos,
+                  legend_x_pos + spacing * 2., // line sample is two char long.
+                  legend_y_pos));
+                legend_x_pos += 2.5 * spacing; // short line & half space.
+              } // use_line
+
+              // Legend text for each Data Series added to the plot.
+              g_inner_ptr = &(derived().image.get_g_element(PLOT_LEGEND_TEXT));
+              g_inner_ptr->push_back(new text_element(
+                legend_x_pos, // allow space for the marker.
+                legend_y_pos,
+                derived().series[i].title, // Text for this data series.
+                derived().legend_header_.font_size(), // font size &
+                derived().legend_header_.font_family(), // font family.
+                "", "", "", "",
+                left_align));
+              legend_y_pos += 2 * spacing;
+            } // for
+          } // void draw_legend()
+
+          void draw_x_label()
+          {
+            // color is set in constructor.
+            //image.get_g_element(detail::PLOT_X_LABEL).style().stroke_color(black);
+            // and using y_label_color(color)
+
+            std::string label = derived().x_label_info.text(); // x_axis label, and optional units.
+            if (derived().use_x_label_units && (derived().x_units_info.text() != ""))
+            { // Append the units, if any, providing brackets ().
+              label += "  (" + derived().x_units_info.text() + ")";
+            }
+            // Simplest to start from the bottom of the image.
+            // and move up to give enough space for the X-axis label.
+
+            double y = derived().image.y_size();  // bottom edge of image.
+            y -= derived().x_label_font_size(); // Up enough for a space underneath label.
+            derived().image.get_g_element(PLOT_X_LABEL).push_back(new text_element(
+              ( // x position relative to the x-axis which is middle of plot window.
+              derived().plot_x2 + derived().plot_x1) / 2,  // x coordinate - middle.
+              y, // Up from image bottom edge.
+              label,
+              derived().x_label_font_size(),
+              derived().x_label_font_family(), "", "", "", "", center_align, horizontal)
+              );
+          } // void draw_x_label()
+
+          // TODO split into adjust_limit(double& x) and call twice?,
+          // and TODO use to check 1-D for limit values too?
+          void adjust_limits(double& x, double& y)
+          { // If value reaches limit of max, min, infinity,
+            // use the appropriate plot min or max.
+            if(detail::limit_max(x))
+            {
+              x = derived().plot_x2;
+            }
+            if(detail::limit_max(y))
+            {
+              y = derived().plot_y1;
+            }
+            if(detail::limit_min(x))
+            {
+              x = derived().plot_x1;
+            }
+            if(detail::limit_min(y))
+            {
+              y = derived().plot_y1;
+            }
+            // If value is NaN, use zero instead.
+            // TODO Do we want/get a different color or shape for NaNs??
+            if(detail::limit_NaN(x))
+            {
+              x = 0;
+              transform_x(x);
+            }
+            if(detail::limit_NaN(y))
+            {
+              y = 0;
+              transform_y(y);
+            }
+          } // void adjust_limits
+
+          void draw_plot_point(double x, double y,
+            g_element& g_ptr,
+            const plot_point_style& sty)
+          {
+            int size = sty.size_;
+            double half_size = size / 2.;
 
-        { // ! use_x_ticks_on_plot_window_ = Internal - value labels just below horizontal X-axis.
-          if (derived().use_x_ticks_on_plot_window_ || ((value != 0) && derived().use_x_axis_lines_))
-          { // Avoid a "0" below the X-axis if it would be cut through by any internal vertical Y-axis line.
-           derived().image.get_g_element(detail::PLOT_VALUE_LABELS).text(
-              x1, y,
-              label.str(),
-              derived().x_label_value.font_size(), derived().x_label_value.font_family(),
-              "", "", "", "", alignment, // center label on the tick.
-              derived().x_label_rotation_);
+            // For 1-D plots, the points do not *need* to be centered on the X-axis,
+            // and putting them just above, or sitting on, the X-axis is much clearer.
+            // For 2-D plots, the symbol center should, of course,
+            // be *centered exactly* on x, y.
+            // circle and ellipse are naturally centered on the point.
+            // for rect x and y half_size offset centers square on the point.
+            // But symbols are in a rectangular box and the offset is different for x & y
+            // even assuming that the symbol is centered in the rectangle.
+            // the vertical and horizontal ticks are deliberately offset above the axes.
+            // TODO Not sure this is fully resolved.
+
+            switch(sty.shape_) // from enum point_shape none, round, square, point, egg
+            {
+            case round:
+              g_ptr.circle(x, y, half_size);
+              break;
+            case square:
+              g_ptr.rect(x - half_size, y - half_size, size, size);
+              break;
+            case egg:
+              g_ptr.ellipse(x, y, half_size, size * 2.); // Tall thin egg!
+              break;
+
+              // Offset from center is not an issue with vertical or horizontal ticks.
+              // TODO stroke color of line seems to be FILL color, not the stroke color.
+              // This is OK-ish, but I'm not sure why.
+
+              //svg_color sc = sty.stroke_color;
+              //svg_color fc = sty.fill_color;
+
+            case vertical_tick: // Especially neat for 1-D points.
+              g_ptr.line(x, y, x , y - size); // tick up from axis.
+              break;
+            case vertical_line:
+              g_ptr.line(x, y + size, x , y - size); // line up & down from axis.
+              break;
+            case horizontal_tick:
+              // horizontal_tick is pretty useless for 1-D because the horizontal line is on the X-axis.
+              g_ptr.line(x, y, x + size, y ); // tick right from axis.
+              break;
+            case horizontal_line:
+              g_ptr.line(x, y - size, x + size, y ); // line left & right from axis.
+              // horizontal_line is pretty useless for 1-D because the horizontal line is on the X-axis.
+              break;
+
+            case symbol:
+              g_ptr.text(x, y + half_size, sty.symbols_, size, "Lucida Sans Unicode"); // symbol(s), size and centre.
+              // TODO Need to provide way to set style.symbols when Boost.Parameter is unravelled.
+
+              // Unicode symbols that work on most browsers are listed at
+              // boost\math_toolkit\libs\math\doc\sf_and_dist\html4_symbols.qbk,
+              // http://www.htmlhelp.com/reference/html40/entities/symbols.html
+              // and  http://www.alanwood.net/demos/ent4_frame.html
+              // The Unicode value in decimal 9830 or hex x2666 must be prefixed with & and terminated with ;
+              // for example &x2666; for xml
+              // and then enveloped with "" to convert to a std::string, for example: "♦" for diamond.
+
+              break;
+            case diamond:
+              g_ptr.text(x, y, "♦", size, "Lucida Sans Unicode");
+              // size / 4. puts bottom tip on the X-axis,
+              // size / 2. put center above the X-axis
+              // x, y, put on the X-axis - probably what is needed for 2-D plots.
+              // diamond, spades, clubs & hearts fill with expected fill_color.
+              break;
+            case asterisk:
+              g_ptr.text(x, y - size / 3., "∗", size, "Lucida Sans Unicode");
+              // asterisk is black filled.
+              // size /3 puts the bottom tip on the X-axis.
+              break;
+            case lozenge:
+              g_ptr.text(x, y - size / 3., "◊", size, "Lucida Sans Unicode");
+              // size / 3 to get tip of lozenge just on the X-axis.
+              // lozenge seems not to fill?
+              break;
+            case club:
+              g_ptr.text(x, y, "♣", size, "Lucida Sans Unicode");
+              // x, y, puts club just on the X-axis
+              break;
+            case spade:
+              g_ptr.text(x, y, "♠", size, "Lucida Sans Unicode");
+              //
+              break;
+            case heart:
+              g_ptr.text(x, y , "♥", size, "Lucida Sans Unicode");
+              //
+              break;
+            case cone: // Pointing down triangle.
+              g_ptr.triangle(x - half_size, y - size, x + half_size, y - size, x, y, false);
+              // Last point puts the bottom tip of the triangle on the X-axis.
+              // This may not be wanted for 2-D.
+              break;
+            case cross:
+              g_ptr.line(x, y + size, x , y - size); // line up & down from axis,
+              g_ptr.line(x, y - size, x + size, y ); // & line left & right from axis.
+              // Cross is pretty useless for 1-D because the horizontal line is on the X-axis.
+
+              break;
+              // TODO Other point_shapes do nothing yet.
+            }
+          } // void draw_plot_point
+
+          // -----------------------------------------------------------------
+          // Clear Functions.
+          // When writing to multiple documents, the contents of the plot
+          // may change significantly between. Rather than figuring out what
+          // has and has not changed, just erase the contents of the
+          // legend, title... in the document and start over.
+          // -----------------------------------------------------------------
+
+          void clear_all()
+          {
+            clear_legend();
+            clear_background();
+            clear_x_axis();
+            clear_y_axis();
+            clear_title();
+            clear_points();
+            clear_plot_background();
+            clear_grids();
           }
-        }
-      } // use_x_major_labels
-    }
-    else
-    { // Outside plot window - so do nothing?  Warning?
-      //std::cerr << "Writing draw_x_major_ticks OUTside plot window: "
-      //  "x1 = " << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
-    }
-  } // draw_x_major_ticks
 
-  void draw_x_axis()
-  {
-    if(derived().use_x_axis_lines_)
-    { // Draw the horizontal X-axis line the full width of the plot window,
-      // perhaps including an addition in lieu of a major tick.
-      double xleft = derived().plot_x1;
-      double xright = derived().plot_x2;
-      if (derived().use_left_ticks && derived().use_x_ticks_on_plot_window_ 
-        && (derived().y_axis_position_ == y_intersect))
-      { // Extend the horizontal line left in lieu of longest tick.
-        xleft -= (std::max)(derived().y_minor_tick_length_, derived().y_major_tick_length_);
-      }
-      double y = derived().x_axis; // y = 0, (provided y range includes zero).
-      derived().image.get_g_element(PLOT_X_AXIS).line(
-        xleft, y,
-        xright, y);
-    }
-
-    // Access the paths for the ticks & grids, ready for additions.
-    path_element& minor_tick_path = derived().image.get_g_element(PLOT_X_MINOR_TICKS).path();
-    path_element& major_tick_path = derived().image.get_g_element(PLOT_X_MAJOR_TICKS).path();
-    path_element& minor_grid_path = derived().image.get_g_element(PLOT_X_MINOR_GRID).path();
-    path_element& major_grid_path = derived().image.get_g_element(PLOT_X_MAJOR_GRID).path();
-
-    // x_minor_jump is the interval between minor ticks.
-    double x_minor_jump = derived().x_major_interval_ /
-      (derived().x_num_minor_ticks_ + 1.);
+          void clear_background()
+          {
+            derived().image.get_g_element(PLOT_BACKGROUND).clear();
+          }
 
-    // Draw the ticks on the positive side (right of zero).
-    for(double x = 0.; x <= derived().x_max; x += derived().x_major_interval_)
-    {
-      for(double j = x + x_minor_jump;
-        j < (x + derived().x_major_interval_) * (1. - 2 * std::numeric_limits<double>::epsilon());
-        j += x_minor_jump)
-        // Reduce test value by a few bits to avoid accumulated rounding error 
-        // that intermittently puts minor ticks *at same value as* major ticks.
-      { // This will output 'orphaned' minor ticks that are beyond the plot window,
-        // if the last major tick does not coincide with the plot window.
-        // These are just ignored in draw_x_minor_ticks.
-        // There might be 9 of them, so
-        // if you have the common 9 minor tick between major ticks!
-        // TODO this seems ugly - as does the negative ones below.
-        draw_x_minor_ticks(j, minor_tick_path, minor_grid_path);
-      } // for j
-      if ((x != 0. || !derived().use_y_axis_lines_) || derived().use_x_ticks_on_plot_window_)
-      { // Avoid a major tick at x == 0 where there *is* a vertical Y-axis line.
-        // (won't be Y-axis line for 1-D where the zero tick is always wanted).
-        draw_x_major_ticks(x, major_tick_path, major_grid_path);
-      }
-    }
+          void clear_title()
+          {
+            derived().image.get_g_element(PLOT_TITLE).clear();
+          }
 
-    // Draw the ticks on the negative side (left of zero).
-    for(double x = 0.; x >= derived().x_min; x -= derived().x_major_interval_)
-    {
-      // Draw minor ticks.
-      for(double j = x - x_minor_jump; 
-        j > (x - derived().x_major_interval_ + x_minor_jump) * (1. + 2 * std::numeric_limits<double>::epsilon());
-        // Increase test value by a few bits to avoid accumulated rounding error 
-        // that intermittently puts minor ticks *at same value as* major ticks.
+          void clear_points()
+          {
+            derived().image.get_g_element(PLOT_DATA_POINTS).clear();
+          }
 
-        j -= x_minor_jump)
-      {
-        if ((j != 0. || !derived().use_y_axis_lines_)  || derived().use_x_ticks_on_plot_window_)
-        { // Avoid a minor tick at x == 0 where there *is* a vertical Y-axis line.
-          // (won't be Y-axis line for 1-D where the zero tick is always wanted).
-          // But no tick means no value label 0 either unless on_plot_window.
-          draw_x_minor_ticks(j, minor_tick_path, minor_grid_path);
-        }
-      }
-      if ((x != 0. || !derived().use_y_axis_lines_) || derived().use_x_ticks_on_plot_window_)
-      { // Avoid a major tick at x == 0 where there *is* a vertical Y-axis line.
-        // (won't be Y-axis line for 1-D where the zero tick is always wanted).
-        // But no tick means no value label 0 either unless on_plot_window.
-        draw_x_major_ticks(x, major_tick_path, major_grid_path);
-      }
-    }
-  } // void draw_x_axis()
-
-  // --------------------------------------------------------------------
-  // Draw functions - legend & title (if any).
-  // --------------------------------------------------------------------
+          void clear_plot_background()
+          {
+            derived().image.get_g_element(PLOT_WINDOW_BACKGROUND).clear();
+          }
 
-  void draw_title()
-  {
-    // Update title_info with position.
-    derived().title_info.x(derived().image.x_size() / 2.); // Center of image.
-    // Assumes align = center_align.
-    double y;
-    if (derived().use_plot_window_)
-    {
-       y = derived().plot_y1; // plot_y1 IS now assigned in calculate_plot_window
-       // y is distance from top of image to top of plot window.
-       y /= derived().text_margin_; // Center the title in the space between.
-    }
-    else
-    { // Using all image.
-      y = derived().title_info.font_size() * derived().text_margin_; // Leave a linespace above.
-    }
-    derived().title_info.y(y);
-    derived().image.get_g_element(PLOT_TITLE).push_back(new text_element(derived().title_info));
-  } // void draw_title()
+          void clear_legend()
+          {
+            derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).clear();
+            derived().image.get_g_element(PLOT_LEGEND_POINTS).clear();
+            derived().image.get_g_element(PLOT_LEGEND_TEXT).clear();
+          }
 
-  void calculate_legend_box()
-  {
-    if(derived().use_legend == false)
-    { // No legend.
-      // TODO might this overwrite some previous useful values?
-      // Set values to show legend position invalid.
-      derived().legend_x1_ = -1;
-      derived().legend_x2_ = -1;
-      derived().legend_y1_ = -1;
-      derived().legend_y2_ = -1;
-      return;
-    }
-
-    // Work out the size the legend box needs to be to hold the
-    // header, markers & text.
-    size_t num_series = derived().series.size(); // How many data series.
-    int font_size = derived().legend_header_.font_size();
-    int point_size =  derived().series[0].point_style.size();
-    // Use height of whichever is the biggest of point marker and font.
-
-    double spacing = (std::max)(font_size, point_size);
-    std::cout << spacing <<  ' ' << font_size << ' ' << point_size << std::endl;
-    bool is_header = (derived().legend_header_.text() != "");
-
-    size_t longest = derived().legend_header_.text().size();
-    // 0 if no header.
-    for(unsigned int i = 0; i < num_series; ++i)
-    { // Find the longest text in all the data series.
-      std::string s = derived().series[i].title;
-      size_t siz = s.size();
-      if (siz > longest)
-      {
-        longest = siz;
-      }
-    }
-    std::cout.flags(std::ios_base::dec);
-    std::cout << "Longest legend header or data descriptor " << longest << std::endl; // TODO remove.
-
-    const double wh = 0.7; // TODO share a common value?
-    // font_size is not exact because width varies but use 0.7.
-    double legend_width = (0 + longest) * wh * font_size;
-    // Allow for a leading space, longest 
-    // & trailing space before box margin.
-    if (derived().use_line)
-    { // colored line marker.
-       legend_width += spacing * 2.;
-    }
-    if(derived().series[0].point_style.shape() != none)
-    { // colored data point marker, cross, round... & space
-      legend_width += 2 * derived().series[0].point_style.size();
-    }
-    // else no point marker.
-
-    // legend_height must be *at least* enough for
-    // any legend header and text_margin_s around it
-    // (if any) plus a text_margin_ top and bottom.
-    // Add more height depending on the number of lines of text.
-    double legend_height = spacing; // At top
-    if (is_header) // is a legend header.
-    {
-      legend_height += 2 * font_size; // text & space after.
-    }
-    legend_height += num_series * spacing * 2; // Space for the data point symbols & text.
-
-    if ( (derived().legend_x1_ != -1) 
-      && (derived().legend_y1_ != -1))
-    { // Specific legend box top left position is requested.
-      // Check if the location requested will fit,
-      // now that we know the size of box needed.
-      if ((derived().legend_x1_ < 0) || (derived().legend_x1_ > derived().image.x_size()))
-      { // left outside image.
-         std::cout << "Legend X left " << derived().legend_x1_
-          << " outside image!" << derived().image.x_size() << std::endl;
-      }
-      else if ((derived().legend_y1_ < 0) || (derived().legend_y1_ > derived().image.y_size()))
-      {// Outside image.
-        std::cout << "Legend Y top " << derived().legend_y1_
-          << " outside image!" << derived().image.y_size() << std::endl;
-      }
-      if (derived().legend_x1_ + legend_height > derived().image.x_size())
-      { // Too wide!
-        std::cout << "Legend  " << derived().legend_x1_
-          << " too wide by " << legend_width - derived().image.x_size() << std::endl;
-      }
-      else if (derived().legend_y1_ + legend_height > derived().image.y_size())
-      {
-        std::cout << "Legend Y left " << derived().legend_y1_
-          << " too high by " << legend_height - derived().image.y_size() << std::endl;
-      }
-      // else
-      //throw?
-      // or Set anyway.
-      derived().legend_width_ = legend_width;
-      derived().legend_height_ = legend_height;
-      // derived().legend_.x1 & y1 are OK.
-      derived().legend_x2_ = derived().legend_x1_ + legend_width;
-      derived().legend_y2_ = derived().legend_y1_ + legend_height;
-    }
-    else
-    { // default legend position position.
-      // x, y position of legend 'box' top left, 
-      // default is level with top right of plot window, right by a small space.
-      double legend_x_start = derived().plot_x2;
-      legend_x_start += spacing; // leave a space between plot window and legend box.
-      double legend_y_start = derived().plot_y1;
-      legend_y_start += derived().title_info.font_size() * 2;
-      // leave space for title between image top and legend box.
-
-      // Check if the default location will fit,
-      // now that we know the size of box needed.
-      if ((legend_x_start < 0) || (legend_x_start > derived().image.x_size()))
-      { // Outside image - should never happen but check anyway?
-        std::cout << "Legend X left " << legend_x_start
-          << " outside image!" << derived().image.x_size() << std::endl;
-      }
-      else if ((legend_y_start < 0) || (legend_y_start > derived().image.y_size()))
-      { // Outside image - should never happen but check anyway?
-        std::cout << "Legend Y top " << legend_y_start
-          << " outside image!" << derived().image.y_size() << std::endl;
-      }
-      if (derived().legend_header_.x() + legend_height > derived().image.x_size())
-      { // Too wide!
-        std::cout << "Legend  " << derived().legend_header_.x()
-          << " too wide by " << legend_width - derived().image_x_size() << std::endl;
-      }
-      else if (derived().legend_header_.y() + legend_height > derived().image.y_size())
-      {
-        std::cout << "Legend Y left " << derived().legend_header_.y()
-          << " too high by " << legend_height - derived().image.y_size() << std::endl;
-      }
-      else
-      { // throw? or set anyway.
-      }
-      derived().legend_width_ = legend_width;
-      derived().legend_height_ = legend_height;
-      derived().legend_x1_ = legend_x_start;
-      derived().legend_x2_ = legend_x_start + legend_width;
-      derived().legend_y1_ = legend_y_start;
-      derived().legend_y2_ = legend_y_start + legend_height;
-    }
-
-    // Draw border box round legend.
-    g_element* g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_BACKGROUND));
-    g_ptr->push_back(new
-      rect_element(derived().legend_x1_, derived().legend_y1_, legend_width, legend_height));
-
-    std::cout << "Legend width " << derived().legend_width_ << ", height "
-         << derived().legend_height_ << ", top left "
-         << derived().legend_x1_ << ", top right "
-         << derived().legend_x2_ << ", bottom left "
-         << derived().legend_y1_ << ", botton right "
-         << derived().legend_y2_ << std::endl;
+          void clear_x_axis()
+          {
+            derived().image.get_g_element(PLOT_X_AXIS).clear();
+            derived().image.get_g_element(PLOT_X_MINOR_TICKS).clear();
+            derived().image.get_g_element(PLOT_X_MAJOR_TICKS).clear();
+            derived().image.get_g_element(PLOT_X_LABEL).clear();
+            derived().image.get_g_element(PLOT_VALUE_LABELS).clear();
+          }
 
-  } //  void calculate_legend_box()
+          void clear_y_axis()
+          {
+            derived().image.get_g_element(PLOT_Y_AXIS).clear();
+          }
 
-  void draw_legend()
-  {
-    // size_t num_points = derived().series.size();
-    int font_size = derived().legend_header_.font_size();
-    int point_size =  derived().series[0].point_style.size();
-    // Use whichever is the biggest of point marker and font.
-
-    double spacing = (std::max)(font_size, point_size);
-    // std::cerr << spacing <<  ' ' << font_size << ' ' << point_size << endl;
-    bool is_header = (derived().legend_header_.text() != "");
-
-    // TODO use saved version.
-    size_t longest = 0;
-    for(unsigned int i = 0; i < derived().series.size(); ++i)
-    { // Find the longest text in all the data series.
-      std::string s = derived().series[i].title;
-      size_t siz = s.size();
-      if (siz > longest)
-      {
-        longest = siz;
-      }
-    }
-    // Assume legend box position has already been sized and positioned by calculate_legend_box
-    double legend_x_start = derived().legend_x1_; // Saved box location.
-    double legend_width = derived().legend_width_;
-    double legend_y_start = derived().legend_y1_; 
-    double legend_height = derived().legend_height_;
-
-    // Draw border box round legend.
-    g_element* g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_BACKGROUND));
-    g_ptr->push_back(new
-      rect_element(legend_x_start, legend_y_start, legend_width, legend_height));
-
-    double legend_y_pos = legend_y_start + derived().text_margin_ * spacing;
-    if (is_header)
-    { // Draw the legend header text "My Plot Legend".
-      derived().legend_header_.x(legend_x_start + legend_width / 2.); // / 2. to center in legend box.
-      derived().legend_header_.y(legend_y_pos);
-      derived().image.get_g_element(PLOT_LEGEND_TEXT).push_back(new
-        text_element(derived().legend_header_));
-      legend_y_pos += 2 * spacing;
-    }
-
-    g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_POINTS));
-    g_element* g_inner_ptr = g_ptr;
-    g_inner_ptr = &(derived().image.get_g_element(PLOT_LEGEND_TEXT));
-
-    for(unsigned int i = 0; i < derived().series.size(); ++i)
-    { // Show point marker, text info and perhaps line for all the data series.
-      double legend_x_pos = legend_x_start;
-      g_inner_ptr = &(g_ptr->add_g_element());
-      // Use both stroke colors from the point's style.
-      g_inner_ptr->style()
-        .stroke_color(derived().series[i].point_style.stroke_color_);
-      g_inner_ptr->style().stroke_width(2); // TODO create a global for this
+          void clear_grids()
+          {
+            derived().image.get_g_element(PLOT_X_MAJOR_GRID).clear();
+            derived().image.get_g_element(PLOT_X_MINOR_GRID).clear();
+            // TODO don't we need to clear Y grids too??????
+            derived().image.get_g_element(PLOT_Y_MAJOR_GRID).clear();
+            derived().image.get_g_element(PLOT_Y_MINOR_GRID).clear();
+          }
 
-      if(derived().series[i].point_style.shape() != none)
-      {
-        draw_plot_point( // Plot point like circle, square...
-          legend_x_start + spacing / 2, // space before point marker.
-          legend_y_pos,
-          *g_inner_ptr,
-          derived().series[i].point_style);
-        legend_x_pos += 1.0 * spacing;
-      }
-
-      // Line markers  - only really applicable to 2-D sets plot_line_style,
-      if (derived().use_line)
-      { // Need to draw a short line to show color for that data series.
-        g_inner_ptr->style() // Use fill & stroke colors from line style.
-          .stroke_color(derived().series[i].line_style.color);
-        g_inner_ptr->push_back(new line_element(
-          legend_x_pos + spacing /2., // half space leading space
-          legend_y_pos,
-          legend_x_pos + spacing * 2., // line sample is two char long.
-          legend_y_pos));
-        legend_x_pos += 2.5 * spacing; // short line & half space.
-      } // use_line
-
-      // Legend text for each Data Series added to the plot.
-      g_inner_ptr = &(derived().image.get_g_element(PLOT_LEGEND_TEXT));
-      g_inner_ptr->push_back(new text_element(
-        legend_x_pos, // allow space for the marker.
-        legend_y_pos,
-        derived().series[i].title, // Text for this data series.
-        derived().legend_header_.font_size(), // font size &
-        derived().legend_header_.font_family(), // font family.
-        "", "", "", "",
-        left_align));
-      legend_y_pos += 2 * spacing;
-    } // for
-
-    // TODO reconsider this.
-    //if(derived().plot_x2 >= (int)derived().image.x_size())
-    //{ // Put legend above plot because image is tall & thin.
-    //  // TODO this with use control of the legend box position.
-    //}
-  } // void draw_legend()
+        private:
+          Derived& derived()
+          {
+            return static_cast<Derived&>(*this); // Why is cast required?
+            //  error C2440: 'return' : cannot convert from 'boost::svg::detail::axis_plot_frame<Derived>' to 'boost::svg::svg_1d_plot &'
+          }
+          const Derived& derived()const
+          {
+            return static_cast<const Derived&>(*this);
+          }
+        public:
+          // Set & get member function Declarations:
+          // See svg_fwd.hpp
+          // -----------------------------------------------------------------
+
+          // Get functions:
+          // =========== Image & plot window ==============
+          // Derived& image_size(unsigned int x, unsigned int y);
+          // unsigned int image_x_size();
+          // unsigned int image_y_size()
+          // bool plot_window_on()
+          // svg_color background_color()
+          // svg_color background_border_color()
+          // svg_color plot_background_color()
+          //
+          // std::pair<double, double> plot_window_x()
+          // std::pair<double, double> plot_window_y()
+
+          // ========= Title & legend ============
+          // bool title_on()
+          // const std::string title()
+          // unsigned int title_font_size()
+          // const std::string title_font()
+          // svg_color title_color()
+          // bool legend_on()
+          // const std::string legend_title()
+          // svg_color legend_background_color()
+          // svg_color legend_border_color()
+          // unsigned int legend_title_font_size()
+          // ========= Axes & Ticks ============
+          // bool x_axis_on()
+          // unsigned int x_axis_width()
+          // bool x_external_style_on()
+          // bool x_ticks_up_on()
+          // bool x_ticks_down_on()
+          // std::pair<double, double> x_range()
+          // double x_minimum()
+          // double x_maximum()
+          // double x_major_interval()
+          // unsigned int x_num_minor__ticks()
+          // double x_major_tick()
+          // svg_color x_major_tick_color()
+          // svg_color x_minor_tick_color()
+          // unsigned int x_major_tick_length()
+          // unsigned int x_major_tick_width_()
+          // unsigned int x_minor_tick_length_()
+          // unsigned int x_minor_tick_width_()
+          // ========= Labels ============
+          // bool x_label_on() // Show X-axis label text.
+          // std::string x_label()
+          // bool x_label_units_on() //
+          // std::string x_label_units() // Show X-axis units text.
+          // bool x_major_labels_on()
+          // svg_color x_label_color()
+          // bool axes_on()
+          // svg_color x_axis_color()
+          // bool y_axis_on()
+          // svg_color y_axis_color()
+          // std::string y_label()
+          // svg_color y_label_color()
+          // ========= grid ============
+          // bool x_major_grid_on()
+          // bool x_minor_grid_on()
+          // unsigned int x_major_grid_width()
+          // unsigned int x_minor_grid_width()
+          // svg_color x_major_grid_color()
+          // svg_color x_minor_grid_color()
+
+          // Set functions:
+
+          //Derived& image_size(unsigned int x, unsigned int y)
+          //Derived& image_x_size(unsigned int x);
+          //Derived& image_y_size(unsigned int y);
+
+          //Derived& title(const std::string& title)
+
+          //Derived& document_title(const std::string&);
+          //Derived& description(const std::string&);
+          //Derived& copyright_date(const std::string&);
+          //Derived& copyright_holder(const std::string&);
+
+          //Derived& title_font_size(unsigned int size)
+          //Derived& legend_title_font_size(unsigned int size)
+          //Derived& legend_on(bool cmd)
+          //Derived& plot_window_on(bool cmd)
+          //Derived& plot_window_x(unsigned int min_x, unsigned int max_x)
+          //Derived& plot_window_y(unsigned int min_y, unsigned int max_y)
+          //Derived& x_external_style_on(bool cmd)
+          //Derived& x_ticks_up_on(bool cmd)
+          //Derived& x_ticks_down_on(bool cmd)
+          //Derived& x_label_on(bool cmd)
+          //Derived& x_label_units_on(bool cmd)
+          //Derived& x_major_labels_on(bool cmd)
+          //Derived& title_on(bool cmd)
+          //Derived& x_major_grid_on(bool is)
+          //Derived& x_minor_grid_on(bool is)
+          //Derived& axes_on(bool is)
+          //Derived& x_axis_on(bool is)
+          //Derived& y_axis_on(bool is);
+          //Derived& title_color(const svg_color& col)
+          //Derived& background_color(const svg_color& col)
+          //Derived& legend_background_color(const svg_color& col)
+          //Derived& legend_border_color(const svg_color& col)
+          //Derived& background_border_color(const svg_color& col)
+          //Derived& plot_background_color(const svg_color& col)
+          //Derived& x_axis_color(const svg_color& col)
+          //Derived& y_axis_color(const svg_color& col)
+          //Derived& x_label_color(const svg_color& col)
+          //Derived& x_label_color(const svg_color& col)
+          //Derived& y_label_color(const svg_color& col)
+          //Derived& x_major_tick_color(const svg_color& col)
+          //Derived& x_minor_tick_color(const svg_color& col)
+          //Derived& x_major_grid_color(const svg_color& col)
+          //Derived& x_major_grid_width(unsigned int w)
+          //Derived& x_minor_grid_color(const svg_color& col)
+          //Derived& x_minor_grid_width(unsigned int w)
+          //Derived& x_axis_width(unsigned int width)
+          //Derived& x_label(const std::string& str)
+          //Derived& x_label_units(const std::string& str)
+          //Derived& y_label(const std::string& str)
+          //Derived& x_major_interval(double inter)
+          //Derived& x_major_tick_length(unsigned int length)
+          //Derived& x_major_tick_width_(unsigned int width)
+          //Derived& x_minor_tick_length_(unsigned int length)
+          //Derived& x_minor_tick_width_(unsigned)
+          //Derived& x_major_tick(double d) int width)
+          //Derived& x_num_minor_ticks(unsigned int num)
+          //Derived& x_range(double min_x, double max_x)
+          //Derived& x_minimum(double min_x)
+          //Derived& x_maximum(double max_x)
+          //Derived& load_stylesheet(const std::string& file)
+          // svg& get_svg()
+
+          // Shapes and glyphs need BOTH fill and stroke to be set.
+          // Both are usually the same in this application.
+          // If both are set, stroke is considered 'more important',
+          // and so is returned by get functions.
+
+
+          // Member functions to set plot options.
+          // All return derived() == *this to permit chaining.
+
+          //-------------------------------------------------------
+
+          Derived& image_size(unsigned int x, unsigned int y)
+          { // Might put default sizes here?
+            // Check on sanity of these values?
+            derived().image.image_size(x, y);
+            return derived();
+          }
 
-  void draw_x_label()
-  {
-    // color is set in constructor.
-    //image.get_g_element(detail::PLOT_X_LABEL).style().stroke_color(black);
-    // and using y_label_color(color)
-
-    std::string label = derived().x_label_info.text(); // x_axis label, and optional units.
-    if (derived().use_x_label_units && (derived().x_units_info.text() != ""))
-    { // Append the units, if any, providing brackets ().
-      label += "  (" + derived().x_units_info.text() + ")";
-    }
-    // Simplest to start from the bottom of the image.
-    // and move up to give enough space for the X-axis label.
-
-    double y = derived().image.y_size();  // bottom edge of image.
-    y -= derived().x_label_font_size(); // Up enough for a space underneath label.
-    derived().image.get_g_element(PLOT_X_LABEL).push_back(new text_element(
-      ( // x position relative to the x-axis which is middle of plot window.
-				derived().plot_x2 + derived().plot_x1) / 2,  // x coordinate - middle.
-      y, // Up from image bottom edge.
-      label,
-      derived().x_label_font_size(),
-      derived().x_label_font_family(), "", "", "", "", center_align, horizontal)
-    );
-  } // void draw_x_label()
-
-  // TODO split into adjust_limit(double& x) and call twice?,
-  // and TODO use to check 1-D for limit values too?
-  void adjust_limits(double& x, double& y)
-  { // If value reaches limit of max, min, infinity,
-    // use the appropriate plot min or max.
-    if(detail::limit_max(x))
-    {
-      x = derived().plot_x2;
-    }
-    if(detail::limit_max(y))
-    {
-      y = derived().plot_y1;
-    }
-    if(detail::limit_min(x))
-    {
-      x = derived().plot_x1;
-    }
-    if(detail::limit_min(y))
-    {
-      y = derived().plot_y1;
-    }
-    // If value is NaN, use zero instead.
-    // TODO Do we want/get a different color or shape for NaNs??
-    if(detail::limit_NaN(x))
-    {
-      x = 0;
-      transform_x(x);
-    }
-    if(detail::limit_NaN(y))
-    {
-      y = 0;
-      transform_y(y);
-    }
-  } // void adjust_limits
-
-  void draw_plot_point(double x, double y,
-    g_element& g_ptr,
-    const plot_point_style& sty)
-  {
-    int size = sty.size_;
-    double half_size = size / 2.;
+          unsigned int image_x_size()
+          {
+            return derived().image.x_size();
+          }
 
-    // For 1-D plots, the points do not *need* to be centered on the X-axis,
-    // and putting them just above, or sitting on, the X-axis is much clearer.
-    // For 2-D plots, the symbol center should, of course,
-    // be *centered exactly* on x, y.
-    // circle and ellipse are naturally centered on the point.
-    // for rect x and y half_size offset centers square on the point.
-    // But symbols are in a rectangular box and the offset is different for x & y
-    // even assuming that the symbol is centered in the rectangle.
-    // the vertical and horizontal ticks are deliberately offset above the axes.
-    // TODO Not sure this is fully resolved.
+          Derived& image_x_size(unsigned int i)
+          {
+            derived().image.x_size(i);
+            return derived();
+          }
 
-    switch(sty.shape_) // from enum point_shape none, round, square, point, egg
-    {
-    case round:
-      g_ptr.circle(x, y, half_size);
-      break;
-    case square:
-      g_ptr.rect(x - half_size, y - half_size, size, size);
-      break;
-    case egg:
-      g_ptr.ellipse(x, y, half_size, size * 2.); // Tall thin egg!
-      break;
-
-    // Offset from center is not an issue with vertical or horizontal ticks.
-    // TODO stroke color of line seems to be FILL color, not the stroke color.
-    // This is OK-ish, but I'm not sure why.
-
-    //svg_color sc = sty.stroke_color;
-    //svg_color fc = sty.fill_color;
-
-    case vertical_tick: // Especially neat for 1-D points.
-      g_ptr.line(x, y, x , y - size); // tick up from axis.
-      break;
-    case vertical_line:
-      g_ptr.line(x, y + size, x , y - size); // line up & down from axis.
-      break;
-    case horizontal_tick:
-    // horizontal_tick is pretty useless for 1-D because the horizontal line is on the X-axis.
-      g_ptr.line(x, y, x + size, y ); // tick right from axis.
-      break;
-    case horizontal_line:
-      g_ptr.line(x, y - size, x + size, y ); // line left & right from axis.
-    // horizontal_line is pretty useless for 1-D because the horizontal line is on the X-axis.
-      break;
-
-    case symbol:
-      g_ptr.text(x, y + half_size, sty.symbols_, size, "Lucida Sans Unicode"); // symbol(s), size and centre.
-      // TODO Need to provide way to set style.symbols when Boost.Parameter is unravelled.
-
-      // Unicode symbols that work on most browsers are listed at
-      // boost\math_toolkit\libs\math\doc\sf_and_dist\html4_symbols.qbk,
-      // http://www.htmlhelp.com/reference/html40/entities/symbols.html
-      // and  http://www.alanwood.net/demos/ent4_frame.html
-      // The Unicode value in decimal 9830 or hex x2666 must be prefixed with & and terminated with ;
-      // for example &x2666; for xml
-      // and then enveloped with "" to convert to a std::string, for example: "♦" for diamond.
-
-      break;
-    case diamond:
-      g_ptr.text(x, y, "♦", size, "Lucida Sans Unicode");
-      // size / 4. puts bottom tip on the X-axis,
-      // size / 2. put center above the X-axis
-      // x, y, put on the X-axis - probably what is needed for 2-D plots.
-      // diamond, spades, clubs & hearts fill with expected fill_color.
-      break;
-    case asterisk:
-      g_ptr.text(x, y - size / 3., "∗", size, "Lucida Sans Unicode");
-      // asterisk is black filled.
-      // size /3 puts the bottom tip on the X-axis.
-      break;
-    case lozenge:
-      g_ptr.text(x, y - size / 3., "◊", size, "Lucida Sans Unicode");
-      // size / 3 to get tip of lozenge just on the X-axis.
-      // lozenge seems not to fill?
-      break;
-    case club:
-      g_ptr.text(x, y, "♣", size, "Lucida Sans Unicode");
-      // x, y, puts club just on the X-axis
-      break;
-    case spade:
-      g_ptr.text(x, y, "♠", size, "Lucida Sans Unicode");
-      //
-      break;
-    case heart:
-      g_ptr.text(x, y , "♥", size, "Lucida Sans Unicode");
-      //
-      break;
-    case cone: // Pointing down triangle.
-      g_ptr.triangle(x - half_size, y - size, x + half_size, y - size, x, y, false);
-      // Last point puts the bottom tip of the triangle on the X-axis.
-      // This may not be wanted for 2-D.
-      break;
-    case cross:
-      g_ptr.line(x, y + size, x , y - size); // line up & down from axis,
-      g_ptr.line(x, y - size, x + size, y ); // & line left & right from axis.
-      // Cross is pretty useless for 1-D because the horizontal line is on the X-axis.
-
-    break;
-     // TODO Other point_shapes do nothing yet.
-    }
-  } // void draw_plot_point
-
-  // -----------------------------------------------------------------
-  // Clear Functions.
-  // When writing to multiple documents, the contents of the plot
-  // may change significantly between. Rather than figuring out what
-  // has and has not changed, just erase the contents of the
-  // legend, title... in the document and start over.
-  // -----------------------------------------------------------------
+          unsigned int image_y_size()
+          {
+            return derived().image.y_size();
+          }
 
-  void clear_all()
-  {
-    clear_legend();
-    clear_background();
-    clear_x_axis();
-    clear_y_axis();
-    clear_title();
-    clear_points();
-    clear_plot_background();
-    clear_grids();
-  }
+          Derived& image_y_size(unsigned int i)
+          {
+            derived().image.y_size(i);
+            return derived();
+          }
 
-  void clear_background()
-  {
-    derived().image.get_g_element(PLOT_BACKGROUND).clear();
-  }
+          svg_color background_color()
+          {
+            return derived().image.get_g_element(PLOT_BACKGROUND).style().fill_color();
+          }
 
-  void clear_title()
-  {
-    derived().image.get_g_element(PLOT_TITLE).clear();
-  }
+          Derived& background_border_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_color(col);
+            return derived();
+          }
 
-  void clear_points()
-  {
-    derived().image.get_g_element(PLOT_DATA_POINTS).clear();
-  }
+          svg_color background_border_color()
+          {
+            return derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_color();
+          }
 
-  void clear_plot_background()
-  {
-    derived().image.get_g_element(PLOT_WINDOW_BACKGROUND).clear();
-  }
+          Derived& background_border_width(double w)
+          {
+            derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_width(w);
+            return derived();
+          }
 
-  void clear_legend()
-  {
-    derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).clear();
-    derived().image.get_g_element(PLOT_LEGEND_POINTS).clear();
-    derived().image.get_g_element(PLOT_LEGEND_TEXT).clear();
-  }
+          double background_border_width()
+          {
+            return derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_width();
+          }
 
-  void clear_x_axis()
-  {
-    derived().image.get_g_element(PLOT_X_AXIS).clear();
-    derived().image.get_g_element(PLOT_X_MINOR_TICKS).clear();
-    derived().image.get_g_element(PLOT_X_MAJOR_TICKS).clear();
-    derived().image.get_g_element(PLOT_X_LABEL).clear();
-    derived().image.get_g_element(PLOT_VALUE_LABELS).clear();
-  }
+          Derived& description(const std::string d)
+          { // Writes description to the document(for header as <desc>).
+            derived().image.description(d);
+            return derived();
+          }
 
-  void clear_y_axis()
-  {
-    derived().image.get_g_element(PLOT_Y_AXIS).clear();
-  }
+          const std::string& description()
+          { // Gets description of the document(for header as <desc>).
+            return derived().image.description();
+          }
 
-  void clear_grids()
-  {
-    derived().image.get_g_element(PLOT_X_MAJOR_GRID).clear();
-    derived().image.get_g_element(PLOT_X_MINOR_GRID).clear();
-    // TODO don't we need to clear Y grids too??????
-    derived().image.get_g_element(PLOT_Y_MAJOR_GRID).clear();
-    derived().image.get_g_element(PLOT_Y_MINOR_GRID).clear();
-  }
+          Derived& document_title(const std::string d)
+          { // Writes document title to the document(for header as <title>)..
+            derived().image.document_title(d);
+            return derived();
+          }
+          std::string document_title()
+          { // Get document title to the document(for header as <title>)..
+            return derived().image.document_title();
+          }
 
-private:
-  Derived& derived()
-  {
-    return static_cast<Derived&>(*this); // Why is cast required?
-    //  error C2440: 'return' : cannot convert from 'boost::svg::detail::axis_plot_frame<Derived>' to 'boost::svg::svg_1d_plot &'
-  }
-  const Derived& derived()const
-  {
-    return static_cast<const Derived&>(*this);
-  }
-public:
-  // Set & get member function Declarations:
-  // See svg_fwd.hpp
-  // -----------------------------------------------------------------
-
-  // Get functions:
-  // =========== Image & plot window ==============
-  // Derived& image_size(unsigned int x, unsigned int y);
-  // unsigned int image_x_size();
-  // unsigned int image_y_size()
-  // bool plot_window_on()
-  // svg_color background_color()
-  // svg_color background_border_color()
-  // svg_color plot_background_color()
-  //
-  // std::pair<double, double> plot_window_x()
-  // std::pair<double, double> plot_window_y()
-
-  // ========= Title & legend ============
-  // bool title_on()
-  // const std::string title()
-  // unsigned int title_font_size()
-  // const std::string title_font()
-  // svg_color title_color()
-  // bool legend_on()
-  // const std::string legend_title()
-  // svg_color legend_background_color()
-  // svg_color legend_border_color()
-  // unsigned int legend_title_font_size()
-  // ========= Axes & Ticks ============
-  // bool x_axis_on()
-  // unsigned int x_axis_width()
-  // bool x_external_style_on()
-  // bool x_ticks_up_on()
-  // bool x_ticks_down_on()
-  // std::pair<double, double> x_range()
-  // double x_minimum()
-  // double x_maximum()
-  // double x_major_interval()
-  // unsigned int x_num_minor__ticks()
-  // double x_major_tick()
-  // svg_color x_major_tick_color()
-  // svg_color x_minor_tick_color()
-  // unsigned int x_major_tick_length()
-  // unsigned int x_major_tick_width_()
-  // unsigned int x_minor_tick_length_()
-  // unsigned int x_minor_tick_width_()
-  // ========= Labels ============
-  // bool x_label_on() // Show X-axis label text.
-  // std::string x_label()
-  // bool x_label_units_on() //
-  // std::string x_label_units() // Show X-axis units text.
-  // bool x_major_labels_on()
-  // svg_color x_label_color()
-  // bool axes_on()
-  // svg_color x_axis_color()
-  // bool y_axis_on()
-  // svg_color y_axis_color()
-  // std::string y_label()
-  // svg_color y_label_color()
-  // ========= grid ============
-  // bool x_major_grid_on()
-  // bool x_minor_grid_on()
-  // unsigned int x_major_grid_width()
-  // unsigned int x_minor_grid_width()
-  // svg_color x_major_grid_color()
-  // svg_color x_minor_grid_color()
-
-  // Set functions:
-
-//Derived& image_size(unsigned int x, unsigned int y)
-//Derived& image_x_size(unsigned int x);
-//Derived& image_y_size(unsigned int y);
-
-//Derived& title(const std::string& title)
-
-//Derived& document_title(const std::string&);
-//Derived& description(const std::string&);
-//Derived& copyright_date(const std::string&);
-//Derived& copyright_holder(const std::string&);
-
-//Derived& title_font_size(unsigned int size)
-//Derived& legend_title_font_size(unsigned int size)
-//Derived& legend_on(bool cmd)
-//Derived& plot_window_on(bool cmd)
-//Derived& plot_window_x(unsigned int min_x, unsigned int max_x)
-//Derived& plot_window_y(unsigned int min_y, unsigned int max_y)
-//Derived& x_external_style_on(bool cmd)
-//Derived& x_ticks_up_on(bool cmd)
-//Derived& x_ticks_down_on(bool cmd)
-//Derived& x_label_on(bool cmd)
-//Derived& x_label_units_on(bool cmd)
-//Derived& x_major_labels_on(bool cmd)
-//Derived& title_on(bool cmd)
-//Derived& x_major_grid_on(bool is)
-//Derived& x_minor_grid_on(bool is)
-//Derived& axes_on(bool is)
-//Derived& x_axis_on(bool is)
-//Derived& y_axis_on(bool is);
-//Derived& title_color(const svg_color& col)
-//Derived& background_color(const svg_color& col)
-//Derived& legend_background_color(const svg_color& col)
-//Derived& legend_border_color(const svg_color& col)
-//Derived& background_border_color(const svg_color& col)
-//Derived& plot_background_color(const svg_color& col)
-//Derived& x_axis_color(const svg_color& col)
-//Derived& y_axis_color(const svg_color& col)
-//Derived& x_label_color(const svg_color& col)
-//Derived& x_label_color(const svg_color& col)
-//Derived& y_label_color(const svg_color& col)
-//Derived& x_major_tick_color(const svg_color& col)
-//Derived& x_minor_tick_color(const svg_color& col)
-//Derived& x_major_grid_color(const svg_color& col)
-//Derived& x_major_grid_width(unsigned int w)
-//Derived& x_minor_grid_color(const svg_color& col)
-//Derived& x_minor_grid_width(unsigned int w)
-//Derived& x_axis_width(unsigned int width)
-//Derived& x_label(const std::string& str)
-//Derived& x_label_units(const std::string& str)
-//Derived& y_label(const std::string& str)
-//Derived& x_major_interval(double inter)
-//Derived& x_major_tick_length(unsigned int length)
-//Derived& x_major_tick_width_(unsigned int width)
-//Derived& x_minor_tick_length_(unsigned int length)
-//Derived& x_minor_tick_width_(unsigned)
-//Derived& x_major_tick(double d) int width)
-//Derived& x_num_minor_ticks(unsigned int num)
-//Derived& x_range(double min_x, double max_x)
-//Derived& x_minimum(double min_x)
-//Derived& x_maximum(double max_x)
-//Derived& load_stylesheet(const std::string& file)
-// svg& get_svg()
-
-// Shapes and glyphs need BOTH fill and stroke to be set.
-// Both are usually the same in this application.
-// If both are set, stroke is considered 'more important',
-// and so is returned by get functions.
-
-
-  // Member functions to set plot options.
-  // All return derived() == *this to permit chaining.
-
-  //-------------------------------------------------------
-
-  Derived& image_size(unsigned int x, unsigned int y)
-  { // Might put default sizes here?
-    // Check on sanity of these values?
-    derived().image.image_size(x, y);
-    return derived();
-  }
+          Derived& copyright_holder(const std::string d)
+          { // Writes copyright_holder to the document
+            // (for header as <!-- SVG Plot Copyright Paul A. Bristow 2007 --> )
+            // and as metadata: meta name="copyright" content="Paul A. Bristow" />
+            derived().image.copyright_holder(d);
+            return derived();
+          }
 
-  unsigned int image_x_size()
-  {
-    return derived().image.x_size();
-  }
+          const std::string copyright_holder()
+          { // Get copyright_holder.
+            return derived().image.copyright_holder();
+          }
 
-  Derived& image_x_size(unsigned int i)
-  {
-    derived().image.x_size(i);
-    return derived();
-  }
+          Derived& copyright_date(const std::string d)
+          { // Writes copyright_date to the document.
+            // and as metadata <meta name="date" content="2007" />
+            derived().image.copyright_date(d);
+            return derived();
+          }
 
-  unsigned int image_y_size()
-  {
-    return derived().image.y_size();
-  }
+          const std::string copyright_date()
+          { // Get copyright_date.
+            return derived().image.copyright_date();
+          }
 
-  Derived& image_y_size(unsigned int i)
-  {
-    derived().image.y_size(i);
-    return derived();
-  }
+          Derived& license(std::string repro = "permits",
+            std::string distrib = "permits",
+            std::string attrib = "requires",
+            std::string commercial = "permits")
+          { // Might check these are "permits", "requires", or "prohibits"?
+            derived().image.license(repro, distrib, attrib, commercial);
+            return derived();
+          }
 
-  svg_color background_color()
-  {
-    return derived().image.get_g_element(PLOT_BACKGROUND).style().fill_color();
-  }
+          const bool license_on()
+          {
+            return derived().image.is_license();
+          }
 
-  Derived& background_border_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_color(col);
-    return derived();
-  }
+          const std::string license_reproduction()
+          { // Get copyright_date.
+            return derived().image.reproduction();
+          }
 
-  svg_color background_border_color()
-  {
-    return derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_color();
-  }
+          const std::string license_distribution()
+          { // Get copyright_date.
+            return derived().image.distribution();
+          }
 
-  Derived& background_border_width(double w)
-  {
-    derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_width(w);
-    return derived();
-  }
+          const std::string license_attribution()
+          { // Get copyright_date.
+            return derived().image.attribution();
+          }
 
-  double background_border_width()
-  {
-    return derived().image.get_g_element(PLOT_BACKGROUND).style().stroke_width();
-  }
+          const std::string license_commercialuse()
+          { // Get copyright_date.
+            return derived().image.commercialuse();
+          }
 
-  Derived& description(const std::string d)
-  { // Writes description to the document(for header as <desc>).
-    derived().image.description(d);
-    return derived();
-  }
-
-  const std::string& description()
-  { // Gets description of the document(for header as <desc>).
-    return derived().image.description();
-  }
-
-  Derived& document_title(const std::string d)
-  { // Writes document title to the document(for header as <title>)..
-    derived().image.document_title(d);
-    return derived();
-  }
-  std::string document_title()
-  { // Get document title to the document(for header as <title>)..
-    return derived().image.document_title();
-  }
-
-  Derived& copyright_holder(const std::string d)
-  { // Writes copyright_holder to the document
-    // (for header as <!-- SVG Plot Copyright Paul A. Bristow 2007 --> )
-    // and as metadata: meta name="copyright" content="Paul A. Bristow" />
-    derived().image.copyright_holder(d);
-    return derived();
-  }
-
-  const std::string copyright_holder()
-  { // Get copyright_holder.
-    return derived().image.copyright_holder();
-  }
-
-  Derived& copyright_date(const std::string d)
-  { // Writes copyright_date to the document.
-    // and as metadata <meta name="date" content="2007" />
-    derived().image.copyright_date(d);
-    return derived();
-  }
-
-  const std::string copyright_date()
-  { // Get copyright_date.
-    return derived().image.copyright_date();
-  }
-
-  Derived& license(std::string repro = "permits",
-    std::string distrib = "permits",
-    std::string attrib = "requires",
-    std::string commercial = "permits")
-  { // Might check these are "permits", "requires", or "prohibits"?
-    derived().image.license(repro, distrib, attrib, commercial);
-    return derived();
-  }
+          Derived& coord_precision(int digits)
+          { // Precision of coordinates in decimal digits (default 3).
+            derived().image.coord_precision(digits);
+            return derived();
+          }
 
-  const bool license_on()
-  {
-    return derived().image.is_license();
-  }
+          int coord_precision()
+          { //
+            return derived().image.coord_precision();
+          }
 
-  const std::string license_reproduction()
-  { // Get copyright_date.
-    return derived().image.reproduction();
-  }
-
-  const std::string license_distribution()
-  { // Get copyright_date.
-    return derived().image.distribution();
-  }
-
-  const std::string license_attribution()
-  { // Get copyright_date.
-    return derived().image.attribution();
-  }
-
-  const std::string license_commercialuse()
-  { // Get copyright_date.
-    return derived().image.commercialuse();
-  }
-
-  Derived& coord_precision(int digits)
-  { // Precision of coordinates in decimal digits (default 3).
-    derived().image.coord_precision(digits);
-    return derived();
-  }
-
-  int coord_precision()
-  { //
-    return derived().image.coord_precision();
-  }
-
-  Derived& x_value_precision(int digits)
-  { // Precision of X tick label values in decimal digits (default 3).
-    derived().x_value_precision_ = digits;
-    return derived();
-  }
-
-  int x_value_precision()
-  { //
-    return derived().x_value_precision_;
-  }
+          Derived& x_value_precision(int digits)
+          { // Precision of X tick label values in decimal digits (default 3).
+            derived().x_value_precision_ = digits;
+            return derived();
+          }
 
-  const std::string title()
-  {
-    return derived().title_info.text();
-  }
+          int x_value_precision()
+          { //
+            return derived().x_value_precision_;
+          }
 
-  Derived& title_font_size(unsigned int i)
-  {
-    derived().title_info.font_size(i);
-    return derived();
-  }
+          const std::string title()
+          {
+            return derived().title_info.text();
+          }
 
-  unsigned int title_font_size()
-  {
-    return derived().title_info.font_size();
-  }
+          Derived& title_font_size(unsigned int i)
+          {
+            derived().title_info.font_size(i);
+            return derived();
+          }
 
-  Derived& title_font_family(const std::string& family)
-  {
-    derived().title_info.font_family(family);
-    return derived();
-  }
+          unsigned int title_font_size()
+          {
+            return derived().title_info.font_size();
+          }
 
-  const std::string& title_font_family()
-  {
-    return derived().title_info.font_family();
-  }
+          Derived& title_font_family(const std::string& family)
+          {
+            derived().title_info.font_family(family);
+            return derived();
+          }
 
-  Derived& title_font_style(const std::string& style)
-  {
-    derived().title_info.font_style(style);
-    return derived();
-  }
+          const std::string& title_font_family()
+          {
+            return derived().title_info.font_family();
+          }
 
-  const std::string& title_font_style()
-  {
-    return derived().title_info.font_style();
-  }
+          Derived& title_font_style(const std::string& style)
+          {
+            derived().title_info.font_style(style);
+            return derived();
+          }
 
-  Derived& title_font_weight(const std::string& weight)
-  {
-    derived().title_info.font_weight(weight);
-    return derived();
-  }
+          const std::string& title_font_style()
+          {
+            return derived().title_info.font_style();
+          }
 
-  const std::string& title_font_weight()
-  {
-    return derived().title_info.font_weight();
-  }
+          Derived& title_font_weight(const std::string& weight)
+          {
+            derived().title_info.font_weight(weight);
+            return derived();
+          }
 
-  Derived& legend_font_weight(const std::string& weight)
-  {
-    derived().legend_header_.font_weight(weight);
-    return derived();
-  }
+          const std::string& title_font_weight()
+          {
+            return derived().title_info.font_weight();
+          }
 
-  const std::string& legend_font_weight()
-  {
-    return derived().legend_header_.font_weight();
-  }
+          Derived& legend_font_weight(const std::string& weight)
+          {
+            derived().legend_header_.font_weight(weight);
+            return derived();
+          }
 
-  Derived& title_font_stretch(const std::string& stretch)
-  {
-    derived().title_info.font_stretch(stretch);
-    return derived();
-  }
+          const std::string& legend_font_weight()
+          {
+            return derived().legend_header_.font_weight();
+          }
 
-  const std::string& title_font_stretch()
-  {
-    return derived().title_info.font_stretch();
-  }
+          Derived& title_font_stretch(const std::string& stretch)
+          {
+            derived().title_info.font_stretch(stretch);
+            return derived();
+          }
 
-  Derived& title_font_decoration(const std::string& decoration)
-  {
-    derived().title_info.font_decoration(decoration);
-    return derived();
-  }
+          const std::string& title_font_stretch()
+          {
+            return derived().title_info.font_stretch();
+          }
 
-  const std::string& title_font_decoration()
-  {
-    return derived().title_info.font_decoration();
-  }
+          Derived& title_font_decoration(const std::string& decoration)
+          {
+            derived().title_info.font_decoration(decoration);
+            return derived();
+          }
 
-  Derived& title_font_rotation(int rotate)
-  { // Degrees (0 to 360).
-    derived().title_info.font_rotation(rotate);
-    return derived();
-  }
+          const std::string& title_font_decoration()
+          {
+            return derived().title_info.font_decoration();
+          }
 
-  int title_font_rotation()
-  {
-    return derived().title_info.font_rotation();
-  }
+          Derived& title_font_rotation(int rotate)
+          { // Degrees (0 to 360).
+            derived().title_info.font_rotation(rotate);
+            return derived();
+          }
 
-  Derived& title_font_alignment(align_style alignment)
-  {
-    derived().title_info.font_alignment(alignment);
-    return derived();
-  }
+          int title_font_rotation()
+          {
+            return derived().title_info.font_rotation();
+          }
 
-  align_style title_font_alignment()
-  {
-    return derived().title_info.font_alignment();
-  }
+          Derived& title_font_alignment(align_style alignment)
+          {
+            derived().title_info.font_alignment(alignment);
+            return derived();
+          }
 
-  Derived& legend_width(double width)
-  {
-    derived().legend_width_ = width;
-    return derived();
-  }
+          align_style title_font_alignment()
+          {
+            return derived().title_info.font_alignment();
+          }
 
-  double legend_width()
-  {
-    return derived().legend_width_;
-  }
+          Derived& legend_width(double width)
+          {
+            derived().legend_width_ = width;
+            return derived();
+          }
 
-  Derived& legend_title(const std::string title)
-  {
-    derived().legend_header_.text(title);
-    return derived();
-  }
+          double legend_width()
+          {
+            return derived().legend_width_;
+          }
 
-  const std::string legend_title()
-  {
-    return derived().legend_header_.text();
-  }
+          Derived& legend_title(const std::string title)
+          {
+            derived().legend_header_.text(title);
+            return derived();
+          }
 
-  Derived& legend_font_family(const std::string& family)
-  {
-    derived().legend_header_.font_family(family);
-    return derived();
-  }
+          const std::string legend_title()
+          {
+            return derived().legend_header_.text();
+          }
 
-  const std::string& legend_font_family()
-  {
-    return derived().legend_header_.font_family();
-  }
+          Derived& legend_font_family(const std::string& family)
+          {
+            derived().legend_header_.font_family(family);
+            return derived();
+          }
 
-  Derived& legend_title_font_size(unsigned int size)
-  {
-    derived().legend_header_.font_size(size);
-    return derived();
-  }
+          const std::string& legend_font_family()
+          {
+            return derived().legend_header_.font_family();
+          }
 
-  unsigned int legend_title_font_size()
-  {
-    return derived().legend_header_.font_size();
-  }
+          Derived& legend_title_font_size(unsigned int size)
+          {
+            derived().legend_header_.font_size(size);
+            return derived();
+          }
 
-  Derived& legend_top_left(double x, double y)
-  { // Position of top left of legend box (svg coordinates).
-    // Bottom right is controlled by contents, so cannot set it.
-    if((x < 0) || (x > derived().image.x_size()) || (y < 0) || (y > derived().image.y_size()))
-    {
-      throw std::runtime_error("Illegal legend box position.");
-    }
-    derived().legend_x1_ = x;
-    derived().legend_y1_ = y;
-    return derived();
-  }
-
-  std::pair<double, double> legend_top_left()
-  {// Top left of legend box
-    std::pair<double, double> r;
-    r.first = derived().legend_x1_; 
-    r.second = derived().legend_y1_;
-    return r;
-  }
-
-  std::pair<double, double> legend_bottom_right()
-  {// Top left of legend box
-    std::pair<double, double> r;
-    r.first = derived().legend_x2_; 
-    r.second = derived().legend_y2_;
-    return r;
-  }
+          unsigned int legend_title_font_size()
+          {
+            return derived().legend_header_.font_size();
+          }
 
-  Derived& line_on(bool is)
-  {
-    derived().use_line = is;
-    return derived();
-  }
+          Derived& legend_top_left(double x, double y)
+          { // Position of top left of legend box (svg coordinates).
+            // Bottom right is controlled by contents, so cannot set it.
+            if((x < 0) || (x > derived().image.x_size()) || (y < 0) || (y > derived().image.y_size()))
+            {
+              throw std::runtime_error("Illegal legend box position.");
+            }
+            derived().legend_left_ = x;
+            derived().legend_top_ = y;
+            return derived();
+          }
 
-  bool line_on()
-  {
-    return derived().use_line;
-  }
+          std::pair<double, double> legend_top_left()
+          {// Top left of legend box.
+            std::pair<double, double> r;
+            r.first = derived().legend_left_; 
+            r.second = derived().legend_top_;
+            return r;
+          }
 
-  Derived& legend_on(bool cmd)
-  {
-    derived().use_legend = cmd;
-    if(cmd)
-    {
-      derived().image.get_g_element(detail::PLOT_LEGEND_BACKGROUND)
-        .style().fill_color(white)
-        .stroke_color(black);
-    }
-    return derived();
-  }
+          std::pair<double, double> legend_bottom_right()
+          {// BOttom right of legend box.
+            std::pair<double, double> r;
+            r.first = derived().legend_right_; 
+            r.second = derived().legend_bottom_;
+            return r;
+          }
 
-  bool legend_on()
-  {
-    return derived().use_legend;
-  }
+          Derived& line_on(bool is)
+          {
+            derived().use_line = is;
+            return derived();
+          }
 
-  Derived& plot_window_on(bool cmd)
-  {
-    derived().use_plot_window_ = cmd;
+          bool line_on()
+          {
+            return derived().use_line;
+          }
 
-    if(cmd)
-    { // set plot window color and border color.
-      // TODO - allow user to change these.
-      derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND)
-        .style().fill_color(white)
-        .stroke_color(black);
-    }
-    return derived();
-  }
+          Derived& legend_on(bool cmd)
+          {
+            derived().use_legend = cmd;
+            if(cmd)
+            {
+              derived().image.get_g_element(detail::PLOT_LEGEND_BACKGROUND)
+                .style().fill_color(white)
+                .stroke_color(black);
+            }
+            return derived();
+          }
 
-  bool plot_window_on()
-  {
-    return derived().use_plot_window_;
-  }
+          bool legend_on()
+          {
+            return derived().use_legend;
+          }
 
-  Derived& plot_border_color(const svg_color& col)
-  {
-    derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color(col);
-    return derived();
-  }
-
-  svg_color plot_border_color()
-  { 
-    return derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color();
-  }
+          Derived& legend_place(legend_places l)
+          {
+            derived().legend_place_ = l;
+            return derived();
+          }
 
-  double plot_border_width()
-  {
-      return derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_width();
-  }
+          legend_places legend_place()
+          {
+            return derived().legend_place_;
+          }
 
-  Derived& plot_border_width(double w)
-  {
-    derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_width(w);
-    return derived();
-  }
+          bool legend_outside()
+          {
+            return derived().use_outside_legend_;
+          }
+          Derived& plot_window_on(bool cmd)
+          {
+            derived().use_plot_window_ = cmd;
 
-  Derived& border_margin(double w)
-  {
-    derived().border_margin_ = w;
-    return derived();
-  }
+            if(cmd)
+            { // set plot window color and border color.
+              // TODO - allow user to change these.
+              derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND)
+                .style().fill_color(white)
+                .stroke_color(black);
+            }
+            derived().legend_place_ = outside_right;
+            return derived();
+          }
 
-  double border_margin()
-  {
-    return derived().border_margin_;
-  }
+          bool plot_window_on()
+          {
+            return derived().use_plot_window_;
+          }
 
-  Derived& border_width(double w)
-  {
-    derived().border_width_ = w;
-    return derived();
-  }
+          Derived& plot_border_color(const svg_color& col)
+          {
+            derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color(col);
+            return derived();
+          }
 
-  double border_width()
-  {
-    return derived().border_width_;
-  }
+          svg_color plot_border_color()
+          { 
+            return derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color();
+          }
 
-  Derived& plot_window_x(double min_x, double max_x)
-  { // This is normally calculated from other plot values.
-    if(max_x <= min_x)
-    {
-      throw std::runtime_error("plot_window_x: X range: x_max < x_min");
-    }
-    derived().plot_x1 = min_x;
-    derived().plot_x2 = max_x;
-    return derived();
-  }
-
-  Derived& plot_window_y(double min_y, double max_y)
-  { // This is normally calculated from other plot values.
-    if(max_y <= min_y)
-    {
-      throw std::runtime_error("plot_window_y : Y range: y_max < y_min");
-    }
-    derived().plot_y1 = min_y;
-    derived().plot_y2 = max_y;
-    return derived();
-  }
+          double plot_border_width()
+          {
+            return derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_width();
+          }
+
+          Derived& plot_border_width(double w)
+          {
+            derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_width(w);
+            return derived();
+          }
+
+          Derived& border_margin(double w)
+          {
+            derived().border_margin_ = w;
+            return derived();
+          }
+
+          double border_margin()
+          {
+            return derived().border_margin_;
+          }
+
+          Derived& border_width(double w)
+          {
+            derived().border_width_ = w;
+            return derived();
+          }
+
+          double border_width()
+          {
+            return derived().border_width_;
+          }
+
+          Derived& plot_window_x(double min_x, double max_x)
+          { // This is normally calculated from other plot values.
+            if(max_x <= min_x)
+            {
+              throw std::runtime_error("plot_window_x: X range: x_max < x_min");
+            }
+            derived().plot_x1 = min_x;
+            derived().plot_x2 = max_x;
+            return derived();
+          }
+
+          Derived& plot_window_y(double min_y, double max_y)
+          { // This is normally calculated from other plot values.
+            if(max_y <= min_y)
+            {
+              throw std::runtime_error("plot_window_y : Y range: y_max < y_min");
+            }
+            derived().plot_y1 = min_y;
+            derived().plot_y2 = max_y;
+            return derived();
+          }
+
+          std::pair<double, double> plot_window_x()
+          {
+            std::pair<double, double> r;
+            r.first = derived().plot_x1;
+            r.second = derived().plot_x2;
+            return r;
+          }
+
+          double plot_window_x_left()
+          {
+            return derived().plot_x1;
+          }
+          double plot_window_x_right()
+          {
+            return derived().plot_x2;
+          }
+          double plot_window_y_top()
+          {
+            return derived().plot_y1;
+          }
+          double plot_window_y_bottom()
+          {
+            return derived().plot_y2;
+          }
+
+          std::pair<double, double> plot_window_y()
+          {
+            std::pair<double, double> r;
+            r.first = derived().plot_y1;
+            r.second = derived().plot_y2;
+            return r;
+          }
+
+          double x_minor_interval()
+          {
+            return derived().x_minor_interval_;  // interval
+          }
+
+          double y_minor_interval()
+          {
+            return derived().y_minor_interval_;  // interval
+          }
+
+          Derived& x_ticks_up_on(bool cmd)
+          {
+            derived().use_up_ticks = cmd;
+            return derived();
+          }
+
+          bool x_ticks_up_on()
+          {
+            return derived().use_up_ticks;
+          }
+
+          Derived& x_ticks_down_on(bool cmd)
+          {
+            derived().use_down_ticks = cmd;
+            return derived();
+          }
+
+          bool x_ticks_down_on()
+          {
+            return derived().use_down_ticks;
+          }
+          // Only need y_ticks_left_on & y_ticks_right_on in 2D
+
+          Derived& x_label_on(bool cmd)
+          { // Show X-axis label text, or not.
+            derived().use_x_label = cmd;
+            return derived();
+          }
+
+          bool x_label_on()
+          {
+            return derived().use_x_label;
+          }
+
+          Derived& x_label_font_size(unsigned int i)
+          { 
+            derived().x_label_info.font_size(i);
+            return derived();
+          }
+
+          unsigned int x_label_font_size()
+          {
+            return derived().x_label_info.font_size();
+          }
+
+          Derived& x_value_font_size(unsigned int i)
+          { 
+            derived().x_value_value.font_size(i);
+            return derived();
+          }
+
+          unsigned int x_value_font_size()
+          {
+            return derived().x_value_value.font_size();
+          }
+
+          Derived& x_label_font_family(const std::string& family)
+          {
+            derived().x_label_info.font_family(family);
+            return derived();
+          }
+
+          const std::string& x_label_font_family()
+          {
+            return derived().x_label_info.font_family();
+          }
+
+          Derived& x_value_ioflags(int flags)
+          { // IO flags of X tick label values (default 0X201).
+            derived().x_value_ioflags_ = flags;
+            return derived();
+          }
+
+          int x_value_ioflags()
+          { // ALL stream ioflags for control of format of X value labels.
+            return derived().x_value_ioflags_;
+          }
+
+          Derived& title(const std::string title)
+          { // Plot title.
+            derived().title_info.text(title);
+            return derived();
+          }
+
+          Derived& x_axis_label_color(const svg_color& col)
+          { // Set BOTH stroke and fill to the same color.
+            derived().image.get_g_element(detail::PLOT_X_LABEL).style().fill_color(col);
+            derived().image.get_g_element(detail::PLOT_X_LABEL).style().stroke_color(col);
+            return *this;
+          }
+
+          svg_color x_axis_label_color()
+          { // But only return the stroke color.
+            return derived().image.get_g_element(detail::PLOT_X_LABEL).style().stroke_color();
+          }
+
+          Derived& x_axis_value_color(const svg_color& col)
+          { // Set BOTH stroke and fill to the same color.
+            derived().image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
+            derived().image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
+            return *this;
+          }
+
+          svg_color x_axis_value_color()
+          { // But only return the stroke color.
+            return derived().image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color();
+          }
+
+          Derived& x_ticks_on_plot_window_on(bool cmd)
+          { // External style.
+            derived().use_x_ticks_on_plot_window_ = cmd;
+            return derived();
+          }
+
+          bool x_ticks_on_plot_window_on()
+          { // External style = true.
+            return derived().use_x_ticks_on_plot_window_;
+          }
 
-  std::pair<double, double> plot_window_x()
-  {
-    std::pair<double, double> r;
-    r.first = derived().plot_x1;
-    r.second = derived().plot_x2;
-    return r;
-  }
+          Derived& x_label_units_on(bool cmd)
+          {
+            derived().use_x_label_units = cmd;
+            return derived();
+          }
 
-  double plot_window_x_left()
-  {
-    return derived().plot_x1;
-  }
-  double plot_window_x_right()
-  {
-    return derived().plot_x2;
-  }
-  double plot_window_y_top()
-  {
-    return derived().plot_y1;
-  }
-  double plot_window_y_bottom()
-  {
-    return derived().plot_y2;
-  }
+          bool x_label_units_on()
+          {
+            return derived().use_x_label_units;
+          }
 
-  std::pair<double, double> plot_window_y()
-  {
-    std::pair<double, double> r;
-    r.first = derived().plot_y1;
-    r.second = derived().plot_y2;
-    return r;
-  }
+          Derived& x_major_labels_on(bool cmd)
+          {
+            derived().use_x_major_labels = cmd;
+            return derived();
+          }
 
-  double x_minor_interval()
-  {
-    return derived().x_minor_interval_;  // interval
-  }
+          bool x_major_labels_on()
+          {
+            return derived().use_x_major_labels;
+          }
 
-  double y_minor_interval()
-  {
-    return derived().y_minor_interval_;  // interval
-  }
+          Derived& x_major_label_rotation(int rot)
+          {
+            derived().x_label_rotation_ = rot;
+            return derived();
+          }
 
-  Derived& x_ticks_up_on(bool cmd)
-  {
-    derived().use_up_ticks = cmd;
-    return derived();
-  }
+          int x_major_label_rotation()
+          {
+            return derived().x_label_rotation_;
+          }
 
-  bool x_ticks_up_on()
-  {
-    return derived().use_up_ticks;
-  }
+          Derived& title_on(bool cmd)
+          {
+            derived().use_title = cmd;
+            return derived();
+          }
 
-  Derived& x_ticks_down_on(bool cmd)
-  {
-    derived().use_down_ticks = cmd;
-    return derived();
-  }
+          bool title_on()
+          {
+            return derived().use_title;
+          }
 
-  bool x_ticks_down_on()
-  {
-    return derived().use_down_ticks;
-  }
-  // Only need y_ticks_left_on & y_ticks_right_on in 2D
-
-  Derived& x_label_on(bool cmd)
-  { // Show X-axis label text, or not.
-    derived().use_x_label = cmd;
-    return derived();
-  }
+          Derived& x_major_grid_on(bool is)
+          {
+            derived().use_x_major_grid_ = is;
+            return derived();
+          }
 
-  bool x_label_on()
-  {
-    return derived().use_x_label;
-  }
+          bool x_major_grid_on()
+          {
+            return derived().use_x_major_grid_;
+          }
 
-  Derived& x_label_font_size(unsigned int i)
-  { 
-    derived().x_label_info.font_size(i);
-    return derived();
-  }
+          Derived& x_minor_grid_on(bool is)
+          {
+            derived().use_x_minor_grid_ = is;
+            return derived();
+          }
 
-  unsigned int x_label_font_size()
-  {
-    return derived().x_label_info.font_size();
-  }
+          bool x_minor_grid_on()
+          {
+            return derived().use_x_minor_grid_;
+          }
 
-  Derived& x_value_font_size(unsigned int i)
-  { 
-    derived().x_value_value.font_size(i);
-    return derived();
-  }
+          Derived& axes_on(bool is)
+          { // Draw *both* x and y axes (note plural).
+            derived().use_x_axis_lines_ = is;
+            derived().use_y_axis_lines_ = is;
+            return derived();
+          }
 
-  unsigned int x_value_font_size()
-  {
-    return derived().x_value_value.font_size();
-  }
+          bool axes_on()
+          { // Used X in preference to Y for 1D, but now require *both* x and y axis on.
+            return derived().use_x_axis_lines_ && derived().use_y_axis_lines_;
+          }
 
-  Derived& x_label_font_family(const std::string& family)
-  {
-    derived().x_label_info.font_family(family);
-    return derived();
-  }
+          Derived& x_axis_on(bool is)
+          { // Draw a horizontal x_axis line.
+            derived().use_x_axis_lines_ = is;
+            return derived();
+          }
 
-  const std::string& x_label_font_family()
-  {
-    return derived().x_label_info.font_family();
-  }
+          bool x_axis_on()
+          { // Use X in preference to Y for 1D
+            return derived().use_x_axis_lines_;
+          }
 
-  Derived& x_value_ioflags(int flags)
-  { // IO flags of X tick label values (default 0X201).
-    derived().x_value_ioflags_ = flags;
-    return derived();
-  }
-
-  int x_value_ioflags()
-  { // ALL stream ioflags for control of format of X value labels.
-    return derived().x_value_ioflags_;
-  }
-
-  Derived& title(const std::string title)
-  { // Plot title.
-    derived().title_info.text(title);
-    return derived();
-  }
-
-
-  Derived& x_axis_label_color(const svg_color& col)
-  { // Set BOTH stroke and fill to the same color.
-    derived().image.get_g_element(detail::PLOT_X_LABEL).style().fill_color(col);
-    derived().image.get_g_element(detail::PLOT_X_LABEL).style().stroke_color(col);
-    return *this;
-  }
-
-  svg_color x_axis_label_color()
-  { // But only return the stroke color.
-    return derived().image.get_g_element(detail::PLOT_X_LABEL).style().stroke_color();
-  }
-
-  Derived& x_axis_value_color(const svg_color& col)
-  { // Set BOTH stroke and fill to the same color.
-    derived().image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
-    derived().image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
-    return *this;
-  }
-
-  svg_color x_axis_value_color()
-  { // But only return the stroke color.
-    return derived().image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color();
-  }
-
-  Derived& x_ticks_on_plot_window_on(bool cmd)
-  { // External style.
-    derived().use_x_ticks_on_plot_window_ = cmd;
-    return derived();
-  }
-
-  bool x_ticks_on_plot_window_on()
-  { // External style = true.
-    return derived().use_x_ticks_on_plot_window_;
-  }
+          Derived& y_axis_on(bool is)
+          {// Draw a vertical y_axis line.
+            derived().use_y_axis_lines_ = is;
+            return derived();
+          }
 
-  Derived& x_label_units_on(bool cmd)
-  {
-    derived().use_x_label_units = cmd;
-    return derived();
-  }
+          bool y_axis_on()
+          { // Should be always false for 1D.
+            return derived().use_y_axis_lines_;
+          }
 
-  bool x_label_units_on()
-  {
-    return derived().use_x_label_units;
-  }
+          // enums like PLOT_TITLE provide a std:string like "title"
+          // colors .stroke_color, .stroke_width and font are set in the appropriate g_element.
 
-  Derived& x_major_labels_on(bool cmd)
-  {
-    derived().use_x_major_labels = cmd;
-    return derived();
-  }
+          Derived& title_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_TITLE).style().stroke_color(col);
+            derived().image.get_g_element(PLOT_TITLE).style().fill_color(col);
+            return derived();
+          }
 
-  bool x_major_labels_on()
-  {
-    return derived().use_x_major_labels;
-  }
+          svg_color title_color()
+          { // Function title_color sets both fill and stroke,
+            // but stroke (outside) is considered 'more important'.
+            return derived().image.get_g_element(PLOT_TITLE).style().stroke_color();
+          }
 
-  Derived& x_major_label_rotation(int rot)
-  {
-    derived().x_label_rotation_ = rot;
-    return derived();
-  }
+          Derived& title_font_width(double width)
+          { // width of text is effectively the boldness
+            derived().image.get_g_element(PLOT_TITLE).style().stroke_width(width); 
+            return derived();
+          }
 
-  int x_major_label_rotation()
-  {
-    return derived().x_label_rotation_;
-  }
+          double title_font_width()
+          {
+            return derived().image.get_g_element(PLOT_TITLE).style().stroke_width();
+          }
 
-  Derived& title_on(bool cmd)
-  {
-    derived().use_title = cmd;
-    return derived();
-  }
+          Derived& legend_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_LEGEND_TEXT).style().fill_color(col);
+            derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_color(col);
+            return derived();
+          }
 
-  bool title_on()
-  {
-    return derived().use_title;
-  }
+          svg_color legend_color()
+          { // Function legend_color sets both fill and stroke,
+            // but stroke (outside) is considered 'more important'.
+            return derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_color();
+          }
 
-  Derived& x_major_grid_on(bool is)
-  {
-    derived().use_x_major_grid_ = is;
-    return derived();
-  }
+          Derived& legend_font_width(double width)
+          { // width of text is effectively the boldness.
+            derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width(width);
+            return derived();
+          }
 
-  bool x_major_grid_on()
-  {
-    return derived().use_x_major_grid_;
-  }
+          double legend_font_width()
+          {
+            return derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width();
+          }
 
-  Derived& x_minor_grid_on(bool is)
-  {
-    derived().use_x_minor_grid_ = is;
-    return derived();
-  }
+          Derived& background_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_BACKGROUND).style().fill_color(col);
+            return derived();
+          }
 
-  bool x_minor_grid_on()
-  {
-    return derived().use_x_minor_grid_;
-  }
+          Derived& legend_background_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().fill_color(col);
+            return derived();
+          }
 
-  Derived& axes_on(bool is)
-  { // Draw *both* x and y axes (note plural).
-    derived().use_x_axis_lines_ = is;
-    derived().use_y_axis_lines_ = is;
-    return derived();
-  }
-
-  bool axes_on()
-  { // Used X in preference to Y for 1D, but now require *both* x and y axis on.
-    return derived().use_x_axis_lines_ && derived().use_y_axis_lines_;
-  }
-
-  Derived& x_axis_on(bool is)
-  { // Draw a horizontal x_axis line.
-    derived().use_x_axis_lines_ = is;
-    return derived();
-  }
-
-  bool x_axis_on()
-  { // Use X in preference to Y for 1D
-    return derived().use_x_axis_lines_;
-  }
-
-  Derived& y_axis_on(bool is)
-  {// Draw a vertical y_axis line.
-    derived().use_y_axis_lines_ = is;
-    return derived();
-  }
-
-  bool y_axis_on()
-  { // Should be always false for 1D.
-    return derived().use_y_axis_lines_;
-  }
+          svg_color legend_background_color()
+          {
+            return derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().fill_color();
+          }
 
-  // enums like PLOT_TITLE provide a std:string like "title"
-  // colors .stroke_color, .stroke_width and font are set in the appropriate g_element.
+          Derived& legend_border_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().stroke_color(col);
+            return derived();
+          }
 
-  Derived& title_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_TITLE).style().stroke_color(col);
-    derived().image.get_g_element(PLOT_TITLE).style().fill_color(col);
-    return derived();
-  }
-
-  svg_color title_color()
-  { // Function title_color sets both fill and stroke,
-    // but stroke (outside) is considered 'more important'.
-    return derived().image.get_g_element(PLOT_TITLE).style().stroke_color();
-  }
-
-  Derived& title_font_width(double width)
-  { // width of text is effectively the boldness
-    derived().image.get_g_element(PLOT_TITLE).style().stroke_width(width); 
-    return derived();
-  }
+          svg_color legend_border_color()
+          {
+            return derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().stroke_color();
+          }
 
-  double title_font_width()
-  {
-    return derived().image.get_g_element(PLOT_TITLE).style().stroke_width();
-  }
+          Derived& plot_background_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color(col);
+            return derived();
+          }
 
-  Derived& legend_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_LEGEND_TEXT).style().fill_color(col);
-    derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_color(col);
-    return derived();
-  }
-
-  svg_color legend_color()
-  { // Function legend_color sets both fill and stroke,
-    // but stroke (outside) is considered 'more important'.
-    return derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_color();
-  }
-
-  Derived& legend_font_width(double width)
-  { // width of text is effectively the boldness.
-    derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width(width);
-    return derived();
-  }
+          svg_color plot_background_color()
+          {
+            return derived().image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color();
+          }
 
-  double legend_font_width()
-  {
-    return derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width();
-  }
+          Derived& x_axis_color(const svg_color& col)
+          { // Note only stroke color is set.
+            derived().image.get_g_element(PLOT_X_AXIS).style().stroke_color(col);
+            return derived();
+          }
 
-  Derived& background_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_BACKGROUND).style().fill_color(col);
-    return derived();
-  }
+          svg_color x_axis_color()
+          { 
+            return derived().image.get_g_element(PLOT_X_AXIS).style().stroke_color();
+          }
 
-  Derived& legend_background_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().fill_color(col);
-    return derived();
-  }
+          Derived& y_axis_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_Y_AXIS).style().stroke_color(col);
+            return derived();
+          }
 
-  svg_color legend_background_color()
-  {
-    return derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().fill_color();
-  }
+          svg_color y_axis_color()
+          {
+            return derived().image.get_g_element(PLOT_Y_AXIS).style().stroke_color();
+          }
 
-  Derived& legend_border_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().stroke_color(col);
-    return derived();
-  }
+          Derived& x_label_color(const svg_color& col)
+          { // add fill as well PAB Oct 07
+            derived().image.get_g_element(PLOT_X_LABEL).style().fill_color(col);
+            derived().image.get_g_element(PLOT_X_LABEL).style().stroke_color(col);
+            return derived();
+          }
 
-  svg_color legend_border_color()
-  {
-    return derived().image.get_g_element(PLOT_LEGEND_BACKGROUND).style().stroke_color();
-  }
+          Derived& x_label_width(double width)
+          { // width of text is effectively the boldness.
+            x_label_width_ = width;
+            derived().image.get_g_element(PLOT_X_LABEL).style().stroke_width(width);
+            return derived();
+          }
 
-  Derived& plot_background_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color(col);
-    return derived();
-  }
+          double x_label_width()
+          {
+            //return x_label_width_;
+            return derived().image.get_g_element(PLOT_X_LABEL).style().stroke_width();
+          }
 
-  svg_color plot_background_color()
-  {
-    return derived().image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color();
-  }
+          svg_color x_label_color()
+          {
+            return derived().image.get_g_element(PLOT_X_LABEL).style().fill_color();
+          }
 
-  Derived& x_axis_color(const svg_color& col)
-  { // Note only stroke color is set.
-    derived().image.get_g_element(PLOT_X_AXIS).style().stroke_color(col);
-    return derived();
-  }
-
-  svg_color x_axis_color()
-  { 
-    return derived().image.get_g_element(PLOT_X_AXIS).style().stroke_color();
-  }
+          Derived& y_label_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_Y_LABEL).style().fill_color(col);
+            derived().image.get_g_element(PLOT_Y_LABEL).style().stroke_color(col);
+            return derived();
+          }
 
-  Derived& y_axis_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_Y_AXIS).style().stroke_color(col);
-    return derived();
-  }
+          svg_color y_label_color()
+          {
+            return derived().image.get_g_element(PLOT_Y_LABEL).style().fill_color();
+          }
 
-  svg_color y_axis_color()
-  {
-    return derived().image.get_g_element(PLOT_Y_AXIS).style().stroke_color();
-  }
+          Derived& x_major_tick_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_color(col);
+            return derived();
+          }
 
-  Derived& x_label_color(const svg_color& col)
-  { // add fill as well PAB Oct 07
-    derived().image.get_g_element(PLOT_X_LABEL).style().fill_color(col);
-    derived().image.get_g_element(PLOT_X_LABEL).style().stroke_color(col);
-    return derived();
-  }
-
-  Derived& x_label_width(double width)
-  { // width of text is effectively the boldness.
-    x_label_width_ = width;
-    derived().image.get_g_element(PLOT_X_LABEL).style().stroke_width(width);
-    return derived();
-  }
+          svg_color x_major_tick_color()
+          {
+            return derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_color();
+          }
 
-  double x_label_width()
-  {
-    //return x_label_width_;
-    return derived().image.get_g_element(PLOT_X_LABEL).style().stroke_width();
-  }
+          Derived& x_minor_tick_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_color(col);
+            return derived();
+          }
 
-  svg_color x_label_color()
-  {
-    return derived().image.get_g_element(PLOT_X_LABEL).style().fill_color();
-  }
+          svg_color x_minor_tick_color()
+          {
+            return derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_color();
+          }
 
-  Derived& y_label_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_Y_LABEL).style().fill_color(col);
-    derived().image.get_g_element(PLOT_Y_LABEL).style().stroke_color(col);
-    return derived();
-  }
+          Derived& x_major_grid_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_color(col);
+            return derived();
+          }
 
-  svg_color y_label_color()
-  {
-    return derived().image.get_g_element(PLOT_Y_LABEL).style().fill_color();
-  }
+          svg_color x_major_grid_color()
+          {
+            return derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_color();
+          }
 
-  Derived& x_major_tick_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_color(col);
-    return derived();
-  }
+          Derived& x_major_grid_width(double w)
+          {
+            derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width(w);
+            return derived();
+          }
 
-  svg_color x_major_tick_color()
-  {
-    return derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_color();
-  }
+          double x_major_grid_width()
+          {
+            return derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width();
+          }
 
-  Derived& x_minor_tick_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_color(col);
-    return derived();
-  }
+          Derived& x_minor_grid_color(const svg_color& col)
+          {
+            derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_color(col);
+            return derived();
+          }
 
-  svg_color x_minor_tick_color()
-  {
-    return derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_color();
-  }
+          svg_color x_minor_grid_color()
+          {
+            return derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_color();
+          }
 
-  Derived& x_major_grid_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_color(col);
-    return derived();
-  }
+          Derived& x_minor_grid_width(double w)
+          {
+            derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_width(w);
+            return derived();
+          }
 
-  svg_color x_major_grid_color()
-  {
-    return derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_color();
-  }
+          double x_minor_grid_width()
+          {
+            return derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_width();
+          }
 
-  Derived& x_major_grid_width(double w)
-  {
-    derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width(w);
-    return derived();
-  }
+          Derived& x_axis_width(double width)
+          {
+            derived().image.get_g_element(PLOT_X_AXIS).style().stroke_width(width);
+            return derived();
+          }
 
-  double x_major_grid_width()
-  {
-    return derived().image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width();
-  }
+          double x_axis_width()
+          {
+            return derived().image.get_g_element(PLOT_X_AXIS).style().stroke_width();
+          }
 
-  Derived& x_minor_grid_color(const svg_color& col)
-  {
-    derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_color(col);
-    return derived();
-  }
+          Derived& data_lines_width(double width)
+          {
+            derived().image.get_g_element(PLOT_DATA_LINES).style().stroke_width(width);
+            return derived();
+          }
 
-  svg_color x_minor_grid_color()
-  {
-    return derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_color();
-  }
+          double data_lines_width()
+          {
+            return derived().image.get_g_element(PLOT_DATA_LINES).style().stroke_width();
+          }
 
-  Derived& x_minor_grid_width(double w)
-  {
-    derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_width(w);
-    return derived();
-  }
+          Derived& x_label(const std::string& str)
+          {
+            derived().x_label_info.text(str);
+            return derived();
+          }
 
-  double x_minor_grid_width()
-  {
-    return derived().image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_width();
-  }
+          std::string x_label()
+          {
+            return derived().x_label_info.text();
+          }
 
-  Derived& x_axis_width(double width)
-  {
-    derived().image.get_g_element(PLOT_X_AXIS).style().stroke_width(width);
-    return derived();
-  }
+          Derived& x_label_units(const std::string& str)
+          {
+            derived().x_units_info.text(str);
+            return derived();
+          }
 
-  double x_axis_width()
-  {
-    return derived().image.get_g_element(PLOT_X_AXIS).style().stroke_width();
-  }
+          std::string x_label_units()
+          {
+            return derived().x_units_info.text();
+          }
 
-  Derived& data_lines_width(double width)
-  {
-    derived().image.get_g_element(PLOT_DATA_LINES).style().stroke_width(width);
-    return derived();
-  }
+          // y_label not needed in 1D.
+          Derived& y_label(const std::string& str)
+          {
+            derived().y_label_info.text(str);
+            return derived();
+          }
 
-  double data_lines_width()
-  {
-    return derived().image.get_g_element(PLOT_DATA_LINES).style().stroke_width();
-  }
+          std::string y_label()
+          {
+            return derived().y_label_info.text();
+          }
 
-  Derived& x_label(const std::string& str)
-  {
-    derived().x_label_info.text(str);
-    return derived();
-  }
+          Derived& y_label_units(const std::string& str)
+          {
+            derived().y_units_info.text(str);
+            return derived();
+          }
 
-  std::string x_label()
-  {
-    return derived().x_label_info.text();
-  }
+          std::string y_label_units()
+          {
+            return derived().y_units_info.text();
+          }
 
-  Derived& x_label_units(const std::string& str)
-  {
-    derived().x_units_info.text(str);
-    return derived();
-  }
+          Derived& x_major_interval(double inter)
+          {
+            derived().x_major_interval_ = inter;
+            return derived();
+          }
 
-  std::string x_label_units()
-  {
-    return derived().x_units_info.text();
-  }
+          double x_major_interval()
+          {
+            return derived().x_major_interval_;
+          }
 
-  // y_label not needed in 1D.
-  Derived& y_label(const std::string& str)
-  {
-    derived().y_label_info.text(str);
-    return derived();
-  }
+          Derived& x_major_tick_length(double length)
+          {
+            derived().x_major_tick_length_ = length;
+            return derived();
+          }
 
-  std::string y_label()
-  {
-    return derived().y_label_info.text();
-  }
+          double x_major_tick_length()
+          {
+            return derived().x_major_tick_length_;
+          }
 
-  Derived& y_label_units(const std::string& str)
-  {
-    derived().y_units_info.text(str);
-    return derived();
-  }
+          Derived& x_major_tick_width(double width)
+          {
+            derived().x_major_tick_width_ = width; // Redundant?
+            derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width(width);
+            return derived();
+          }
 
-  std::string y_label_units()
-  {
-    return derived().y_units_info.text();
-  }
+          double x_major_tick_width()
+          {
+            return derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width();
+          }
 
-  Derived& x_major_interval(double inter)
-  {
-    derived().x_major_interval_ = inter;
-    return derived();
-  }
+          Derived& x_minor_tick_length(double length)
+          {
+            derived().x_minor_tick_length_ = length;
+            return derived();
+          }
 
-  double x_major_interval()
-  {
-    return derived().x_major_interval_;
-  }
+          double x_minor_tick_length()
+          {
+            return derived().x_minor_tick_length_;
+          }
 
-  Derived& x_major_tick_length(double length)
-  {
-    derived().x_major_tick_length_ = length;
-    return derived();
-  }
+          Derived& x_minor_tick_width(double width)
+          {
+            derived().x_minor_tick_width_ = width;
+            derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width(width);
+            return derived();
+          }
 
-  double x_major_tick_length()
-  {
-    return derived().x_major_tick_length_;
-  }
+          double x_minor_tick_width()
+          {
+            // return derived().x_minor_tick_width_; // should be the same but store in stroke_width is definitive.
+            return derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width();
+          }
 
-  Derived& x_major_tick_width(double width)
-  {
-    derived().x_major_tick_width_ = width; // Redundant?
-    derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width(width);
-    return derived();
-  }
+          Derived& x_major_tick(double d)
+          { // Interval (Cartesian units) between major ticks.
+            derived().x_major_interval_ = d;
+          }
 
-  double x_major_tick_width()
-  {
-    return derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width();
-  }
+          double x_major_tick()
+          { // Interval (Cartesian units) between major ticks.
+            return derived().x_major_interval_;
+          }
 
-  Derived& x_minor_tick_length(double length)
-  {
-    derived().x_minor_tick_length_ = length;
-    return derived();
-  }
+          Derived& x_minor_interval(double interval)
+          { // aka x_minor_tick
+            derived().x_minor_interval_ = interval;
+            return derived();
+          }
 
-  double x_minor_tick_length()
-  {
-    return derived().x_minor_tick_length_;
-  }
+          Derived& x_num_minor_ticks(unsigned int num)
+          {
+            derived().x_num_minor_ticks_ = num;
+            return derived();
+          }
 
-  Derived& x_minor_tick_width(double width)
-  {
-    derived().x_minor_tick_width_ = width;
-    derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width(width);
-    return derived();
-  }
+          unsigned int x_num_minor_ticks()
+          { // NB NOT float or double!
+            return derived().x_num_minor_ticks_;
+          }
 
-  double x_minor_tick_width()
-  {
-   // return derived().x_minor_tick_width_; // should be the same but store in stroke_width is definitive.
-   return derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width();
-  }
-
-  Derived& x_major_tick(double d)
-  { // Interval (Cartesian units) between major ticks.
-    derived().x_major_interval_ = d;
-  }
-
-  double x_major_tick()
-  { // Interval (Cartesian units) between major ticks.
-    return derived().x_major_interval_;
-  }
-
-  Derived& x_minor_interval(double interval)
-  { // aka x_minor_tick
-    derived().x_minor_interval_ = interval;
-    return derived();
-  }
+          Derived& x_range(double min_x, double max_x)
+          {
+            if(max_x <= min_x)
+            {
+              throw std::runtime_error("Illegal Argument: X range: x_max < x_min");
+            }
+            derived().x_min = min_x;
+            derived().x_max = max_x;
+            return derived();
+          }
 
-  Derived& x_num_minor_ticks(unsigned int num)
-  {
-    derived().x_num_minor_ticks_ = num;
-    return derived();
-  }
-
-  unsigned int x_num_minor_ticks()
-  { // NB NOT float or double!
-    return derived().x_num_minor_ticks_;
-  }
+          std::pair<double, double> x_range()
+          {
+            std::pair<double, double> r;
+            r.first = derived().x_min;
+            r.second = derived().x_max;
+            return r;
+          }
 
-  Derived& x_range(double min_x, double max_x)
-  {
-    if(max_x <= min_x)
-    {
-      throw std::runtime_error("Illegal Argument: X range: x_max < x_min");
-    }
-    derived().x_min = min_x;
-    derived().x_max = max_x;
-    return derived();
-  }
+          // Avoid clashes with class svg_1d_plot variable x_min & x_max,
+          // so use longer x_minimum, x_maximum ...
+          Derived& x_minimum(double min_x)
+          {
+            // Can't check here that x_max > x_min because may not have set x_max yet.
+            // TODO ensure that there is another check somewhere.
+            derived().x_min = min_x;
+            return derived();
+          }
 
-  std::pair<double, double> x_range()
-  {
-    std::pair<double, double> r;
-    r.first = derived().x_min;
-    r.second = derived().x_max;
-    return r;
-  }
-
-  // Avoid clashes with class svg_1d_plot variable x_min & x_max,
-  // so use longer x_minimum, x_maximum ...
-  Derived& x_minimum(double min_x)
-  {
-    // Can't check here that x_max > x_min because may not have set x_max yet.
-    // TODO ensure that there is another check somewhere.
-    derived().x_min = min_x;
-    return derived();
-  }
+          double x_minimum()
+          {
+            return derived().x_min;
+          }
 
-  double x_minimum()
-  {
-    return derived().x_min;
-  }
+          Derived& x_maximum(double x)
+          {
+            // Can't check here that x_max > x_min because may not have set x_min yet.
+            // TODO check that there is another check somewhere.
+            derived().x_max = x;
+            return derived();
+          }
 
-  Derived& x_maximum(double x)
-  {
-    // Can't check here that x_max > x_min because may not have set x_min yet.
-    // TODO check that there is another check somewhere.
-    derived().x_max = x;
-    return derived();
-  }
+          double x_maximum()
+          {
+            return derived().x_max;
+          }
 
-  double x_maximum()
-  {
-    return derived().x_max;
-  }
+          // Stylesheet.
 
-  // Stylesheet.
+          Derived& load_stylesheet(const std::string& file)
+          {
+            derived().image.load_stylesheet(file);
+            return derived();
+          }
 
-  Derived& load_stylesheet(const std::string& file)
-  {
-    derived().image.load_stylesheet(file);
-    return derived();
-  }
+          // Image info (& identical const version).
 
-  // Image info (& identical const version).
+          svg& get_svg()
+          {
+            derived()._update_image();
+            return derived().image;
+          }
 
-  svg& get_svg()
-  {
-    derived()._update_image();
-    return derived().image;
-  }
+          const svg& get_svg() const
+          {
+            derived()._update_image();
+            return derived().image;
+          }
+        }; // template <class Derived> class axis_plot_frame
 
-  const svg& get_svg() const
-  {
-    derived()._update_image();
-    return derived().image;
-  }
-}; // template <class Derived> class axis_plot_frame
-
-} // detail
-} // svg
-} // boost
+      } // detail
+    } // svg
+  } // boost
 
 #endif // BOOST_SVG_AXIS_PLOT_FRAME_HPP
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp	2007-12-20 07:14:05 EST (Thu, 20 Dec 2007)
@@ -164,13 +164,13 @@
   // TODO SVG has also a not yet implemented boldness.
   double title_width_; 
   double legend_width_;
-  double legend_x1_; // Left of legend box. (Optionally set by legend_position).
-  double legend_y1_; // Top of legend box.
+  double legend_left_; // Left of legend box. (Optionally set by legend_position).
+  double legend_top_; // Top of legend box.
   // Size of legend box is controlled by its contents,
   // but may be helpful to store bottom right coordinates.
   // legend_bottom_right() gives access.
-  double legend_x2_; // right of legend box.
-  double legend_y2_; // bottom of legend box.
+  double legend_right_; // right of legend box.
+  double legend_bottom_; // bottom of legend box.
 
   // X-Axis information.
   // (Y_axis stored as one point because this is a 1D graph).
@@ -236,7 +236,7 @@
     //x_units_info(0, 0, "(units)", 14, "Times New Roman", "italic", "bold", "wider", "underline", right_align, horizontal),
     text_margin_(2.), // for text was 1.5 // as a fraction of the font size.
     border_margin_(5), // Prevent plot window box begin right on edge.
-    legend_x1_(-1), legend_x2_(-1),legend_y1_(-1),legend_y2_(-1), // Indicates not yet set.
+    legend_left_(-1), legend_right_(-1),legend_top_(-1),legend_bottom_(-1), // Indicates not yet set.
 
     x_min(-10), x_max(10),
     use_legend(false),
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp	2007-12-20 07:14:05 EST (Thu, 20 Dec 2007)
@@ -52,1697 +52,1704 @@
 
 #ifndef BOOST_SVG_BOOST_PARAMETER_NAMES
 #define BOOST_SVG_BOOST_PARAMETER_NAMES
-  BOOST_PARAMETER_NAME(my_plot)
-  BOOST_PARAMETER_NAME(container)
-  BOOST_PARAMETER_NAME(title)
-  BOOST_PARAMETER_NAME(stroke_color)
-  BOOST_PARAMETER_NAME(fill_color)
-  BOOST_PARAMETER_NAME(point_style)
-  BOOST_PARAMETER_NAME(x_functor)
-  BOOST_PARAMETER_NAME(size)
+    BOOST_PARAMETER_NAME(my_plot)
+      BOOST_PARAMETER_NAME(container)
+      BOOST_PARAMETER_NAME(title)
+      BOOST_PARAMETER_NAME(stroke_color)
+      BOOST_PARAMETER_NAME(fill_color)
+      BOOST_PARAMETER_NAME(point_style)
+      BOOST_PARAMETER_NAME(x_functor)
+      BOOST_PARAMETER_NAME(size)
 #endif
-  // TODO Why are these outside the #endif? Subset?
-  // Remove when class plot used instead of Boost.Parameter.
-  BOOST_PARAMETER_NAME(bezier_on)
-  BOOST_PARAMETER_NAME(line_on)
-  BOOST_PARAMETER_NAME(line_color)
-  BOOST_PARAMETER_NAME(area_fill_color)
-
-  // -----------------------------------------------------------------
-  // This allows us to store plot state locally in svg_plot. We don't
-  // store it in "svg" because transforming the points after they are
-  // written to the document would be difficult. We store the Cartesian
-  // coordinates locally and transform them before we write them.
-  // -----------------------------------------------------------------
-struct svg_2d_plot_series;
-class svg_2d_plot;
+      // TODO Why are these outside the #endif? Subset?
+      // Remove when class plot used instead of Boost.Parameter.
+      BOOST_PARAMETER_NAME(bezier_on)
+      BOOST_PARAMETER_NAME(line_on)
+      BOOST_PARAMETER_NAME(line_color)
+      BOOST_PARAMETER_NAME(area_fill_color)
+
+      // -----------------------------------------------------------------
+      // This allows us to store plot state locally in svg_plot. We don't
+      // store it in "svg" because transforming the points after they are
+      // written to the document would be difficult. We store the Cartesian
+      // coordinates locally and transform them before we write them.
+      // -----------------------------------------------------------------
+    struct svg_2d_plot_series;
+    class svg_2d_plot;
 
-static const double wh_ = 0.7; // font text width/height ratio.
-static const double sin45 = 0.707; // Use if axis value labels are sloping.
+    static const double wh_ = 0.7; // font text width/height ratio.
+    static const double sin45 = 0.707; // Use if axis value labels are sloping.
 
     enum y_axis_intersect {left = -1, y_intersect = 0, right = +1};
     enum x_axis_intersect {bottom = -1, x_intersect = 0, top = +1};
 
-struct svg_2d_plot_series
-{
-  // 2-D Data series points to plot.
-  std::multimap<double, double> series; // Normal 'OK to plot' data values.
-  std::multimap<double, double> series_limits; // 'limit' values: too big or small, or NaN.
-  // multimap is used rather than vector of pairs because
-  // multimap sorts and ensures that lines joining data points
-  // are unaffected by the order in which data is presented.
-  // (For 1-D a vector of doubles can be used).
-
-  std::string title;
-  plot_point_style point_style;
-  plot_line_style line_style;
-
-  template <class T>
-  svg_2d_plot_series(T begin, T end,
-    std::string title, // of data series.
-    const plot_point_style& point,
-    const plot_line_style& line)
-    :
-  title(title),
-    point_style(point),
-    line_style(line)
-  { // Constructor.
-    for(T i = begin; i != end; ++i)
-    { // Sort into normal and limited series.
-      if(detail::pair_is_limit(*i))
-      { // Either x and/or y is at limit.
-        series_limits.insert(*i);
-      }
-      else
-      { // normal point.
-        series.insert(*i);
-      }
-    }
-  } // svg_2d_plot_series
-}; // struct svg_2d_plot_series
+    struct svg_2d_plot_series
+    {
+      // 2-D Data series points to plot.
+      std::multimap<double, double> series; // Normal 'OK to plot' data values.
+      std::multimap<double, double> series_limits; // 'limit' values: too big or small, or NaN.
+      // multimap is used rather than vector of pairs because
+      // multimap sorts and ensures that lines joining data points
+      // are unaffected by the order in which data is presented.
+      // (For 1-D a vector of doubles can be used).
+
+      std::string title;
+      plot_point_style point_style;
+      plot_line_style line_style;
+
+      template <class T>
+      svg_2d_plot_series(T begin, T end,
+        std::string title, // of data series.
+        const plot_point_style& point,
+        const plot_line_style& line)
+        :
+      title(title),
+        point_style(point),
+        line_style(line)
+      { // Constructor.
+        for(T i = begin; i != end; ++i)
+        { // Sort into normal and limited series.
+          if(detail::pair_is_limit(*i))
+          { // Either x and/or y is at limit.
+            series_limits.insert(*i);
+          }
+          else
+          { // normal point.
+            series.insert(*i);
+          }
+        }
+      } // svg_2d_plot_series
+    }; // struct svg_2d_plot_series
 
-class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
-{ // See also svg_1d_plot.hpp for 1-D version.
 
-private:
-  friend class detail::axis_plot_frame<svg_2d_plot>;
-  // Contains functions common to 1 and 2-D.
-
-  double x_scale; // Use by function transform()
-  double x_shift; // to go from Cartesian to svg coordinates.
-  double y_scale;
-  double y_shift;
-
-  // Stored so as to avoid rewriting style information constantly.
-  svg image;
-
-  text_style a_style; // Defaults.
-
-  text_element title_info; // Plot title.
-  text_element legend_header_; // legend box header or title (if any).
-  text_element x_label_info; // For example: "length"
-  text_element x_label_value; // For example: "1.2" or "1.2e+001"
-  text_element y_label_info; // For example: "volume"
-  text_element x_units_info; // For example: "mm"
-  text_element y_units_info; // 2-D only.
-  text_element y_label_value; // For example: "1.2" or "1.2e+001"
-
-  int x_value_precision_; // precision for tick value labels, usually 3 will suffice.
-  int y_value_precision_; // precision for tick value labels, usually 3 will suffice.
-  // Used to decide how much space to allow for tick values.
-  int x_value_ioflags_;  // IO formatting flags for X-axis.
-  int y_value_ioflags_;  // IO formatting flags for Y-axis.
-  double text_margin_; // Marginal space around text items like title,
-  // as a fraction of font size, (pixels) (was fixed at 1.5).
-  double border_margin_; // Marginal (pixels) space around the plot border.
-  double border_width_; // plot border rectangle width.
-
-  // Border information for the plot window (<= image size).
-  // Allows for title and legend to be separate.
-  // Initially will be set to the width and height of the graph image.
-  // calculate_plot_window() sets these values.
-  double plot_x1; // TODO These (and many others) also could be float?
-  double plot_x2;
-  double plot_y1;
-  double plot_y2;
-
-  // X-Axis information.
-  double x_min; // minimum x value (Cartesian units).
-  double x_max; // maximum x value (Cartesian units).
-  double x_axis; // // x-axis (y = 0) transformed into SVG Y coordinates. -1 if not caculated yet.
-  double x_major_interval_; // x_major_interval_ is the stride or interval for major x ticks.
-  // (Cartesian units)  set/get by x_major_interval
-  double x_minor_interval_; // Interval (Cartesian units) between minor ticks.
-  // No set function because x_num_minor_ticks_ used to determine this instead,
-  // but one could calculate x_minor_interval_.
-
-  // text width is effectively the boldness of the font.
-  // But only in graphics mode rather than text mode, and style "bold"
-  // and this is poor on some browsers, so recommend to not set width.
-  // 0 is default, 1 is bolder, 2 very bold and a not-yet-implemented boldness.
-  double image_border_width_;
-  double title_font_width_;
-  double legend_font_width_;
-  double legend_width_; // width of legend box in pixels.
-  double legend_height_; // height of legend box in pixels.
-  double legend_x1_; // Left of legend box. (Optionally set by legend_top_left).
-  double legend_y1_; // Top of legend box.
-  // Size of legend box is controlled by its contents,
-  // but may be helpful to store bottom right coordinates.
-  // legend_bottom_right() gives access.
-  double legend_x2_; // right of legend box.
-  double legend_y2_; // bottom of legend box.
-  size_t legend_longest_; // longest string in legend box.
-  double x_label_width_; // Used for value too.
-  double x_axis_width_; // X-axis horizontal line width. set/get by x_axis_width()
-  double x_major_tick_length_; // pixels.
-  double x_major_tick_width_; // pixels.
-  double x_minor_tick_length_; // pixels.
-  double x_minor_tick_width_; // pixels.
-  // Avoid name clash with x_m*_tick_length and width.
-  unsigned int x_num_minor_ticks_; // number of minor ticks, eg 4 gives major 0, minor 1,2,3,4, major 5
-  double x_major_grid_width_; // pixels.
-  double x_minor_grid_width_; // pixels.
-  // grid width is set in style.stroke_width
-  int x_axis_position_; // 
-
-  // Y-Axis information.
-  unsigned int y_num_minor_ticks_; // number of minor ticks, eg 4 gives major 0, minor 1,2,3,4, major 5
-  double y_min; // minimum y value (Cartesian units).
-  double y_max; // maximum y value (Cartesian units).
-  double y_major_interval_; // y_major_interval_ is the stride or interval for major y ticks.
-  double y_minor_interval_; // y_minor_interval_ is the stride or interval for minor y ticks.
-  double y_label_width_; // TODO used for axis width too for now.  OK?
-  double y_axis; // Y-axis (x = 0) transformed into X SVG coordinates. -1 if not caculated yet.
-  double y_axis_width_; // Y-axis vertical line width.  set/get by y_axis_width()
-  double y_major_tick_length_; // pixels.
-  double y_major_tick_width_; // pixels.
-  double y_minor_tick_length_; // pixels.
-  double y_minor_tick_width_; // pixels.
-  // Avoid name clash with x_m*_tick_length and width.
-  // grid width is set in style.stroke_width
-  double y_major_grid_width_; // pixels.
-  double y_minor_grid_width_; // pixels.
-  double x_label_length_; // width (in SVG) of longest label on X-axis.
-  double y_label_length_; // width (in SVG) of longest label on Y-axis.
-  int y_axis_position_; // 
-
-  // Yes/no options.
-  bool use_title; // Provide a title for the whole plot.
-  bool use_legend; // Provide a legend box.
-  bool use_axis; // Draw x and y axes.  TODO split so can have either or both.
-  bool use_plot_window_; // Use a separate plot window.
-  bool use_x_label; // Label axis with text.
-  bool use_y_label;
-  bool use_x_major_labels; // values for major ticks.
-  bool use_y_major_labels;
-  bool use_x_label_units;
-  bool use_y_label_units;
-  int x_label_rotation_; // X_axis value labels written.
-  int y_label_rotation_; // Y_axis value labels written.
-  bool use_x_major_grid_;
-  bool use_x_minor_grid_;
-  bool use_y_major_grid_;
-  bool use_y_minor_grid_;
-
-  // Note: can have ticks both up and/or down, and/or left and right.
-  bool use_up_ticks;
-  bool use_down_ticks;
-  bool use_x_ticks; // = use_up_ticks || use_down_ticks
-  bool use_left_ticks;
-  bool use_right_ticks;
- // bool use_y_ticks; // = use_left_ticks || use_right_ticks
-  // was external style.
-  bool use_x_ticks_on_plot_window_; // Value labels & ticks on the plot window rather than on X-axis.
-  bool use_y_ticks_on_plot_window_; // Value labels & ticks on the plot window rather than on Y-axis.
-  bool use_x_axis_lines_; // Draw a horizontal X-axis line.
-  bool use_y_axis_lines_; // Draw a vertical Y-axis line.
-  bool use_line; // get/set by line_on(bool); // Not really useful for 1-D,
-  // TODO but needs Boost-Parameter removed to do properly.
-  bool strip_e0s_;
-  unsigned int longest_; // string in legend box.
-
-  // Where we will be storing the data points (series) for transformation.
-  std::vector<svg_2d_plot_series> series; // Defined above.
-
-  std::string plot_window_clip; // = "clip_plot_window" id for clippath
-
-  // http://www.w3.org/TR/SVG/masking.html#ClipPathElement 14.1 Introduction
-  // clipping paths, which uses any combination of 'path', 'text' and basic shapes
-  // to serve as the outline where everything on the "inside" of the outline
-  // is allowed to show through but everything on the outside is masked out.
-  // So the plot_window_clip limits display to a plot_window rectangle.
-
-  //text_style label_style(40); // Or use all defaults.
-  //text_style(int size = 12,  // defaults:
-  //const std::string& font = "sans",
-  //const std::string& style = "",
-  //const std::string& weight = "",
-  //const std::string& stretch = "",
-  //const std::string& decoration = "")
-  //label_style().font_weight("bold");
-
-public: // of class svg_2d_plot: public detail::axis_plot_frame<svg_2d_plot>
-
-  svg_2d_plot() // Constructor, including all the very many default plot options.
-    :
-    // TODO check that *all* options are initialized here.
-    // See documentation for default settings rationale.
-
-
-    a_style(16, "serif"),
-    title_info(0, 0, "Plot of data", 16, "Verdana", "", "", "", "", center_align, horizontal),
-    title_font_width_(1),  // text width is effectively the boldness of the font.
-    legend_width_(200), // width of legend box (pixels)
-    legend_header_(0, 0, "", 14, "Verdana", "italic", "", "bold", "", center_align, horizontal),
-    legend_font_width_(0.5),
-    x_label_info(0, 0, "X Axis", 14, "Verdana", "", "bold", "", "", center_align, horizontal),
-    x_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, horizontal, a_style),
-    x_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, horizontal),
-    // TODO use this and provide way to set'n'get separately.
-    x_axis(-1), // -1 means not yet valid.
-    y_axis(-1), // -1 means not yet valid.
-    x_label_width_(2),
-    x_axis_width_(2), // Width of X-axis line.
-    y_label_info(0, 0, "Y Axis", 14, "Verdana", "", "bold", "", "", center_align, upward),
-    y_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, upward),
-    y_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, upward),
-    y_label_width_(5),
-    y_axis_width_(2), // vertical line.
-    x_label_rotation_(horizontal),
-    y_label_rotation_(horizontal),
-    // Plot may look odd if font and size of label & units are different!
-    // y_units_info(0, 0, "(units)", 11, "Times New Roman", "italic", "bold", "wider", "underline", right_align, upsidedown),
-    // shows some values that might be useful if svg browsers are fully implemented
-    // to support font modification to text characters.
-    // italic and bold seem the only ones working at present.
-    x_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
-    x_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
-    y_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
-    y_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
-    // Note that ALL the flags are set, overwriting any defaults, so std::dec is wise.
-    image_border_width_(1),
-    text_margin_(2.), // for axis label text, as a multiplier of the font size.
-    border_margin_(10), // Prevent plot window box beginning right on edge,
-    border_width_(20), // width of any border to plot window and legend box.
-    // less than half the font size of label value will result in clipping.
-    // plot_x1, x2, y1, 2 are set in calculate_plot_window
-    legend_x1_(-1), legend_x2_(-1),legend_y1_(-1),legend_y2_(-1), // -1 Indicates not yet set.
-    x_min(-10), x_max(10), // so plots range from -10 to +10
-    y_min(-10), y_max(10),
-    x_major_interval_(2), // x stride between major ticks & value label.
-    y_major_interval_(2), // y stride
-    // Ticks on axes.
-    x_num_minor_ticks_(4), // suits
-    y_num_minor_ticks_(4), // suits: major 0, minor 2, 4, 6, 8, major 10
-    x_major_tick_length_(10.), // If both up and down, total is twice this.
-    x_minor_tick_length_(5.),
-    x_major_tick_width_(2.),
-    x_minor_tick_width_(1.),
-    y_major_tick_length_(10.), // If both left and right, total is twice this.
-    y_minor_tick_length_(5.),
-    y_major_tick_width_(2.),
-    y_minor_tick_width_(1.),
-    // grids
-    x_major_grid_width_(1.),
-    x_minor_grid_width_(0.5),
-    y_major_grid_width_(1.),
-    y_minor_grid_width_(0.5),
-    // Use by transform Cartesian to SVG.
-    x_scale(1.), x_shift(0.),
-    y_scale(1.), y_shift(0.),
-    x_minor_interval_(0), // These are calculated from x & y_num_minor_ticks_
-    y_minor_interval_(0), // but given a value here for safety.
-    x_axis_position_(0),
-    y_axis_position_(0),
-    x_label_length_(0),
-    y_label_length_(0),
-
-    plot_window_clip("plot_window"), // for <clipPath id="plot_window" ...
-
-    // Boolean options.
-    strip_e0s_(false),
-    use_down_ticks(true), // On X-axis.
-    use_up_ticks(false), // external ticks only.
-    //use_x_ticks(false), // = use_up_ticks || use_down_ticks
-    use_left_ticks(true), // On y-axis.
-    use_right_ticks(false), // On y-axis
-    //use_y_ticks(true), // = use_left_ticks || use_right_ticks  TODO get rid of this. NOT useful
-    use_x_ticks_on_plot_window_(false), // was external_style
-    use_y_ticks_on_plot_window_(false), // was external_style
-    use_x_label_units(false),
-    use_y_label_units(false),
-    use_x_major_labels(true), // tick value labels.
-    use_y_major_labels(true),
-    use_x_label(true), // "X-axis"
-    use_y_label(true), // "Y-axis" - true for 2-D, false for 1-D.
-    use_title(true),
-    use_legend(false), use_axis(true),
-    use_x_axis_lines_(true), // draw horizontal X-axis line.
-    use_y_axis_lines_(true), // draw vertical Y-axis line.
-    use_x_major_grid_(true),
-    use_x_minor_grid_(false),
-    use_y_major_grid_(true),
-    use_y_minor_grid_(false),
-    use_plot_window_(true),
-    use_line(true)
-    // TODO but needs Boost-Parameter removed to do properly.
-
-  {
-    image_size(500, 400); // Default image size for 2-D.
-    // 2-D usually needs to be squarer than 1-D.
+ 
+    class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
+    { // See also svg_1d_plot.hpp for 1-D version.
+
+    private:
+      friend class detail::axis_plot_frame<svg_2d_plot>;
+      // Contains functions common to 1 and 2-D.
+
+      double x_scale; // Use by function transform()
+      double x_shift; // to go from Cartesian to svg coordinates.
+      double y_scale;
+      double y_shift;
+
+      // Stored so as to avoid rewriting style information constantly.
+      svg image;
+
+      text_style a_style; // Defaults.
+
+      text_element title_info; // Plot title.
+      text_element legend_header_; // legend box header or title (if any).
+      text_element x_label_info; // For example: "length"
+      text_element x_label_value; // For example: "1.2" or "1.2e+001"
+      text_element y_label_info; // For example: "volume"
+      text_element x_units_info; // For example: "mm"
+      text_element y_units_info; // 2-D only.
+      text_element y_label_value; // For example: "1.2" or "1.2e+001"
+
+      int x_value_precision_; // precision for tick value labels, usually 3 will suffice.
+      int y_value_precision_; // precision for tick value labels, usually 3 will suffice.
+      // Used to decide how much space to allow for tick values.
+      int x_value_ioflags_;  // IO formatting flags for X-axis.
+      int y_value_ioflags_;  // IO formatting flags for Y-axis.
+      double text_margin_; // Marginal space around text items like title,
+      // as a fraction of font size, (pixels) (was fixed at 1.5).
+      double border_margin_; // Marginal (pixels) space around the plot border.
+      double border_width_; // plot border rectangle width.
+
+      // Border information for the plot window (<= image size).
+      // Allows for title and legend to be separate.
+      // Initially will be set to the width and height of the graph image.
+      // calculate_plot_window() sets these values.
+      double plot_x1; // TODO These (and many others) also could be float?
+      double plot_x2;
+      double plot_y1;
+      double plot_y2;
+
+      // X-Axis information.
+      double x_min; // minimum x value (Cartesian units).
+      double x_max; // maximum x value (Cartesian units).
+      double x_axis; // // x-axis (y = 0) transformed into SVG Y coordinates. -1 if not caculated yet.
+      double x_major_interval_; // x_major_interval_ is the stride or interval for major x ticks.
+      // (Cartesian units)  set/get by x_major_interval
+      double x_minor_interval_; // Interval (Cartesian units) between minor ticks.
+      // No set function because x_num_minor_ticks_ used to determine this instead,
+      // but one could calculate x_minor_interval_.
+
+      // text width is effectively the boldness of the font.
+      // But only in graphics mode rather than text mode, and style "bold"
+      // and this is poor on some browsers, so recommend to not set width.
+      // 0 is default, 1 is bolder, 2 very bold and a not-yet-implemented boldness.
+      double image_border_width_;
+      double title_font_width_;
+      double legend_font_width_;
+      legend_places legend_place_;
+      double legend_width_; // width of legend box in pixels.
+      double legend_height_; // height of legend box in pixels.
+      double legend_left_; // Left of legend box. (Optionally set by legend_top_left).
+      double legend_top_; // Top of legend box.
+      // Size of legend box is controlled by its contents,
+      // but may be helpful to store bottom right coordinates.
+      // legend_bottom_right() gives access.
+      double legend_right_; // right of legend box.
+      double legend_bottom_; // bottom of legend box.
+      size_t legend_longest_; // longest string in legend box.
+      double x_label_width_; // Used for value too.
+      double x_axis_width_; // X-axis horizontal line width. set/get by x_axis_width()
+      double x_major_tick_length_; // pixels.
+      double x_major_tick_width_; // pixels.
+      double x_minor_tick_length_; // pixels.
+      double x_minor_tick_width_; // pixels.
+      // Avoid name clash with x_m*_tick_length and width.
+      unsigned int x_num_minor_ticks_; // number of minor ticks, eg 4 gives major 0, minor 1,2,3,4, major 5
+      double x_major_grid_width_; // pixels.
+      double x_minor_grid_width_; // pixels.
+      // grid width is set in style.stroke_width
+      int x_axis_position_; // 
+
+      // Y-Axis information.
+      unsigned int y_num_minor_ticks_; // number of minor ticks, eg 4 gives major 0, minor 1,2,3,4, major 5
+      double y_min; // minimum y value (Cartesian units).
+      double y_max; // maximum y value (Cartesian units).
+      double y_major_interval_; // y_major_interval_ is the stride or interval for major y ticks.
+      double y_minor_interval_; // y_minor_interval_ is the stride or interval for minor y ticks.
+      double y_label_width_; // TODO used for axis width too for now.  OK?
+      double y_axis; // Y-axis (x = 0) transformed into X SVG coordinates. -1 if not caculated yet.
+      double y_axis_width_; // Y-axis vertical line width.  set/get by y_axis_width()
+      double y_major_tick_length_; // pixels.
+      double y_major_tick_width_; // pixels.
+      double y_minor_tick_length_; // pixels.
+      double y_minor_tick_width_; // pixels.
+      // Avoid name clash with x_m*_tick_length and width.
+      // grid width is set in style.stroke_width
+      double y_major_grid_width_; // pixels.
+      double y_minor_grid_width_; // pixels.
+      double x_label_length_; // width (in SVG) of longest label on X-axis.
+      double y_label_length_; // width (in SVG) of longest label on Y-axis.
+      int y_axis_position_; // 
+
+      // Yes/no options.
+      bool use_title; // Provide a title for the whole plot.
+      bool use_legend; // Provide a legend box. 
+      bool use_outside_legend_;
+      bool use_axis; // Draw x and y axes.  TODO split so can have either or both.
+      bool use_plot_window_; // Use a separate plot window.
+      bool use_x_label; // Label axis with text.
+      bool use_y_label;
+      bool use_x_major_labels; // values for major ticks.
+      bool use_y_major_labels;
+      bool use_x_label_units;
+      bool use_y_label_units;
+      int x_label_rotation_; // X_axis value labels written.
+      int y_label_rotation_; // Y_axis value labels written.
+      bool use_x_major_grid_;
+      bool use_x_minor_grid_;
+      bool use_y_major_grid_;
+      bool use_y_minor_grid_;
+
+      // Note: can have ticks both up and/or down, and/or left and right.
+      bool use_up_ticks;
+      bool use_down_ticks;
+      bool use_x_ticks; // = use_up_ticks || use_down_ticks
+      bool use_left_ticks;
+      bool use_right_ticks;
+      // bool use_y_ticks; // = use_left_ticks || use_right_ticks
+      // was external style.
+      bool use_x_ticks_on_plot_window_; // Value labels & ticks on the plot window rather than on X-axis.
+      bool use_y_ticks_on_plot_window_; // Value labels & ticks on the plot window rather than on Y-axis.
+      bool use_x_axis_lines_; // Draw a horizontal X-axis line.
+      bool use_y_axis_lines_; // Draw a vertical Y-axis line.
+      bool use_line; // get/set by line_on(bool); // Not really useful for 1-D,
+      // TODO but needs Boost-Parameter removed to do properly.
+      bool strip_e0s_;
+      unsigned int longest_; // string in legend box.
+
+      // Where we will be storing the data points (series) for transformation.
+      std::vector<svg_2d_plot_series> series; // Defined above.
+
+      std::string plot_window_clip; // = "clip_plot_window" id for clippath
+
+      // http://www.w3.org/TR/SVG/masking.html#ClipPathElement 14.1 Introduction
+      // clipping paths, which uses any combination of 'path', 'text' and basic shapes
+      // to serve as the outline where everything on the "inside" of the outline
+      // is allowed to show through but everything on the outside is masked out.
+      // So the plot_window_clip limits display to a plot_window rectangle.
+
+      //text_style label_style(40); // Or use all defaults.
+      //text_style(int size = 12,  // defaults:
+      //const std::string& font = "sans",
+      //const std::string& style = "",
+      //const std::string& weight = "",
+      //const std::string& stretch = "",
+      //const std::string& decoration = "")
+      //label_style().font_weight("bold");
+
+    public: // of class svg_2d_plot: public detail::axis_plot_frame<svg_2d_plot>
+
+      svg_2d_plot() // Constructor, including all the very many default plot options.
+        :
+      // TODO check that *all* options are initialized here.
+      // See documentation for default settings rationale.
+
+      a_style(16, "serif"),
+        title_info(0, 0, "Plot of data", 16, "Verdana", "", "", "", "", center_align, horizontal),
+        title_font_width_(1),  // text width is effectively the boldness of the font.
+        legend_width_(200), // width of legend box (pixels)
+        legend_header_(0, 0, "", 14, "Verdana", "italic", "", "bold", "", center_align, horizontal),
+        legend_font_width_(0.5),
+        x_label_info(0, 0, "X Axis", 14, "Verdana", "", "bold", "", "", center_align, horizontal),
+        x_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, horizontal, a_style),
+        x_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, horizontal),
+        // TODO use this and provide way to set'n'get separately.
+        x_axis(-1), // -1 means not yet valid.
+        y_axis(-1), // -1 means not yet valid.
+        x_label_width_(2),
+        x_axis_width_(2), // Width of X-axis line.
+        y_label_info(0, 0, "Y Axis", 14, "Verdana", "", "bold", "", "", center_align, upward),
+        y_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, upward),
+        y_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, upward),
+        y_label_width_(5),
+        y_axis_width_(2), // vertical line.
+        x_label_rotation_(horizontal),
+        y_label_rotation_(horizontal),
+        // Plot may look odd if font and size of label & units are different!
+        // y_units_info(0, 0, "(units)", 11, "Times New Roman", "italic", "bold", "wider", "underline", right_align, upsidedown),
+        // shows some values that might be useful if svg browsers are fully implemented
+        // to support font modification to text characters.
+        // italic and bold seem the only ones working at present.
+        x_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
+        x_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
+        y_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
+        y_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
+        // Note that ALL the flags are set, overwriting any defaults, so std::dec is wise.
+        image_border_width_(1),
+        text_margin_(2.), // for axis label text, as a multiplier of the font size.
+        border_margin_(10), // Prevent plot window box beginning right on edge,
+        border_width_(20), // width of any border to plot window and legend box.
+        // less than half the font size of label value will result in clipping.
+        // plot_x1, x2, y1, 2 are set in calculate_plot_window
+        legend_left_(-1), legend_right_(-1),legend_top_(-1),legend_bottom_(-1), // Default top left of plot window.
+        legend_place_(inside), // default but interacts with using plot_window
+        x_min(-10), x_max(10), // so plots range from -10 to +10
+        y_min(-10), y_max(10),
+        x_major_interval_(2), // x stride between major ticks & value label.
+        y_major_interval_(2), // y stride
+        // Ticks on axes.
+        x_num_minor_ticks_(4), // suits
+        y_num_minor_ticks_(4), // suits: major 0, minor 2, 4, 6, 8, major 10
+        x_major_tick_length_(10.), // If both up and down, total is twice this.
+        x_minor_tick_length_(5.),
+        x_major_tick_width_(2.),
+        x_minor_tick_width_(1.),
+        y_major_tick_length_(10.), // If both left and right, total is twice this.
+        y_minor_tick_length_(5.),
+        y_major_tick_width_(2.),
+        y_minor_tick_width_(1.),
+        // grids
+        x_major_grid_width_(1.),
+        x_minor_grid_width_(0.5),
+        y_major_grid_width_(1.),
+        y_minor_grid_width_(0.5),
+        // Use by transform Cartesian to SVG.
+        x_scale(1.), x_shift(0.),
+        y_scale(1.), y_shift(0.),
+        x_minor_interval_(0), // These are calculated from x & y_num_minor_ticks_
+        y_minor_interval_(0), // but given a value here for safety.
+        x_axis_position_(0),
+        y_axis_position_(0),
+        x_label_length_(0),
+        y_label_length_(0),
+
+        plot_window_clip("plot_window"), // for <clipPath id="plot_window" ...
+
+        // Boolean options.
+        strip_e0s_(false),
+        use_down_ticks(true), // On X-axis.
+        use_up_ticks(false), // external ticks only.
+        //use_x_ticks(false), // = use_up_ticks || use_down_ticks
+        use_left_ticks(true), // On y-axis.
+        use_right_ticks(false), // On y-axis
+        //use_y_ticks(true), // = use_left_ticks || use_right_ticks  TODO get rid of this. NOT useful
+        use_x_ticks_on_plot_window_(false), // was external_style
+        use_y_ticks_on_plot_window_(false), // was external_style
+        use_x_label_units(false),
+        use_y_label_units(false),
+        use_x_major_labels(true), // tick value labels.
+        use_y_major_labels(true),
+        use_x_label(true), // "X-axis"
+        use_y_label(true), // "Y-axis" - true for 2-D, false for 1-D.
+        use_title(true),
+        use_legend(false),
+        use_outside_legend_(true),
+        use_axis(true),
+        use_x_axis_lines_(true), // draw horizontal X-axis line.
+        use_y_axis_lines_(true), // draw vertical Y-axis line.
+        use_x_major_grid_(true),
+        use_x_minor_grid_(false),
+        use_y_major_grid_(true),
+        use_y_minor_grid_(false),
+        use_plot_window_(false),
+        use_line(true)
+        // TODO but needs Boost-Parameter removed to do properly.
 
-    using namespace boost::svg::detail; // avoid detail::
+      {
+        image_size(500, 400); // Default image size for 2-D.
+        // 2-D usually needs to be squarer than 1-D.
 
-    // Build the document tree by adding all children of the root node.
-    for(int i = 0; i < SVG_PLOT_DOC_CHILDREN; ++i)
-    {
-      image.add_g_element();
-    }
-    set_ids();
+        using namespace boost::svg::detail; // avoid detail::
 
-    // Set other SVG color, stroke & width defaults for various child PLOT nodes.
+        // Build the document tree by adding all children of the root node.
+        for(int i = 0; i < SVG_PLOT_DOC_CHILDREN; ++i)
+        {
+          image.add_g_element();
+        }
+        set_ids();
 
-    // Tick length etc is now set above in the constructor, but width & color here.
-    image.get_g_element(PLOT_BACKGROUND).style().fill_color(white);
-    image.get_g_element(PLOT_BACKGROUND).style().stroke_color(yellow); // TODO test only ?
-    image.get_g_element(PLOT_BACKGROUND).style().stroke_width(image_border_width_); //
-    image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color(white);
-    image.get_g_element(PLOT_WINDOW_BACKGROUND).style().stroke_width(1).stroke_color(yellow);
-    image.get_g_element(PLOT_LIMIT_POINTS).style().stroke_color(lightslategray).fill_color(antiquewhite);
-    image.get_g_element(PLOT_X_AXIS).style().stroke_color(black).stroke_width(x_axis_width_);
-    image.get_g_element(PLOT_Y_AXIS).style().stroke_color(black).stroke_width(y_axis_width_);
-    image.get_g_element(PLOT_X_LABEL).style().fill_color(black);
-    image.get_g_element(PLOT_Y_LABEL).style().fill_color(black);
-    image.get_g_element(PLOT_VALUE_LABELS).style().fill_color(black); // text
-    image.get_g_element(PLOT_LEGEND_TEXT).style().fill_color(black);
-    image.get_g_element(PLOT_TITLE).style().fill_color(black).stroke_on(false);
-    // If stroke color is not set, then get a very 'thin' font and width has no effect.
-    // Firefox text is rather thin compared to IE.
+        // Set other SVG color, stroke & width defaults for various child PLOT nodes.
 
-    // Note that widths are stored in member data *and* copied here.
-    // Not sure if this is wise but ...
+        // Tick length etc is now set above in the constructor, but width & color here.
+        image.get_g_element(PLOT_BACKGROUND).style().fill_color(white);
+        image.get_g_element(PLOT_BACKGROUND).style().stroke_color(yellow); // TODO test only ?
+        image.get_g_element(PLOT_BACKGROUND).style().stroke_width(image_border_width_); //
+        image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color(white);
+        image.get_g_element(PLOT_WINDOW_BACKGROUND).style().stroke_width(1).stroke_color(yellow);
+        image.get_g_element(PLOT_LIMIT_POINTS).style().stroke_color(lightslategray).fill_color(antiquewhite);
+        image.get_g_element(PLOT_X_AXIS).style().stroke_color(black).stroke_width(x_axis_width_);
+        image.get_g_element(PLOT_Y_AXIS).style().stroke_color(black).stroke_width(y_axis_width_);
+        image.get_g_element(PLOT_X_LABEL).style().fill_color(black);
+        image.get_g_element(PLOT_Y_LABEL).style().fill_color(black);
+        image.get_g_element(PLOT_VALUE_LABELS).style().fill_color(black); // text
+        image.get_g_element(PLOT_LEGEND_TEXT).style().fill_color(black);
+        image.get_g_element(PLOT_TITLE).style().fill_color(black).stroke_on(false);
+        // If stroke color is not set, then get a very 'thin' font and width has no effect.
+        // Firefox text is rather thin compared to IE.
 
-    // Ticks
-    if(use_up_ticks || use_down_ticks)
-    {
-      image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width(x_major_tick_width_).stroke_color(black);
-      image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width(x_minor_tick_width_).stroke_color(black);
-    }
-    if(use_left_ticks || use_right_ticks)
-    {
-      image.get_g_element(PLOT_Y_MAJOR_TICKS).style().stroke_width(y_major_tick_width_).stroke_color(black);
-      image.get_g_element(PLOT_Y_MINOR_TICKS).style().stroke_width(y_minor_tick_width_).stroke_color(black);
-    }
-    // Grids.
-    // Default color & width for grid, used or not.
-      image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width(x_major_grid_width_).stroke_color(svg_color(200, 220, 255));
-      BOOST_ASSERT(image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_color() == svg_color(200, 220, 255));
-      image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_width(x_minor_grid_width_).stroke_color(svg_color(200, 220, 255));
-      image.get_g_element(PLOT_Y_MAJOR_GRID).style().stroke_width(y_major_grid_width_).stroke_color(svg_color(200, 220, 255));
-      image.get_g_element(PLOT_Y_MINOR_GRID).style().stroke_width(y_minor_grid_width_).stroke_color(svg_color(200, 220, 255));
-      image.get_g_element(PLOT_DATA_LINES).style().stroke_width(2);
-
-  } // svg_2d_plot() default constructor.
-
-private:
-  // svg_2d_plot Member Functions.
-
-  void set_ids()  // TODO is this only used once in constructor and should be inline?
-  { // document ids for use in <g id = "PLOT_TITLE".../>
-    for(int i = 0; i < detail::SVG_PLOT_DOC_CHILDREN; ++i)
-    {
-      image.get_g_element(i).id(detail::document_ids[i]);
-    }
-  } //  void set_ids()
+        // Note that widths are stored in member data *and* copied here.
+        // Not sure if this is wise but ...
 
-  //void calculate_transform() now inline in calcualte_plot_window
-  //{ // Calculate scale and shift factors for transform from Cartesian to plot.
-  //  // SVG image is 0, 0 at top left, Cartesian at bottom left.
-  //  x_scale = (plot_x2 - plot_x1) / (x_max - x_min);
-  //  x_shift = plot_x1 - x_min *(plot_x2 - plot_x1) / (x_max - x_min);
-  //  y_scale = -(plot_y2-plot_y1) / (y_max-y_min);
-  //  y_shift = plot_y1 - (y_max * (plot_y1 - plot_y2) / (y_max - y_min));
-  //} //   void calculate_transform()
-
-  void transform_pair(std::pair<double, double>& pt)
-  { // Transform both x and y from Cartesian to SVG coordinates.
-    // SVG image is 0, 0 at top left, Cartesian at bottom left.
-    transform_point(pt.first, pt.second);
-  }
-
-  void calculate_plot_window()
-  { // The plot window is used to set a clip path:
-    // this ensures that data points and lines (and anything else)
-    // outside this window are NOT drawn.
-    // Start by assuming we can use all the svg image,
-    //  but reduce by width of any image border.
-    plot_x1 = 0 + image_border_width_; // left
-    plot_y1 = 0 + image_border_width_; // top
-    plot_x2 = image.x_size() - image_border_width_; // right
-    plot_y2 = image.y_size() - image_border_width_; // bottom
-
-    calculate_legend_box();
-    if(use_legend 
-      && (legend_x1_ == -1) ) // Legend box position NOT been set by legend_top_left.
-    { // Leave space for legend at right of plot window.
-      plot_x2 -= legend_width_;  // legend box width.
-    }
-    if(use_x_label)
-    { // Leave space at bottom for X axis label.
-      plot_y2 -= x_label_info.font_size() * (text_margin_);
-    }
-    if(use_y_label)
-    { // Leave space at left for Y axis label.
-      plot_x1 += y_label_info.font_size() * (text_margin_ - 0.5);
-    }
-    if(use_title)
-    { // Leave space at top for title.
-      // TODO what if want to put title at bottom?
-      plot_y1 += title_font_size() * (text_margin_ + 0.5);
-    }
-    if(use_plot_window_)
-    { // Reduce to allow for legend, axes ticks to be on or outside plot_window.
-      // Give the plot window a border (set with plot_border_width(double)).
-      // Needed to allow any plot window border rectangle to show OK.
-      // border_margin is to prevent it being right on the image border.
-      plot_x1 += plot_border_width() + border_margin(); // pixels.
-      plot_x2 -= plot_border_width() + border_margin();
-      plot_y1 += plot_border_width() + border_margin();
-      plot_y2 -= plot_border_width() + border_margin();
-    }
-    // Check if the axes will intersect.
-    y_axis_position_ = y_intersect;  // Y-axis will intersect X-axis.
-    if (x_min > std::numeric_limits<double>::min())
-    { // Y-axis > 0 so will not intersect X -axis, (all positive)
-      y_axis_position_ = left; // Y-axis free to left of end of X-axis.
-      use_y_ticks_on_plot_window_ = true;
-    }
-    else if (y_max < -std::numeric_limits<double>::min())
-    { // Y-axis < 0 so will not intersect X -axis, (all negative)
-      y_axis_position_ = right;
-      use_y_ticks_on_plot_window_ = true;
-    }
-    x_axis_position_ = x_intersect;  // X-axis will intersect Y-axis.
-    if (y_min > std::numeric_limits<double>::min()) // all definitely > zero.
-    { // y_min > 0 so X-axis will not intersect Y-axis, so use bottom plot window.
-      x_axis_position_ = bottom; // X-axis to bottom.
-      use_x_ticks_on_plot_window_ = true;
-    }
-    else if(y_max < -std::numeric_limits<double>::min())  // all definitely < zero.
-    { // // y_max < 0 so X-axis will not intersect Y-axis, so use top plot window.
-      x_axis_position_ = top; // X-axis to top.
-      use_x_ticks_on_plot_window_ = true;
-    }
+        // Ticks
+        if(use_up_ticks || use_down_ticks)
+        {
+          image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width(x_major_tick_width_).stroke_color(black);
+          image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width(x_minor_tick_width_).stroke_color(black);
+        }
+        if(use_left_ticks || use_right_ticks)
+        {
+          image.get_g_element(PLOT_Y_MAJOR_TICKS).style().stroke_width(y_major_tick_width_).stroke_color(black);
+          image.get_g_element(PLOT_Y_MINOR_TICKS).style().stroke_width(y_minor_tick_width_).stroke_color(black);
+        }
+        // Grids.
+        // Default color & width for grid, used or not.
+        image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width(x_major_grid_width_).stroke_color(svg_color(200, 220, 255));
+        BOOST_ASSERT(image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_color() == svg_color(200, 220, 255));
+        image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_width(x_minor_grid_width_).stroke_color(svg_color(200, 220, 255));
+        image.get_g_element(PLOT_Y_MAJOR_GRID).style().stroke_width(y_major_grid_width_).stroke_color(svg_color(200, 220, 255));
+        image.get_g_element(PLOT_Y_MINOR_GRID).style().stroke_width(y_minor_grid_width_).stroke_color(svg_color(200, 220, 255));
+        image.get_g_element(PLOT_DATA_LINES).style().stroke_width(2);
+
+        legend_place_ = (use_plot_window_) ? outside_right : inside; // Defaults.
+        // Note if set plot_window_on() then also need to set legend_place.
+        // (if set a default in plot_window then call to set legend place must to come *after* it.
+        // So not set a default?  But leaving it as inside is worse?)
+
+      } // svg_2d_plot() default constructor.
+
+    private:
+      // svg_2d_plot Member Functions.
+
+      void set_ids()  // TODO is this only used once in constructor and should be inline?
+      { // document ids for use in <g id = "PLOT_TITLE".../>
+        for(int i = 0; i < detail::SVG_PLOT_DOC_CHILDREN; ++i)
+        {
+          image.get_g_element(i).id(detail::document_ids[i]);
+        }
+      } //  void set_ids()
 
-    // Also need a >half font to allow the value label on any max major tick to avoid clipping.
-    // Even after reading http://www.w3.org/TR/SVG/fonts.html, unclear how to
-    // determine the width of digits, so an arbitrary average width height ratio wh is used:
-
-    // We would really like to know the length of the longest value label here!
-    // Might convert the max and then use its .length()?
-    int chars = (y_value_precision_ + 1 + 1); // sign & decimal point.
-    if((y_value_ioflags_ & std::ios::scientific) == std::ios::scientific)
-    { // precision is number of decimal places in the fractional part (default 6).
-      chars += 5; // Also need space for e, sign & 3 exponent digits = 5)
-    }
-    else if((y_value_ioflags_ & std::ios::fixed) == std::ios::fixed)
-    { // precision is 
-      chars += 2; // Need space for decimal point & at least 1 more digit)
-    }
-    else
-    { // Default neither fixed nor scientific, no leading or trailing zero(s).
-      // allowing sign and decimal point should probably be enough, 
-      // but only a check of the actual values will be accurate.  TODO?
-    }
-    y_label_length_ = 0; // SVG units.
-    if (y_label_rotation_ == horizontal)
-    { // Move edge right to give space for y_value_precision_ digits.
-      y_label_length_ += y_label_value.font_size() * (chars * wh_);
-    }
-    else if((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
-    { // Only need one char width from Y-axis label.
-      y_label_length_ += y_label_value.font_size() * 1.5;
-    }
-    else
-    { // Assume some slope 45, so diagonally down from tick,
-      // and takes a bit less room.
-      y_label_length_ = y_label_value.font_size() * chars * wh_ * sin45;
-    }
-    if (use_y_major_labels && (y_axis_position_ != right) )
-    {
-      //if (abs(x_min/(x_max - x_min)) < 0.05) // < 5% of range.
-      //  // Y-axis is too close to the axis label.
-      //  // Want to do this:
-      //  //((y_axis - plot_x1) < (y_label_length_ - y_major_tick_width_)) )
-      //  // needs to calculate transform to get into SVG units, but this is changing plot_x1 !!
-      //{ // force onto plot window. BUT this only looks right if plot window is on.
-      //  // because makr ticks and label are on the plot window
-      // use_y_ticks_on_plot_window_ = true;
-      //}
-      //if (use_y_ticks_on_plot_window_) // on plot window
-      {  // Move plot window right to make space for value labels,
-        plot_x1 += y_label_length_;
-      }
-    }
+      //void calculate_transform() now inline in calcualte_plot_window
+      //{ // Calculate scale and shift factors for transform from Cartesian to plot.
+      //  // SVG image is 0, 0 at top left, Cartesian at bottom left.
+      //  x_scale = (plot_x2 - plot_x1) / (x_max - x_min);
+      //  x_shift = plot_x1 - x_min *(plot_x2 - plot_x1) / (x_max - x_min);
+      //  y_scale = -(plot_y2-plot_y1) / (y_max-y_min);
+      //  y_shift = plot_y1 - (y_max * (plot_y1 - plot_y2) / (y_max - y_min));
+      //} //   void calculate_transform()
+
+      void transform_pair(std::pair<double, double>& pt)
+      { // Transform both x and y from Cartesian to SVG coordinates.
+        // SVG image is 0, 0 at top left, Cartesian at bottom left.
+        transform_point(pt.first, pt.second);
+      }
+      void calculate_plot_window()
+      { // The plot window is used to set a clip path:
+        // this ensures that data points and lines (and anything else)
+        // outside this window are NOT drawn.
+        // Start by assuming we can use all the svg image,
+        //  but reduce by width of any image border.
+        plot_x1 = 0 + image_border_width_; // left
+        plot_y1 = 0 + image_border_width_; // top
+        plot_x2 = image.x_size() - image_border_width_; // right
+        plot_y2 = image.y_size() - image_border_width_; // bottom
+
+        if(use_title)
+        { // Leave space at top for title.
+          // TODO what if want to put title at bottom?
+          plot_y1 += title_font_size() * (text_margin_ + 0.5);
+        }
+
+        size_legend_box();
+        place_legend_box();
+       if(use_x_label)
+        { // Leave space at bottom for X axis label.
+          plot_y2 -= x_label_info.font_size() * (text_margin_);
+        }
+        if(use_y_label)
+        { // Leave space at left for Y axis label.
+          plot_x1 += y_label_info.font_size() * (text_margin_ - 0.5);
+        }
+        if(use_plot_window_)
+        { // Reduce to allow for legend, axes ticks to be on or outside plot_window.
+          // Give the plot window a border (set with plot_border_width(double)).
+          // Needed to allow any plot window border rectangle to show OK.
+          // border_margin is to prevent it being right on the image border.
+          plot_x1 += plot_border_width() + border_margin(); // pixels.
+          plot_x2 -= plot_border_width() + border_margin();
+          plot_y1 += plot_border_width() + border_margin();
+          plot_y2 -= plot_border_width() + border_margin();
+        }
+        // Check if the axes will intersect.
+        y_axis_position_ = y_intersect;  // Y-axis will intersect X-axis.
+        if (x_min > std::numeric_limits<double>::min())
+        { // Y-axis > 0 so will not intersect X -axis, (all positive)
+          y_axis_position_ = left; // Y-axis free to left of end of X-axis.
+          use_y_ticks_on_plot_window_ = true;
+        }
+        else if (y_max < -std::numeric_limits<double>::min())
+        { // Y-axis < 0 so will not intersect X -axis, (all negative)
+          y_axis_position_ = right;
+          use_y_ticks_on_plot_window_ = true;
+        }
+        x_axis_position_ = x_intersect;  // X-axis will intersect Y-axis.
+        if (y_min > std::numeric_limits<double>::min()) // all definitely > zero.
+        { // y_min > 0 so X-axis will not intersect Y-axis, so use bottom plot window.
+          x_axis_position_ = bottom; // X-axis to bottom.
+          use_x_ticks_on_plot_window_ = true;
+        }
+        else if(y_max < -std::numeric_limits<double>::min())  // all definitely < zero.
+        { // // y_max < 0 so X-axis will not intersect Y-axis, so use top plot window.
+          x_axis_position_ = top; // X-axis to top.
+          use_x_ticks_on_plot_window_ = true;
+        }
+
+        // Also need a >half font to allow the value label on any max major tick to avoid clipping.
+        // Even after reading http://www.w3.org/TR/SVG/fonts.html, unclear how to
+        // determine the width of digits, so an arbitrary average width height ratio wh is used:
+
+        // We would really like to know the length of the longest value label here!
+        // Might convert the max and then use its .length()?
+        int chars = (y_value_precision_ + 1 + 1); // sign & decimal point.
+        if((y_value_ioflags_ & std::ios::scientific) == std::ios::scientific)
+        { // precision is number of decimal places in the fractional part (default 6).
+          chars += 5; // Also need space for e, sign & 3 exponent digits = 5)
+        }
+        else if((y_value_ioflags_ & std::ios::fixed) == std::ios::fixed)
+        { // precision is 
+          chars += 2; // Need space for decimal point & at least 1 more digit)
+        }
+        else
+        { // Default neither fixed nor scientific, no leading or trailing zero(s).
+          // allowing sign and decimal point should probably be enough, 
+          // but only a check of the actual values will be accurate.  TODO?
+        }
+        y_label_length_ = 0; // SVG units.
+        if (y_label_rotation_ == horizontal)
+        { // Move edge right to give space for y_value_precision_ digits.
+          y_label_length_ += y_label_value.font_size() * (chars * wh_);
+        }
+        else if((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
+        { // Only need one char width from Y-axis label.
+          y_label_length_ += y_label_value.font_size() * 1.5;
+        }
+        else
+        { // Assume some slope 45, so diagonally down from tick,
+          // and takes a bit less room.
+          y_label_length_ = y_label_value.font_size() * chars * wh_ * sin45;
+        }
+        if (use_y_major_labels && (y_axis_position_ != right) )
+        {
+          //if (abs(x_min/(x_max - x_min)) < 0.05) // < 5% of range.
+          //  // Y-axis is too close to the axis label.
+          //  // Want to do this:
+          //  //((y_axis - plot_x1) < (y_label_length_ - y_major_tick_width_)) )
+          //  // needs to calculate transform to get into SVG units, but this is changing plot_x1 !!
+          //{ // force onto plot window. BUT this only looks right if plot window is on.
+          //  // because makr ticks and label are on the plot window
+          // use_y_ticks_on_plot_window_ = true;
+          //}
+          //if (use_y_ticks_on_plot_window_) // on plot window
+          {  // Move plot window right to make space for value labels,
+            plot_x1 += y_label_length_;
+          }
+        }
+
+        if (use_x_major_labels && (use_x_ticks_on_plot_window_ || (x_axis_position_ != top) ))
+        { // Move bottom of plot window up to give space for x value labels.
+          // x_value_precision_ digits etc.
+          double l = x_value_precision_ + 1 + 1; // sign & decimal point.
+          if(x_label_rotation_ == horizontal)
+          { // Only 1 char height & 1 space needed if horizontal.
+            l = 2;
+          } 
+          else 
+          { // will need more than 2
+            //l += 1; // extra space at top and bottom?
+            if ((x_value_ioflags_ & std::ios::scientific) == std::ios::scientific)
+            { // space for "e+000"
+              l += 5;
+            }
+            else if((x_value_ioflags_ & std::ios::fixed) == std::ios::fixed)
+            { // Need space for decimal point & sign & at least 1 more digit)
+              l += 3;
+            }
+            if ((x_label_rotation_ == upward) || (x_label_rotation_ == downward))
+            { // Need space for longest.
+            }
+            else
+            { // Assume some slope, say 45, so * sin(45) = 0.707.
+              l *= sin45;
+            }
+          }
+          plot_y2 -= x_label_value.font_size() * l * wh_; // Move up.
+        }
+        if(use_left_ticks)
+        { // Start left of plot to right to give space for biggest of any external left ticks.
+          plot_x1 += (std::max)(y_major_tick_length_, y_minor_tick_length_);  // Avoid macro max trap!
+        }
+        if(use_down_ticks)
+        { // Start bottom of plot higher to give space for any external down ticks.
+          plot_y2 -= (std::max)(x_major_tick_length_, x_minor_tick_length_);
+        }
+
+
+        if (use_x_axis_lines_) 
+        { // Want a X-axis line, so check if range include zero, so axes intersect,
+          // and x_axis is svg coordinate of Y-axis (usually y = 0).
+          // If not fix axis to bottom of the plot window
+          // and leave space (and quiggle between) to show this.
+          if (x_axis_position_ == bottom) // All definitely > zero.
+          { // y_min > 0 so X-axis will not intersect Y-axis, so use plot window.
+            x_axis = plot_y2; // X-axis to bottom,
+            //plot_y2 -= 2 * y_label_info.font_size(); // with a space.
+          }
+          else if(x_axis_position_ == top)  // definitely < zero.
+          { // // y_max < 0 so X-axis will not intersect Y-axis, so use plot window.
+            x_axis = plot_y1; // X-axis to top, 
+            //plot_y1 += 2 * y_label_info.font_size(); // with a space.
+          }
+          else
+          { // y_axis_position_ == y_intersect
+            // Calculate below after transform is calculated.
+          }
+        } // if (use_x_axis_) 
+
+        if (use_y_axis_lines_) 
+        { // Want a Y-axis line, so check if range include zero, so axes intersect,
+          // and y_axis is svg coordinate of X-axis (usually x = 0).
+          // If not fix axis to left of the plot window
+          // and leave space (and quiggle between) to show this.
+          if (y_axis_position_ == left) // all definitely > zero.
+          { // Y-axis will not intersect X -axis, so put Y-axis line to left of plot window.
+            y_axis = plot_x1; // Y-axis to left,
+            //plot_x1 += 2 * y_label_info.font_size(); // with a space.
+          }
+          else if(y_axis_position_ == right) 
+          { 
+            y_axis = plot_x2; // Y-axis to right of plot window,
+            //plot_x2 -= 2 * y_label_info.font_size(); // with a space.
+          }
+          else
+          { // x_axis_position_ == x_intersect
+            // Calculate below after transform is calculated.
+          }
+        } // if (use_y_axis_) 
+
+
+        // Calculate scale and shift factors for transform from Cartesian to plot.
+        // SVG image is 0, 0 at top left,y increase *downwards*
+        // Cartesian 0, 0 at bottom left, y increasing upwards.
+        x_scale = (plot_x2 - plot_x1) / (x_max - x_min);
+        x_shift = plot_x1 - x_min *(plot_x2 - plot_x1) / (x_max - x_min);
+        y_scale = -(plot_y2-plot_y1) / (y_max-y_min);
+        y_shift = plot_y1 - (y_max * (plot_y1 - plot_y2) / (y_max - y_min));
+
+        if (use_x_axis_lines_)
+        {
+          if(x_axis_position_ == x_intersect)
+          { // Y Range *does* include zero, so x_axis not yet calculated.
+            double y(0.); // Use y = 0
+            transform_y(y);
+            x_axis = y; // svg Y coordinate of horizontal X-axis line.
+          }
+        }
+        if (use_y_axis_lines_)
+        { // May need to calculate axes, if will intersect.
+          if(y_axis_position_ == y_intersect)
+          { // X Range *does* include zero, so y_axis not yet calculated.
+            double x(0.);
+            transform_x(x);
+            y_axis = x; // SVG x coordinate of vertical Y-axis.
+          }
+        }
+        if (use_plot_window_)
+        { // Draw plot window rectangle with background and/or border.
+          image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).push_back(
+            new rect_element(plot_x1, plot_y1, (plot_x2 - plot_x1), plot_y2 - plot_y1));
+        }
+
+      } // calculate_plot_window
+
+      void draw_y_axis()
+      {
+        double x;
+        x = y_axis; // Y-axis (x = 0) transformed into X SVG coordinates.
+        // Perhaps shifted to left or right if origin is missing.
+
+        if(use_y_axis_lines_)
+        { // Draw the vertical Y-axis line (at cartesian x = 0).
+          double ybottom = plot_y2;
+          if (use_down_ticks && use_y_ticks_on_plot_window_ && (x_axis_position_ == x_intersect) )
+          { // Extend the vertical line down in lieu of a tick.
+            ybottom += (std::max)(x_minor_tick_length_, x_major_tick_length_);
+          }
+          image.get_g_element(detail::PLOT_Y_AXIS).line(x, plot_y1, x, ybottom);
+          // <g id="yAxis" stroke="rgb(0,0,0)"><line x1="70.5" y1="53" x2="70.5" y2="357"/>
+        }
+        // Access the paths for the ticks & grids, ready for additions.
+        path_element& minor_tick_path = image.get_g_element(detail::PLOT_Y_MINOR_TICKS).path();
+        path_element& major_tick_path = image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).path();
+        path_element& minor_grid_path = image.get_g_element(detail::PLOT_Y_MINOR_GRID).path();
+        path_element& major_grid_path = image.get_g_element(detail::PLOT_Y_MAJOR_GRID).path();
+
+        if(use_y_ticks_on_plot_window_)
+        { // TODO ensure that labels allow space. - they don't at present.
+          // Was y_external style - so both labels and ticks are OUTSIDE the plot window.
+          // 
+        }
+
+        // y_minor_jump is the interval between minor ticks.
+        double y_minor_jump = y_major_interval_ / ((double)(y_num_minor_ticks_ + 1.) );
+        // TODO Problem here with using floating point?
+        // Was i < y_max; but didn't show the tick and value at y_max so now i <= y_max;
+        // But may still fail if a ls or few bits out? Seems to fail for y = 100, for example.
+
+        // Draw the ticks on the positive side.
+        for(double y = 0; y <= y_max; y += y_major_interval_)
+        {
+          for(double j = y + y_minor_jump;
+            j < (y + y_major_interval_) * (1. - 2 * std::numeric_limits<double>::epsilon());
+            j += y_minor_jump)
+          { // Draw minor ticks.
+            // This will output 'orphaned' minor ticks that are beyond the plot window,
+            // if the last major tick does not coincide with the plot window.
+            // These are just ignored in draw_x_minor_ticks.
+            // There might be 9 of them,
+            // if you have the common 9 minor tick between major ticks!
+            // TODO this seems ugly - as does the negative ones below.
+            if (j != 0. || ! use_x_axis_lines_)
+            { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
+              // (won't be X-axis line for 1-D where the zero tick is always wanted).
+              draw_y_minor_ticks(j, minor_tick_path, minor_grid_path);
+            }
+          }
+          if ((y != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
+          { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
+            // (won't be X-axis line for 1-D where the zero tick is always wanted).
+            draw_y_major_ticks(y, major_tick_path, major_grid_path);
+          }
+        }
+
+        // Draw the ticks on the negative side.
+        for(double y = 0; y >= y_min; y -= y_major_interval_)
+        {
+          for(double j=y; j > y-y_major_interval_; j-= y_major_interval_ / (y_num_minor_ticks_ + 1))
+          { // Draw minor ticks.
+            if ((j != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
+            { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
+              // (won't be X-axis line for 1-D where the zero tick is always wanted).
+              draw_y_minor_ticks(j, minor_tick_path, minor_grid_path);
+            }
+          }
+          if ((y != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
+          { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
+            // (won't be X-axis line for 1-D where the zero tick is always wanted).
+            draw_y_major_ticks(y, major_tick_path, major_grid_path);
+          }
+        }
+      } // draw_y_axis
+
+      void draw_y_label()
+      {
+        // image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_color(black);
+        // Now set in constructor, and can be changed with member function .
+
+        std::string label = y_label_info.text(); // x_axis label, and optional units.
+        if (use_x_label_units && (y_units_info.text() != ""))
+        { // Append the units, if any, providing brackets ().
+          // TODO Is this the best policy - or should the user provide the ()s????
+          label += "  (" + y_units_info.text() + ")";
+        }
 
-    if (use_x_major_labels && (use_x_ticks_on_plot_window_ || (x_axis_position_ != top) ))
-    { // Move bottom of plot window up to give space for x value labels.
-      // x_value_precision_ digits etc.
-      double l = x_value_precision_ + 1 + 1; // sign & decimal point.
-      if(x_label_rotation_ == horizontal)
-      { // Only 1 char height & 1 space needed if horizontal.
-        l = 2;
-      } 
-      else 
-      { // will need more than 2
-        //l += 1; // extra space at top and bottom?
-        if ((x_value_ioflags_ & std::ios::scientific) == std::ios::scientific)
-        { // space for "e+000"
-          l += 5;
-        }
-        else if((x_value_ioflags_ & std::ios::fixed) == std::ios::fixed)
-        { // Need space for decimal point & sign & at least 1 more digit)
-          l += 3;
+        image.get_g_element(detail::PLOT_Y_LABEL).push_back(new
+          text_element(y_label_info.font_size() * 1.5,
+          // shift over one char height to right from left edge of image.
+          (plot_y2 + plot_y1) / 2., // center on the plot window.
+          label, // "Y-Axis" for example.
+          y_label_info.font_size(),
+          y_label_info.font_family(),
+          "", "", "", "",
+          center_align, // One might want it to left or right_align?
+          upward)); // Y label must be drawn vertically.
+      } // draw_y_label
+
+      void draw_y_major_ticks(double value, path_element& tick_path, path_element& grid_path)
+      { // Draw Y axis major ticks, tick value labels & grids.
+        double y1(value);
+        transform_y(y1); // cartesian to SVG coordinates.
+        double x1(0.); // left end of tick.
+        double x2(image.y_size()); // right end of tick.
+        if(use_y_major_grid_)
+        { // Draw horizontal major grid line.
+          if(!use_plot_window_)
+          { // TODO is this right?
+            //if (use_title())
+            //{ // title has no effect if at the top.
+            //  y1 += title_info.font_size() * text_margin_;
+            //}
+            if(use_y_label)
+            { // Start further right to give space for y axis value label.
+              y1 -= y_label_value.font_size() * text_margin_ ;
+            }
+
+            if(use_left_ticks)
+            { // And similarly for left ticks.
+              y1 -= y_major_tick_length_;
+            }
+          }
+          else
+          { // Do use_plot_window.
+            x1 = plot_x1 + 1;
+            x2 = plot_x2 - 1;
+          }
+          grid_path.M(x1, y1).L(x2, y1);
+        } // use_y_major_grid_
+
+        if((y1 <= plot_y2) && (y1 >= plot_y1))
+        { // Make sure that we are drawing inside the allowed window.
+          double y_tick_length = y_major_tick_length_;
+          if(use_y_ticks_on_plot_window_) // (was external_style)
+          { // Start ticks on the plot window border.
+            x1 = plot_x1; // x1 = left,
+            x2 = plot_x1; //  x2 = right.
+          }
+          else
+          { // Internal style ticks on vertical Y-axis.
+            x1 = y_axis; // Y-axis line.
+            x2 = y_axis;
+          }
+          if(use_left_ticks)
+          {
+            x1 -= y_tick_length; // left
+          }
+          if (use_right_ticks)
+          {
+            x2 += y_tick_length; // right.
+          }
+          tick_path.M(x1, y1).L(x2, y1); // Draw the major tick.
+          // leaving x1 at the left most end of any tick.
         }
-        if ((x_label_rotation_ == upward) || (x_label_rotation_ == downward))
-        { // Need space for longest.
+
+        if(use_y_major_labels)
+        { // Label the tick with value, for example "1.2"
+          std::stringstream label;
+          label.precision(y_value_precision_);
+          label.flags(y_value_ioflags_); // set ALL IOflags.
+          label << value; // Example: label.str() == "20" or "0.25" or "1.2e+015"
+          if(use_left_ticks)
+          {
+            if (y_minor_tick_length_ > y_minor_tick_length_)
+            { // In case some joker has made the minor ticks longer than the major,
+              // we might need to move left more for the longer tick.
+              x1 -= (y_minor_tick_length_ - y_minor_tick_length_);
+            }
+            x1 -= y_label_value.font_size(); // move left by a font width.
+          }
+          else
+          { // No need to move if right tick, or none.
+          }
+          // Need to work out how much space value labels will need.
+          double y = y1;
+          align_style alignment = center_align;
+          if(use_y_ticks_on_plot_window_)
+          { // External to plot window style.
+            if(y_label_rotation_ == horizontal)
+            {  // Just shift down half a digit to center value digits on tick.
+              alignment = right_align;
+              y += y_label_value.font_size() / 2;
+            }
+            else if ((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
+            {// Tick value label straight up or down vertically on y axis.
+              // No shift y down to center.
+              alignment = center_align;
+            }
+            else
+            { // Assume some 45 slope, so need about sqrt(2) less space?
+              x1 += y_label_value.font_size() * 0.5; // move left by half a font width.
+              // no y shift needed.
+              alignment = right_align;
+            }
+            // Always want all values including "0", if labeling external to plot window.
+            // use_ticks_on_plot_window_ == true
+            image.get_g_element(detail::PLOT_VALUE_LABELS).text(
+              x1,
+              y,
+              label.str(), y_label_value.font_size(), "", "", "", "", "", alignment, y_label_rotation_);
+          }
+          else
+          { // ! use_y_ticks_on_plot_window_ == Internal - value labels close to left of vertical Y-axis.
+            if ((value != 0) && use_x_axis_lines_)
+            { // Avoid a zero ON the Y-axis if it would be cut through by any horizontal X-axis line.
+              y += y_label_value.font_size() / 2;
+              image.get_g_element(detail::PLOT_VALUE_LABELS).text(
+                x1 ,
+                y, // Just shift down half a digit to center value digits on tick.
+                label.str(), y_label_value.font_size(), y_label_value.font_family(), "", "", "", "",
+                alignment, // on the tick ???
+                y_label_rotation_);
+            }
+          }
+        } // if(use_y_major_labels)
+      } // draw_y_major_ticks
+
+      void draw_y_minor_ticks(double value, path_element& tick_path, path_element& grid_path)
+      {
+        double x1(0.);
+        double y1(value); // for tick position and value label.
+        transform_y(y1);
+        double x2(image.y_size()); // right edge of image.
+
+        if(use_y_minor_grid_)
+        { // Draw the minor grid, if wanted.
+          if(!use_plot_window_)
+          { // Use whole image, but make space for title & labels text.
+            //if(use_title)
+            //{ // If title at top, should make no difference, unlike X grid.
+            //  x2 -= title_info.font_size() * text_margin_;
+            //}
+            if(use_y_label)
+            {
+              x1 += y_label_info.font_size() * text_margin_;
+              x2 -= y_label_info.font_size() * text_margin_;
+            }
+          }
+          else
+          { // Use plot window.
+            x1 = plot_x1 + 1; // TODO what is the +1 for?
+            x2 = plot_x2 - 1; // Ensure *inside* window?
+          }
+          if((y1 >= plot_y1) && (x1 >= plot_x1) && (x2 <= plot_x2) )
+          { // // Make sure that we are drawing inside the allowed window.
+            grid_path.M(x1, y1).L(x2, y1);
+          }
+          // TODO else just ignore outside plot window?
+        }
+
+        if(use_y_ticks_on_plot_window_)
+        { // Put y minor ticks on the plot window border. External style.
+          x1 = plot_x1; // On the plot window border.
+          x2 = plot_x1;
         }
         else
-        { // Assume some slope, say 45, so * sin(45) = 0.707.
-          l *= sin45;
+        { // Internal style.
+          x1 = y_axis; // On the Y-axis line.
+          x2 = y_axis;
+        }
+        if(use_left_ticks)
+        {
+          x1 -= y_minor_tick_length_;
+        }
+        if(use_right_ticks)
+        {
+          x2 += y_minor_tick_length_;
+        }
+        //if((x1 >= plot_x1) && (x2 <= plot_x2) && (y1 <= plot_y2) && (y1 >= plot_y1))
+        // but can never be inside if left tick!
+        if((y1 <= plot_y2) && (y1 >= plot_y1))
+        { // Make sure that we are drawing inside of the allowed plot window.
+          tick_path.M(x1, y1).L(x2, y1); // Draw the tick.
         }
+        else
+        {// Do nothing?  warn?
+          // std::cout << "y minor tick OUTside " << x1 << ' ' << y1 << ' ' << x2 << std::endl;
+
+        }
+      } // void draw_y_minor_ticks
+
+      void draw_straight_lines(const svg_2d_plot_series& series)
+      { // Straight line between data points (rather than a Bezier curve).
+        double prev_x; // Previous data points.
+        double prev_y;
+        double temp_x(0.);
+        double temp_y;
+
+        g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_LINES).add_g_element();
+        g_ptr.clip_id(plot_window_clip);
+        g_ptr.style().stroke_color(series.line_style.color);
+        g_ptr.style().fill_color(series.line_style.area_fill);
+        path_element& path = g_ptr.path();
+        path.style().fill_color(series.line_style.area_fill);
+
+        bool is_fill = !series.line_style.area_fill.blank;
+        path.fill = is_fill; // Ensure includes a fill="none".
+
+        if(series.series.size() > 1)
+        {
+          std::multimap<double, double>::const_iterator j = series.series.begin();
+
+          // If we have to fill the area under the plot,
+          // we first have to move from the X-axis (y = 0) to the first point,
+          // and again at the end after the last point.
+          prev_x = (*j).first;
+          prev_y = 0.;
+          transform_point(prev_x, prev_y);
+          if(is_fill)
+          { // Move to 1st point.
+            path.style().fill_color(series.line_style.area_fill);
+            path.M(prev_x, prev_y);
+          }
+          transform_y(prev_y = (*j).second);
+          if(is_fill)
+          { // fill wanted.
+            path.style().fill_color(series.line_style.area_fill); // TOD why again?
+            path.L(prev_x, prev_y); // Line from X-axis to 1st point.
+          }
+          else
+          { // fill == blank
+            path.M(prev_x, prev_y);
+          }
+          ++j; // so now refers to 2nd point to plot.
+
+          for(; j != series.series.end(); ++j)
+          {
+            temp_x = (*j).first;
+            temp_y = (*j).second;
+            transform_point(temp_x, temp_y);
+            path.L(temp_x, temp_y); // line to next point.
+
+            if(is_fill)
+            {
+              path.M(temp_x, temp_y);
+            }
+            prev_x = temp_x;
+            prev_y = temp_y;
+          } // for j
+
+          if(is_fill)
+          { // fill wanted.
+            transform_y(temp_y = 0.); // X-axis line.
+            path.L(temp_x, temp_y).z(); // closepath with Z to terminate line.
+          }
+        }
+      } // draw_straight_lines
+
+      void draw_bezier_lines(const svg_2d_plot_series& series)
+      {
+        g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_LINES).add_g_element();
+        g_ptr.clip_id(plot_window_clip);
+        g_ptr.style().stroke_color(series.line_style.color);
+        path_element& path = g_ptr.path();
+
+        std::pair<double, double> n; // current point.
+        std::pair<double, double> n_minus_1; // penultimate.
+        std::pair<double, double> n_minus_2;
+        std::pair<double, double> fwd_vtr;
+        std::pair<double, double> back_vtr;
+
+        bool is_fill = !series.line_style.area_fill.blank;
+        if(is_fill == false)
+        {
+          path.fill = false; // default path constructor is true - TODO why??
+        }
+        else
+        { // fill
+          path.style().fill_color(series.line_style.area_fill);
+        }
+
+        if(series.series.size() > 2)
+        { // Need >= 3 for a cubic curve (start point, 2 control points, and end point).
+          std::multimap<double, double>::const_iterator iter = series.series.begin();
+          n_minus_1 = *(iter++);  // begin() 
+          transform_pair(n_minus_1);
+          n = *(iter++); // middle
+          transform_pair(n);
+          path.M(n_minus_1.first, n_minus_1.second); // move m_minus_1, the 1st data point.
+
+          double control = 0.1;  
+          //0.2 is a scaling factor that Jake used to define the magnitude of the
+          //vector of the current control point to be placed. I was basically
+          //taking advantage of the auto-drawing of Bezier curves that exists in
+          //the SVG format, and this is my attempt to give the control point the
+          //proper length.
+
+          // Experiment suggests that 0.2 gives distorsions with exp curves.
+          // 0.05 is just visually OK with 50 points, but 100 are better.
+
+          for(; iter != series.series.end(); ++iter)
+          {
+            n_minus_2 = n_minus_1; 
+            n_minus_1 = n;
+            n = *iter;
+            transform_pair(n);
+
+            back_vtr.first = ((n_minus_1.first - n.first) + // (x diff - x previous diff) * control
+              (n_minus_2.first - n_minus_1.first)) * control; 
+            back_vtr.second = ((n_minus_1.second - n.second) + // y
+              (n_minus_2.second - n_minus_1.second)) * control;
+
+            // 8.3.6 The cubic Bézier curve commands path.S(x, y).
+            // Start point, end point, & two control points.
+            // Example: S378.5,519.3 381,519.3 ...
+            // S end_control_point, end point
+            // Start is reflection of last point's control point.
+            path.S(n_minus_1.first + back_vtr.first, // x
+              n_minus_1.second + back_vtr.second, // y - end control point
+              n_minus_1.first, n_minus_1.second); // x, y - end point.
+          } // for
+          // Last point.
+          back_vtr.first = 0.; 
+          back_vtr.second = (n.second - n_minus_1.second) * control;
+          path.S(n.first + back_vtr.first, // x
+            n.second + back_vtr.second, // y
+            n.first, n.second); // x, y
+        }
+        else
+        { // Only one or two points, so no curving possible!
+          draw_straight_lines(series);
+        }
+      } // draw_bezier_lines
+
+      void draw_plot_lines()
+      { // Draw line through data series, Bezier curved or straight.
+        for(unsigned int i = 0; i < series.size(); ++i)
+        {
+          if(series[i].line_style.bezier_on)
+          { // curved.
+            draw_bezier_lines(series[i]);
+          }
+          else
+          {
+            draw_straight_lines(series[i]);
+          }
+        }
+      } // draw_plot_lines
+
+      void update_image()
+      {
+        clear_all();
+        // svg paint rules are that later 'painting' writes over previous
+        // painting, so the order of drawing is important.
+
+        // Draw image background (perhaps with border and/or fill color).
+        image.get_g_element(detail::PLOT_BACKGROUND).push_back(
+          new rect_element(0, 0, image.x_size(),  image.y_size()));
+
+        calculate_plot_window();
+        draw_title(); // Moved to ensure plot_X and Y are valid.
+
+        // Define the clip path for the plot window.
+        // We don't want to allow overlap of the plot window border lines,
+        // thus the minor adjustments.
+        // TODO should this be border thickness?
+
+        image.clip_path(rect_element(plot_x1 + 1, plot_y1 + 1,
+          plot_x2 - plot_x1 - 2, plot_y2 - plot_y1 - 2),
+          plot_window_clip);
+        // <clipPath id="plot_window"><rect x="35" y="38" width="309" height="322"/></clipPath>
+
+        image.get_g_element(detail::PLOT_DATA_POINTS).clip_id(plot_window_clip);
+
+        // Draw axes, labels & legend, as required.
+        if(use_axis)
+        {
+          draw_x_axis(); // Must do X-axis first.
+          draw_y_axis(); // TODO is draw_axes used?
+        }
+        if(use_legend)
+        {
+          draw_legend();
+        }
+        if(use_x_label)
+        {
+          draw_x_label();
+        }
+        if(use_y_label)
+        {
+          draw_y_label();
+        }
+
+        draw_plot_lines(); // Draw lines between points.
+
+        // Draw normal 'good' non-limit points.
+        double x(0.);
+        double y(0.);
+        for(unsigned int i = 0; i < series.size(); ++i)
+        {
+          g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_POINTS).add_g_element();
+
+          g_ptr.style()
+            .fill_color(series[i].point_style.fill_color_)
+            .stroke_color(series[i].point_style.stroke_color_);
+
+          for(std::multimap<double, double>::const_iterator j = series[i].series.begin();
+            j != series[i].series.end(); ++j)
+          {
+            x = j->first;
+            y = j->second;
+            transform_point(x, y);
+            if((x > plot_x1)  && (x < plot_x2) && (y > plot_y1)  && (y < plot_y2))
+            { // Onside plot window, so draw a point.
+              draw_plot_point(x, y, g_ptr, series[i].point_style);
+            }
+          } // for
+        } // for normal points
+
+        // Draw all the 'bad' at_limit points.
+        for(unsigned int i = 0; i < series.size(); ++i)
+        {
+          g_element& g_ptr = image.get_g_element(detail::PLOT_LIMIT_POINTS);
+
+          for(std::multimap<double,double>::const_iterator j = series[i].series_limits.begin();
+            j!=series[i].series_limits.end(); ++j)
+          {
+            x = j->first;
+            y = j->second;
+            transform_point(x, y);
+            draw_plot_point(x, y, g_ptr, plot_point_style(blank, blank, series[i].point_style.size_, cone));
+            // TODO why are fill and stroke blank? How is point style for 'bad' values determined?
+          }
+        } // limits point
+      } // void update_image()
+
+
+    public: // Member functions
+      // -----------------------------------------------------------------
+      // write() has two flavors, a file and a ostream.
+      // The file version opens an ostream, and calls the stream version.
+      // The stream version first clears all unnecessary data from the graph,
+      // builds the document tree, and then calls the write function for the root
+      // document node, which calls all other nodes through the Visitor pattern.
+      // -----------------------------------------------------------------
+
+      svg_2d_plot& write(const std::string& filename)
+      { // Write the plot image to a named file.
+        std::ofstream fout(filename.c_str());
+        if(fout.fail())
+        {
+          throw std::runtime_error("Unable to open " + filename);
+        }
+        write(fout); // Using the ostream version.
+        return *this;
       }
-      plot_y2 -= x_label_value.font_size() * l * wh_; // Move up.
-    }
-    if(use_left_ticks)
-    { // Start left of plot to right to give space for biggest of any external left ticks.
-      plot_x1 += (std::max)(y_major_tick_length_, y_minor_tick_length_);  // Avoid macro max trap!
-    }
-    if(use_down_ticks)
-    { // Start bottom of plot higher to give space for any external down ticks.
-      plot_y2 -= (std::max)(x_major_tick_length_, x_minor_tick_length_);
-    }
 
+      svg_2d_plot& write(std::ostream& s_out)
+      { // Write the image to an ostream.
+        update_image();
+        image.write(s_out); // Use the ostream version of write.
+        return *this;
+      }
 
-   if (use_x_axis_lines_) 
-    { // Want a X-axis line, so check if range include zero, so axes intersect,
-      // and x_axis is svg coordinate of Y-axis (usually y = 0).
-      // If not fix axis to bottom of the plot window
-      // and leave space (and quiggle between) to show this.
-      if (x_axis_position_ == bottom) // All definitely > zero.
-      { // y_min > 0 so X-axis will not intersect Y-axis, so use plot window.
-        x_axis = plot_y2; // X-axis to bottom,
-        //plot_y2 -= 2 * y_label_info.font_size(); // with a space.
-      }
-      else if(x_axis_position_ == top)  // definitely < zero.
-      { // // y_max < 0 so X-axis will not intersect Y-axis, so use plot window.
-        x_axis = plot_y1; // X-axis to top, 
-        //plot_y1 += 2 * y_label_info.font_size(); // with a space.
-      }
-      else
-      { // y_axis_position_ == y_intersect
-        // Calculate below after transform is calculated.
-      }
-    } // if (use_x_axis_) 
-
-    if (use_y_axis_lines_) 
-    { // Want a Y-axis line, so check if range include zero, so axes intersect,
-      // and y_axis is svg coordinate of X-axis (usually x = 0).
-      // If not fix axis to left of the plot window
-      // and leave space (and quiggle between) to show this.
-      if (y_axis_position_ == left) // all definitely > zero.
-      { // Y-axis will not intersect X -axis, so put Y-axis line to left of plot window.
-        y_axis = plot_x1; // Y-axis to left,
-        //plot_x1 += 2 * y_label_info.font_size(); // with a space.
-      }
-      else if(y_axis_position_ == right) 
-      { 
-        y_axis = plot_x2; // Y-axis to right of plot window,
-        //plot_x2 -= 2 * y_label_info.font_size(); // with a space.
-      }
-      else
-      { // x_axis_position_ == x_intersect
-        // Calculate below after transform is calculated.
-      }
-    } // if (use_y_axis_) 
-
-
-    // Calculate scale and shift factors for transform from Cartesian to plot.
-    // SVG image is 0, 0 at top left,y increase *downwards*
-    // Cartesian 0, 0 at bottom left, y increasing upwards.
-    x_scale = (plot_x2 - plot_x1) / (x_max - x_min);
-    x_shift = plot_x1 - x_min *(plot_x2 - plot_x1) / (x_max - x_min);
-    y_scale = -(plot_y2-plot_y1) / (y_max-y_min);
-    y_shift = plot_y1 - (y_max * (plot_y1 - plot_y2) / (y_max - y_min));
+      // Member functions to set plot options.
+      // All return *this to permit chaining.
 
-    if (use_x_axis_lines_)
-    {
-      if(x_axis_position_ == x_intersect)
-      { // Y Range *does* include zero, so x_axis not yet calculated.
-        double y(0.); // Use y = 0
-        transform_y(y);
-        x_axis = y; // svg Y coordinate of horizontal X-axis line.
+      // These below only refer to 2D plot.
+      // See axis_plot_label.hpp for all the many 1D functions X-Axis.
+
+      svg_2d_plot& y_label_on(bool cmd)
+      { // Y axis name or label.
+        use_y_label = cmd;
+        return *this;
       }
-    }
-    if (use_y_axis_lines_)
-    { // May need to calculate axes, if will intersect.
-      if(y_axis_position_ == y_intersect)
-      { // X Range *does* include zero, so y_axis not yet calculated.
-        double x(0.);
-        transform_x(x);
-        y_axis = x; // SVG x coordinate of vertical Y-axis.
+
+      bool y_label_on()
+      {
+        return use_y_label;
       }
-    }
-    if (use_plot_window_)
-    { // Draw plot window rectangle with background and/or border.
-      image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).push_back(
-        new rect_element(plot_x1, plot_y1, (plot_x2 - plot_x1), plot_y2 - plot_y1));
-    }
 
-    } // calculate_plot_window
+      svg_2d_plot& x_label_on(bool cmd)
+      {
+        use_x_label = cmd;
+        return *this;
+      }
 
-  void draw_y_axis()
-  {
-    double x;
-    x = y_axis; // Y-axis (x = 0) transformed into X SVG coordinates.
-    // Perhaps shifted to left or right if origin is missing.
-
-    if(use_y_axis_lines_)
-    { // Draw the vertical Y-axis line (at cartesian x = 0).
-      double ybottom = plot_y2;
-      if (use_down_ticks && use_y_ticks_on_plot_window_ && (x_axis_position_ == x_intersect) )
-      { // Extend the vertical line down in lieu of a tick.
-        ybottom += (std::max)(x_minor_tick_length_, x_major_tick_length_);
+      bool x_label_on()
+      {
+        return use_x_label;
       }
-      image.get_g_element(detail::PLOT_Y_AXIS).line(x, plot_y1, x, ybottom);
-    // <g id="yAxis" stroke="rgb(0,0,0)"><line x1="70.5" y1="53" x2="70.5" y2="357"/>
-    }
-    // Access the paths for the ticks & grids, ready for additions.
-    path_element& minor_tick_path = image.get_g_element(detail::PLOT_Y_MINOR_TICKS).path();
-    path_element& major_tick_path = image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).path();
-    path_element& minor_grid_path = image.get_g_element(detail::PLOT_Y_MINOR_GRID).path();
-    path_element& major_grid_path = image.get_g_element(detail::PLOT_Y_MAJOR_GRID).path();
-
-    if(use_y_ticks_on_plot_window_)
-    { // TODO ensure that labels allow space. - they don't at present.
-      // Was y_external style - so both labels and ticks are OUTSIDE the plot window.
-      // 
-    }
 
-    // y_minor_jump is the interval between minor ticks.
-    double y_minor_jump = y_major_interval_ / ((double)(y_num_minor_ticks_ + 1.) );
-    // TODO Problem here with using floating point?
-    // Was i < y_max; but didn't show the tick and value at y_max so now i <= y_max;
-    // But may still fail if a ls or few bits out? Seems to fail for y = 100, for example.
+      svg_2d_plot& y_major_labels_on(bool cmd)
+      {
+        use_y_major_labels = cmd;
+        return *this;
+      }
 
-    // Draw the ticks on the positive side.
-    for(double y = 0; y <= y_max; y += y_major_interval_)
-    {
-      for(double j = y + y_minor_jump;
-        j < (y + y_major_interval_) * (1. - 2 * std::numeric_limits<double>::epsilon());
-        j += y_minor_jump)
-      { // Draw minor ticks.
-        // This will output 'orphaned' minor ticks that are beyond the plot window,
-        // if the last major tick does not coincide with the plot window.
-        // These are just ignored in draw_x_minor_ticks.
-        // There might be 9 of them,
-        // if you have the common 9 minor tick between major ticks!
-        // TODO this seems ugly - as does the negative ones below.
-        if (j != 0. || ! use_x_axis_lines_)
-        { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
-          // (won't be X-axis line for 1-D where the zero tick is always wanted).
-          draw_y_minor_ticks(j, minor_tick_path, minor_grid_path);
-        }
-      }
-      if ((y != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
-      { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
-        // (won't be X-axis line for 1-D where the zero tick is always wanted).
-        draw_y_major_ticks(y, major_tick_path, major_grid_path);
+      bool y_major_labels_on()
+      {
+        return use_y_major_labels;
       }
-    }
 
-    // Draw the ticks on the negative side.
-    for(double y = 0; y >= y_min; y -= y_major_interval_)
-    {
-      for(double j=y; j > y-y_major_interval_; j-= y_major_interval_ / (y_num_minor_ticks_ + 1))
-      { // Draw minor ticks.
-        if ((j != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
-        { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
-          // (won't be X-axis line for 1-D where the zero tick is always wanted).
-          draw_y_minor_ticks(j, minor_tick_path, minor_grid_path);
-        }
+      svg_2d_plot& y_major_label_rotation(int rot)
+      {
+        y_label_rotation_ = rot;
+        return *this;
       }
-      if ((y != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
-      { // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
-        // (won't be X-axis line for 1-D where the zero tick is always wanted).
-        draw_y_major_ticks(y, major_tick_path, major_grid_path);
+
+      int y_major_label_rotation()
+      {
+        return y_label_rotation_;
       }
-    }
-  } // draw_y_axis
 
-  void draw_y_label()
-  {
-    // image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_color(black);
-    // Now set in constructor, and can be changed with member function .
-
-    std::string label = y_label_info.text(); // x_axis label, and optional units.
-    if (use_x_label_units && (y_units_info.text() != ""))
-    { // Append the units, if any, providing brackets ().
-      // TODO Is this the best policy - or should the user provide the ()s????
-      label += "  (" + y_units_info.text() + ")";
-    }
+      svg_2d_plot& y_axis_width(double width)
+      {
+        image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_width(width);
+        return *this;
+      }
 
-    image.get_g_element(detail::PLOT_Y_LABEL).push_back(new
-      text_element(y_label_info.font_size() * 1.5,
-      // shift over one char height to right from left edge of image.
-      (plot_y2 + plot_y1) / 2., // center on the plot window.
-      label, // "Y-Axis" for example.
-       y_label_info.font_size(),
-       y_label_info.font_family(),
-       "", "", "", "",
-       center_align, // One might want it to left or right_align?
-       upward)); // Y label must be drawn vertically.
-  } // draw_y_label
-
-  void draw_y_major_ticks(double value, path_element& tick_path, path_element& grid_path)
-  { // Draw Y axis major ticks, tick value labels & grids.
-    double y1(value);
-    transform_y(y1); // cartesian to SVG coordinates.
-    double x1(0.); // left end of tick.
-    double x2(image.y_size()); // right end of tick.
-    if(use_y_major_grid_)
-    { // Draw horizontal major grid line.
-      if(!use_plot_window_)
-      { // TODO is this right?
-        //if (use_title())
-        //{ // title has no effect if at the top.
-        //  y1 += title_info.font_size() * text_margin_;
-        //}
-        if(use_y_label)
-        { // Start further right to give space for y axis value label.
-          y1 -= y_label_value.font_size() * text_margin_ ;
-        }
+      double y_axis_width()
+      {
+        return image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_width();
+      }
 
-        if(use_left_ticks)
-        { // And similarly for left ticks.
-          y1 -= y_major_tick_length_;
-        }
+      svg_2d_plot& y_value_precision(int digits)
+      { // Precision of Y tick label values in decimal digits (default 3).
+        y_value_precision_ = digits;
+        return *this;
+      }
+
+      int y_value_precision()
+      { // Precision of Y tick label values in decimal digits (default 3).
+        return y_value_precision_;
       }
-      else
-      { // Do use_plot_window.
-        x1 = plot_x1 + 1;
-        x2 = plot_x2 - 1;
+
+      svg_2d_plot& y_value_ioflags(int flags)
+      { // IO flags of Y tick label values (default 0X201).
+        y_value_ioflags_ = flags;
+        return *this;
       }
-      grid_path.M(x1, y1).L(x2, y1);
-    } // use_y_major_grid_
 
-    if((y1 <= plot_y2) && (y1 >= plot_y1))
-    { // Make sure that we are drawing inside the allowed window.
-      double y_tick_length = y_major_tick_length_;
-      if(use_y_ticks_on_plot_window_) // (was external_style)
-      { // Start ticks on the plot window border.
-        x1 = plot_x1; // x1 = left,
-        x2 = plot_x1; //  x2 = right.
+      int y_value_ioflags()
+      { // ALL stream ioflags for control of format of Y value labels.
+        return y_value_ioflags_;
       }
-      else
-      { // Internal style ticks on vertical Y-axis.
-        x1 = y_axis; // Y-axis line.
-        x2 = y_axis;
+
+      svg_2d_plot& y_axis_color(const svg_color& col)
+      { // Set only stroke color.
+        image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_color(col);
+        return *this;
       }
-      if(use_left_ticks)
+
+      svg_color y_axis_color()
+      { // return the stroke color.
+        return image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_color();
+      }
+
+      svg_2d_plot& y_axis_label_color(const svg_color& col)
+      { // Set BOTH stroke and fill to the same color.
+        image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
+        image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
+        return *this;
+      }
+
+      svg_color y_axis_label_color()
+      { // But only return the stroke color.
+        return image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color();
+      }
+
+      svg_2d_plot& y_label_units_on(bool b)
       {
-        x1 -= y_tick_length; // left
+        use_y_label_units = b;
+        return *this;
       }
-      if (use_right_ticks)
+
+      bool y_label_units_on()
+      { // But only return the stroke color.
+        return use_y_label_units;
+      }
+
+      svg_2d_plot& y_axis_value_color(const svg_color& col)
+      { // Set BOTH stroke and fill to the same color.  TODO only stroke color?
+        image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
+        image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
+        return *this;
+      }
+
+      svg_color y_axis_value_color()
+      { // But only return the stroke color.
+        return image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color();
+      }
+
+      svg_2d_plot& y_label_width(double width)
+      { // width of text is effectively the boldness
+        image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_width(width);
+        return *this;
+      }
+
+      double y_label_width()
       {
-        x2 += y_tick_length; // right.
+        return image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_width();
       }
-      tick_path.M(x1, y1).L(x2, y1); // Draw the major tick.
-      // leaving x1 at the left most end of any tick.
-    }
 
-    if(use_y_major_labels)
-    { // Label the tick with value, for example "1.2"
-      std::stringstream label;
-      label.precision(y_value_precision_);
-      label.flags(y_value_ioflags_); // set ALL IOflags.
-      label << value; // Example: label.str() == "20" or "0.25" or "1.2e+015"
-      if(use_left_ticks)
-      {
-        if (y_minor_tick_length_ > y_minor_tick_length_)
-        { // In case some joker has made the minor ticks longer than the major,
-          // we might need to move left more for the longer tick.
-          x1 -= (y_minor_tick_length_ - y_minor_tick_length_);
-        }
-        x1 -= y_label_value.font_size(); // move left by a font width.
-      }
-      else
-      { // No need to move if right tick, or none.
-      }
-      // Need to work out how much space value labels will need.
-      double y = y1;
-      align_style alignment = center_align;
-      if(use_y_ticks_on_plot_window_)
-      { // External to plot window style.
-        if(y_label_rotation_ == horizontal)
-        {  // Just shift down half a digit to center value digits on tick.
-          alignment = right_align;
-          y += y_label_value.font_size() / 2;
-        }
-        else if ((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
-        {// Tick value label straight up or down vertically on y axis.
-         // No shift y down to center.
-          alignment = center_align;
-        }
-        else
-        { // Assume some 45 slope, so need about sqrt(2) less space?
-           x1 += y_label_value.font_size() * 0.5; // move left by half a font width.
-          // no y shift needed.
-          alignment = right_align;
-        }
-        // Always want all values including "0", if labeling external to plot window.
-        // use_ticks_on_plot_window_ == true
-        image.get_g_element(detail::PLOT_VALUE_LABELS).text(
-          x1,
-          y,
-          label.str(), y_label_value.font_size(), "", "", "", "", "", alignment, y_label_rotation_);
-      }
-      else
-      { // ! use_y_ticks_on_plot_window_ == Internal - value labels close to left of vertical Y-axis.
-        if ((value != 0) && use_x_axis_lines_)
-        { // Avoid a zero ON the Y-axis if it would be cut through by any horizontal X-axis line.
-          y += y_label_value.font_size() / 2;
-          image.get_g_element(detail::PLOT_VALUE_LABELS).text(
-            x1 ,
-            y, // Just shift down half a digit to center value digits on tick.
-            label.str(), y_label_value.font_size(), y_label_value.font_family(), "", "", "", "",
-            alignment, // on the tick ???
-            y_label_rotation_);
-        }
+      svg_2d_plot& y_major_grid_color(const svg_color& col)
+      {
+        image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_color(col);
+        return *this;
       }
-    } // if(use_y_major_labels)
-  } // draw_y_major_ticks
 
-      void draw_y_minor_ticks(double value, path_element& tick_path, path_element& grid_path)
-    {
-      double x1(0.);
-      double y1(value); // for tick position and value label.
-      transform_y(y1);
-      double x2(image.y_size()); // right edge of image.
-
-    if(use_y_minor_grid_)
-    { // Draw the minor grid, if wanted.
-      if(!use_plot_window_)
-      { // Use whole image, but make space for title & labels text.
-        //if(use_title)
-        //{ // If title at top, should make no difference, unlike X grid.
-        //  x2 -= title_info.font_size() * text_margin_;
-        //}
-        if(use_y_label)
+      const svg_color& y_major_grid_color()
+      {
+        return image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_color();
+      }
+
+      svg_2d_plot& y_minor_grid_color(const svg_color& col)
+      {
+        image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_color(col);
+        return *this;
+      }
+
+      const svg_color& y_minor_grid_color()
+      {
+        return image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_color();
+      }
+
+      svg_2d_plot& y_major_tick_color(const svg_color& col)
+      {
+        image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_color(col);
+        return *this;
+      }
+
+      const svg_color& y_major_tick_color()
+      {
+        return image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_color();
+      }
+
+      svg_2d_plot& y_minor_tick_color(const svg_color& col)
+      {
+        image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_color(col);
+        return *this;
+      }
+
+      const svg_color& y_minor_tick_color()
+      {
+        return image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_color();
+      }
+
+      svg_2d_plot& y_range(double y1, double y2)
+      { // Set the range (max and min) for Y values.
+        y_min = y1;
+        y_max = y2;
+        if(y2 <= y1)
         {
-          x1 += y_label_info.font_size() * text_margin_;
-          x2 -= y_label_info.font_size() * text_margin_;
+          throw std::runtime_error("Illegal Argument: X scale: x2 < x1");
         }
+        return *this;
       }
-      else
-      { // Use plot window.
-        x1 = plot_x1 + 1; // TODO what is the +1 for?
-        x2 = plot_x2 - 1; // Ensure *inside* window?
+
+      std::pair<double, double> y_range()
+      {
+        std::pair<double, double> r;
+        r.first = y_min;
+        r.second = y_max;
+        return r;
       }
-      if((y1 >= plot_y1) && (x1 >= plot_x1) && (x2 <= plot_x2) )
-      { // // Make sure that we are drawing inside the allowed window.
-        grid_path.M(x1, y1).L(x2, y1);
+
+      double y_minimum()
+      {
+        return y_min;
       }
-      // TODO else just ignore outside plot window?
-    }
 
-    if(use_y_ticks_on_plot_window_)
-    { // Put y minor ticks on the plot window border. External style.
-      x1 = plot_x1; // On the plot window border.
-      x2 = plot_x1;
-    }
-    else
-    { // Internal style.
-      x1 = y_axis; // On the Y-axis line.
-      x2 = y_axis;
-    }
-    if(use_left_ticks)
-    {
-      x1 -= y_minor_tick_length_;
-    }
-    if(use_right_ticks)
-    {
-      x2 += y_minor_tick_length_;
-    }
-    //if((x1 >= plot_x1) && (x2 <= plot_x2) && (y1 <= plot_y2) && (y1 >= plot_y1))
-    // but can never be inside if left tick!
-    if((y1 <= plot_y2) && (y1 >= plot_y1))
-    { // Make sure that we are drawing inside of the allowed plot window.
-      tick_path.M(x1, y1).L(x2, y1); // Draw the tick.
-    }
-    else
-    {// Do nothing?  warn?
-     // std::cout << "y minor tick OUTside " << x1 << ' ' << y1 << ' ' << x2 << std::endl;
+      double y_maximum()
+      {
+        return y_max;
+      }
 
-    }
-  } // void draw_y_minor_ticks
+      svg_2d_plot& y_major_interval(double inter)
+      {
+        y_major_interval_ = inter;
+        return *this;
+      }
 
-  void draw_straight_lines(const svg_2d_plot_series& series)
-  { // Straight line between data points (rather than a Bezier curve).
-    double prev_x; // Previous data points.
-    double prev_y;
-    double temp_x(0.);
-    double temp_y;
-
-    g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_LINES).add_g_element();
-    g_ptr.clip_id(plot_window_clip);
-    g_ptr.style().stroke_color(series.line_style.color);
-    g_ptr.style().fill_color(series.line_style.area_fill);
-    path_element& path = g_ptr.path();
-    path.style().fill_color(series.line_style.area_fill);
+      double y_major_interval()
+      {
+        return y_major_interval_;
+      }
 
-    bool is_fill = !series.line_style.area_fill.blank;
-    path.fill = is_fill; // Ensure includes a fill="none".
+      svg_2d_plot& y_major_tick_length(double length)
+      {
+        y_major_tick_length_ = length;
+        return *this;
+      }
 
-    if(series.series.size() > 1)
-    {
-      std::multimap<double, double>::const_iterator j = series.series.begin();
+      double y_major_tick_length()
+      {
+        return y_major_tick_length_;
+      }
 
-      // If we have to fill the area under the plot,
-      // we first have to move from the X-axis (y = 0) to the first point,
-      // and again at the end after the last point.
-      prev_x = (*j).first;
-      prev_y = 0.;
-      transform_point(prev_x, prev_y);
-      if(is_fill)
-      { // Move to 1st point.
-        path.style().fill_color(series.line_style.area_fill);
-        path.M(prev_x, prev_y);
+      svg_2d_plot& y_minor_tick_length(double length)
+      {
+        y_minor_tick_length_ = length;
+        return *this;
       }
-      transform_y(prev_y = (*j).second);
-      if(is_fill)
-      { // fill wanted.
-        path.style().fill_color(series.line_style.area_fill); // TOD why again?
-        path.L(prev_x, prev_y); // Line from X-axis to 1st point.
+
+      double y_minor_tick_length()
+      {
+        return y_minor_tick_length_;
       }
-      else
-      { // fill == blank
-        path.M(prev_x, prev_y);
+
+      svg_2d_plot& y_num_minor_ticks(unsigned int num)
+      {
+        y_num_minor_ticks_ = num;
+        return *this;
       }
-      ++j; // so now refers to 2nd point to plot.
 
-      for(; j != series.series.end(); ++j)
+      unsigned int y_num_minor_ticks()
       {
-        temp_x = (*j).first;
-        temp_y = (*j).second;
-        transform_point(temp_x, temp_y);
-        path.L(temp_x, temp_y); // line to next point.
+        return y_num_minor_ticks_;
+      }
 
-        if(is_fill)
-        {
-          path.M(temp_x, temp_y);
-        }
-        prev_x = temp_x;
-        prev_y = temp_y;
-      } // for j
+      svg_2d_plot& y_label_axis(const std::string& str)
+      { // Label for Y-axis.
+        y_label_info.text(str);
+        return *this;
+      }
 
-      if(is_fill)
-      { // fill wanted.
-        transform_y(temp_y = 0.); // X-axis line.
-        path.L(temp_x, temp_y).z(); // closepath with Z to terminate line.
+      std::string y_label_axis()
+      {
+        return y_label_info.text();
       }
-    }
-  } // draw_straight_lines
 
-  void draw_bezier_lines(const svg_2d_plot_series& series)
-  {
-    g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_LINES).add_g_element();
-    g_ptr.clip_id(plot_window_clip);
-    g_ptr.style().stroke_color(series.line_style.color);
-    path_element& path = g_ptr.path();
-
-    std::pair<double, double> n; // current point.
-    std::pair<double, double> n_minus_1; // penultimate.
-    std::pair<double, double> n_minus_2;
-    std::pair<double, double> fwd_vtr;
-    std::pair<double, double> back_vtr;
+      svg_2d_plot& y_major_tick_width(double width)
+      {
+        y_major_tick_width_ = width;
+        image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_width(width);
+        return *this;
+      }
 
-    bool is_fill = !series.line_style.area_fill.blank;
-    if(is_fill == false)
-    {
-      path.fill = false; // default path constructor is true - TODO why??
-    }
-    else
-    { // fill
-      path.style().fill_color(series.line_style.area_fill);
-    }
+      double y_major_tick_width()
+      {
+        return y_major_tick_width_;
+      }
 
-    if(series.series.size() > 2)
-    { // Need >= 3 for a cubic curve (start point, 2 control points, and end point).
-      std::multimap<double, double>::const_iterator iter = series.series.begin();
-      n_minus_1 = *(iter++);  // begin() 
-      transform_pair(n_minus_1);
-      n = *(iter++); // middle
-      transform_pair(n);
-      path.M(n_minus_1.first, n_minus_1.second); // move m_minus_1, the 1st data point.
-
-      double control = 0.1;  
-      //0.2 is a scaling factor that Jake used to define the magnitude of the
-      //vector of the current control point to be placed. I was basically
-      //taking advantage of the auto-drawing of Bezier curves that exists in
-      //the SVG format, and this is my attempt to give the control point the
-      //proper length.
-
-      // Experiment suggests that 0.2 gives distorsions with exp curves.
-      // 0.05 is just visually OK with 50 points, but 100 are better.
-
-      for(; iter != series.series.end(); ++iter)
-      {
-        n_minus_2 = n_minus_1; 
-        n_minus_1 = n;
-        n = *iter;
-        transform_pair(n);
-
-        back_vtr.first = ((n_minus_1.first - n.first) + // (x diff - x previous diff) * control
-          (n_minus_2.first - n_minus_1.first)) * control; 
-        back_vtr.second = ((n_minus_1.second - n.second) + // y
-          (n_minus_2.second - n_minus_1.second)) * control;
-
-        // 8.3.6 The cubic Bézier curve commands path.S(x, y).
-        // Start point, end point, & two control points.
-        // Example: S378.5,519.3 381,519.3 ...
-        // S end_control_point, end point
-        // Start is reflection of last point's control point.
-        path.S(n_minus_1.first + back_vtr.first, // x
-               n_minus_1.second + back_vtr.second, // y - end control point
-               n_minus_1.first, n_minus_1.second); // x, y - end point.
-      } // for
-      // Last point.
-      back_vtr.first = 0.; 
-      back_vtr.second = (n.second - n_minus_1.second) * control;
-      path.S(n.first + back_vtr.first, // x
-             n.second + back_vtr.second, // y
-             n.first, n.second); // x, y
-    }
-    else
-    { // Only one or two points, so no curving possible!
-      draw_straight_lines(series);
-    }
-  } // draw_bezier_lines
+      svg_2d_plot& y_minor_tick_width(double width)
+      {
+        y_minor_tick_width_ = width;
+        image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_width(width);
+        return *this;
+      }
 
-  void draw_plot_lines()
-  { // Draw line through data series, Bezier curved or straight.
-    for(unsigned int i = 0; i < series.size(); ++i)
-    {
-      if(series[i].line_style.bezier_on)
-      { // curved.
-        draw_bezier_lines(series[i]);
+      double y_minor_tick_width()
+      {
+        return y_minor_tick_width_;
       }
-      else
+
+      svg_2d_plot& x_ticks_on_plot_window_on(bool is)
       {
-        draw_straight_lines(series[i]);
+        use_x_ticks_on_plot_window_ = is;
+        return *this;
       }
-    }
-  } // draw_plot_lines
 
-  void update_image()
-  {
-    clear_all();
-    // svg paint rules are that later 'painting' writes over previous
-    // painting, so the order of drawing is important.
-
-    // Draw image background (perhaps with border and/or fill color).
-    image.get_g_element(detail::PLOT_BACKGROUND).push_back(
-      new rect_element(0, 0, image.x_size(),  image.y_size()));
-
-    calculate_plot_window();
-    draw_title(); // Moved to ensure plot_X and Y are valid.
-
-    // Define the clip path for the plot window.
-    // We don't want to allow overlap of the plot window border lines,
-    // thus the minor adjustments.
-    // TODO should this be border thickness?
-
-    image.clip_path(rect_element(plot_x1 + 1, plot_y1 + 1,
-      plot_x2 - plot_x1 - 2, plot_y2 - plot_y1 - 2),
-      plot_window_clip);
-    // <clipPath id="plot_window"><rect x="35" y="38" width="309" height="322"/></clipPath>
+      bool x_ticks_on_plot_window_on()
+      {
+        return use_x_ticks_on_plot_window_;
+      }
 
-    image.get_g_element(detail::PLOT_DATA_POINTS).clip_id(plot_window_clip);
+      svg_2d_plot& y_ticks_on_plot_window_on(bool is)
+      {
+        use_y_ticks_on_plot_window_ = is;
+        return *this;
+      }
 
-    // Draw axes, labels & legend, as required.
-    if(use_axis)
-    {
-      draw_x_axis(); // Must do X-axis first.
-      draw_y_axis(); // TODO is draw_axes used?
-    }
-    if(use_legend)
-    {
-      draw_legend();
-    }
-    if(use_x_label)
-    {
-      draw_x_label();
-    }
-    if(use_y_label)
-    {
-      draw_y_label();
-    }
+      bool y_ticks_on_plot_window_on()
+      {
+        return use_y_ticks_on_plot_window_;
+      }
 
-    draw_plot_lines(); // Draw lines between points.
 
-    // Draw normal 'good' non-limit points.
-    double x(0.);
-    double y(0.);
-    for(unsigned int i = 0; i < series.size(); ++i)
-    {
-      g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_POINTS).add_g_element();
+      svg_2d_plot& y_ticks_left_on(bool cmd)
+      {
+        use_left_ticks = cmd;
+        return *this;
+      }
 
-      g_ptr.style()
-        .fill_color(series[i].point_style.fill_color_)
-        .stroke_color(series[i].point_style.stroke_color_);
-
-      for(std::multimap<double, double>::const_iterator j = series[i].series.begin();
-        j != series[i].series.end(); ++j)
-      {
-        x = j->first;
-        y = j->second;
-        transform_point(x, y);
-        if((x > plot_x1)  && (x < plot_x2) && (y > plot_y1)  && (y < plot_y2))
-        { // Onside plot window, so draw a point.
-          draw_plot_point(x, y, g_ptr, series[i].point_style);
-        }
-      } // for
-    } // for normal points
+      bool y_ticks_left_on()
+      {
+        return use_left_ticks;
+      }
 
-    // Draw all the 'bad' at_limit points.
-    for(unsigned int i = 0; i < series.size(); ++i)
-    {
-      g_element& g_ptr = image.get_g_element(detail::PLOT_LIMIT_POINTS);
+      svg_2d_plot& y_ticks_right_on(bool cmd)
+      {
+        use_right_ticks = cmd;
+        return *this;
+      }
 
-      for(std::multimap<double,double>::const_iterator j = series[i].series_limits.begin();
-        j!=series[i].series_limits.end(); ++j)
+      bool y_ticks_right_on()
       {
-        x = j->first;
-        y = j->second;
-        transform_point(x, y);
-        draw_plot_point(x, y, g_ptr, plot_point_style(blank, blank, series[i].point_style.size_, cone));
-        // TODO why are fill and stroke blank? How is point style for 'bad' values determined?
-      }
-    } // limits point
-  } // void update_image()
-
-
-public: // Member functions
-  // -----------------------------------------------------------------
-  // write() has two flavors, a file and a ostream.
-  // The file version opens an ostream, and calls the stream version.
-  // The stream version first clears all unnecessary data from the graph,
-  // builds the document tree, and then calls the write function for the root
-  // document node, which calls all other nodes through the Visitor pattern.
-  // -----------------------------------------------------------------
-
-  svg_2d_plot& write(const std::string& filename)
-  { // Write the plot image to a named file.
-    std::ofstream fout(filename.c_str());
-    if(fout.fail())
-    {
-      throw std::runtime_error("Unable to open " + filename);
-    }
-    write(fout); // Using the ostream version.
-    return *this;
-  }
-
-  svg_2d_plot& write(std::ostream& s_out)
-  { // Write the image to an ostream.
-    update_image();
-    image.write(s_out); // Use the ostream version of write.
-    return *this;
-  }
-
-  // Member functions to set plot options.
-  // All return *this to permit chaining.
-
-  // These below only refer to 2D plot.
-  // See axis_plot_label.hpp for all the many 1D functions X-Axis.
-
-  svg_2d_plot& y_label_on(bool cmd)
-  { // Y axis name or label.
-    use_y_label = cmd;
-    return *this;
-  }
-
-  bool y_label_on()
-  {
-    return use_y_label;
-  }
-
-  svg_2d_plot& x_label_on(bool cmd)
-  {
-    use_x_label = cmd;
-    return *this;
-  }
-
-  bool x_label_on()
-  {
-    return use_x_label;
-  }
-
-  svg_2d_plot& y_major_labels_on(bool cmd)
-  {
-    use_y_major_labels = cmd;
-    return *this;
-  }
-
-  bool y_major_labels_on()
-  {
-    return use_y_major_labels;
-  }
-
-  svg_2d_plot& y_major_label_rotation(int rot)
-  {
-    y_label_rotation_ = rot;
-    return *this;
-  }
-
-  int y_major_label_rotation()
-  {
-    return y_label_rotation_;
-  }
-
-  svg_2d_plot& y_axis_width(double width)
-  {
-    image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_width(width);
-    return *this;
-  }
-
-  double y_axis_width()
-  {
-    return image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_width();
-  }
-
-  svg_2d_plot& y_value_precision(int digits)
-  { // Precision of Y tick label values in decimal digits (default 3).
-    y_value_precision_ = digits;
-    return *this;
-  }
-
-  int y_value_precision()
-  { // Precision of Y tick label values in decimal digits (default 3).
-    return y_value_precision_;
-  }
-
-  svg_2d_plot& y_value_ioflags(int flags)
-  { // IO flags of Y tick label values (default 0X201).
-    y_value_ioflags_ = flags;
-    return *this;
-  }
-
-  int y_value_ioflags()
-  { // ALL stream ioflags for control of format of Y value labels.
-    return y_value_ioflags_;
-  }
-
-  svg_2d_plot& y_axis_color(const svg_color& col)
-  { // Set only stroke color.
-    image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_color(col);
-    return *this;
-  }
-
-  svg_color y_axis_color()
-  { // return the stroke color.
-    return image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_color();
-  }
-
-  svg_2d_plot& y_axis_label_color(const svg_color& col)
-  { // Set BOTH stroke and fill to the same color.
-    image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
-    image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
-    return *this;
-  }
-
-  svg_color y_axis_label_color()
-  { // But only return the stroke color.
-    return image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color();
-  }
-
-  svg_2d_plot& y_label_units_on(bool b)
-  {
-    use_y_label_units = b;
-    return *this;
-  }
-
-  bool y_label_units_on()
-  { // But only return the stroke color.
-    return use_y_label_units;
-  }
-
-  svg_2d_plot& y_axis_value_color(const svg_color& col)
-  { // Set BOTH stroke and fill to the same color.  TODO only stroke color?
-    image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
-    image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
-    return *this;
-  }
-
-  svg_color y_axis_value_color()
-  { // But only return the stroke color.
-    return image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color();
-  }
-
-  svg_2d_plot& y_label_width(double width)
-  { // width of text is effectively the boldness
-    image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_width(width);
-    return *this;
-  }
-
-  double y_label_width()
-  {
-    return image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_width();
-  }
-
-  svg_2d_plot& y_major_grid_color(const svg_color& col)
-  {
-    image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_color(col);
-    return *this;
-  }
-
-  const svg_color& y_major_grid_color()
-  {
-    return image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_color();
-  }
-
-  svg_2d_plot& y_minor_grid_color(const svg_color& col)
-  {
-    image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_color(col);
-    return *this;
-  }
-
-  const svg_color& y_minor_grid_color()
-  {
-    return image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_color();
-  }
-
-  svg_2d_plot& y_major_tick_color(const svg_color& col)
-  {
-    image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_color(col);
-    return *this;
-  }
-
-  const svg_color& y_major_tick_color()
-  {
-    return image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_color();
-  }
-
-  svg_2d_plot& y_minor_tick_color(const svg_color& col)
-  {
-    image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_color(col);
-    return *this;
-  }
-
-  const svg_color& y_minor_tick_color()
-  {
-    return image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_color();
-  }
-
-  svg_2d_plot& y_range(double y1, double y2)
-  { // Set the range (max and min) for Y values.
-    y_min = y1;
-    y_max = y2;
-    if(y2 <= y1)
-    {
-      throw std::runtime_error("Illegal Argument: X scale: x2 < x1");
-    }
-    return *this;
-  }
+        return use_right_ticks;
+      }
+      // Only need y_ticks_left_on & y_ticks_right_on in 2D
+
+
+      svg_2d_plot& y_major_grid_on(bool is)
+      {
+        use_y_major_grid_ = is;
+        return *this;
+      }
+
+      bool y_major_grid_on()
+      {
+        return use_y_major_grid_;
+      }
+
+      svg_2d_plot& y_minor_grid_on(bool is)
+      {
+        use_y_minor_grid_ = is;
+        return *this;
+      }
+
+      bool y_minor_grid_on()
+      {
+        return use_y_minor_grid_;
+      }
+
+      svg_2d_plot& y_minor_grid_width(double width)
+      {
+        y_minor_grid_width_ = width;
+        image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_width(width);
+        return *this;
+      }
+
+      double y_minor_grid_width()
+      {
+        return y_minor_grid_width_;
+      }
+
+      svg_2d_plot& y_major_grid_width(double width)
+      {
+        y_major_grid_width_ = width;
+        image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_width(width);
+        return *this;
+      }
+
+      double y_major_grid_width()
+      {
+        return y_major_grid_width_;
+      }
+
+      svg_2d_plot& y_label_font_size(unsigned int i)
+      { // May be best to tie label & unit font sizes together?
+        y_label_info.font_size(i);
+        // y_units_info.font_size(i);
+        return *this;
+      }
+
+      unsigned int y_label_font_size()
+      {
+        return y_label_info.font_size();
+      }
+
+      svg_2d_plot& y_label_weight(std::string s)
+      { // "bold2 is only one that works so far.
+        y_label_info.font_weight(s);
+        return *this;
+      }
 
-  std::pair<double, double> y_range()
-  {
-    std::pair<double, double> r;
-    r.first = y_min;
-    r.second = y_max;
-    return r;
-  }
-
-  double y_minimum()
-  {
-    return y_min;
-  }
-
-  double y_maximum()
-  {
-    return y_max;
-  }
-
-  svg_2d_plot& y_major_interval(double inter)
-  {
-    y_major_interval_ = inter;
-    return *this;
-  }
-
-  double y_major_interval()
-  {
-    return y_major_interval_;
-  }
-
-  svg_2d_plot& y_major_tick_length(double length)
-  {
-    y_major_tick_length_ = length;
-    return *this;
-  }
-
-  double y_major_tick_length()
-  {
-    return y_major_tick_length_;
-  }
-
-  svg_2d_plot& y_minor_tick_length(double length)
-  {
-    y_minor_tick_length_ = length;
-    return *this;
-  }
-
-  double y_minor_tick_length()
-  {
-    return y_minor_tick_length_;
-  }
-
-  svg_2d_plot& y_num_minor_ticks(unsigned int num)
-  {
-    y_num_minor_ticks_ = num;
-    return *this;
-  }
-
-  unsigned int y_num_minor_ticks()
-  {
-    return y_num_minor_ticks_;
-  }
-
-  svg_2d_plot& y_label_axis(const std::string& str)
-  { // Label for Y-axis.
-    y_label_info.text(str);
-    return *this;
-  }
-
-  std::string y_label_axis()
-  {
-    return y_label_info.text();
-  }
-
-  svg_2d_plot& y_major_tick_width(double width)
-  {
-    y_major_tick_width_ = width;
-    image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_width(width);
-    return *this;
-  }
-
-  double y_major_tick_width()
-  {
-    return y_major_tick_width_;
-  }
-
-  svg_2d_plot& y_minor_tick_width(double width)
-  {
-    y_minor_tick_width_ = width;
-    image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_width(width);
-    return *this;
-  }
-
-  double y_minor_tick_width()
-  {
-    return y_minor_tick_width_;
-  }
-
-  svg_2d_plot& x_ticks_on_plot_window_on(bool is)
-  {
-    use_x_ticks_on_plot_window_ = is;
-    return *this;
-  }
-
-  bool x_ticks_on_plot_window_on()
-  {
-    return use_x_ticks_on_plot_window_;
-  }
-
-  svg_2d_plot& y_ticks_on_plot_window_on(bool is)
-  {
-    use_y_ticks_on_plot_window_ = is;
-    return *this;
-  }
-
-  bool y_ticks_on_plot_window_on()
-  {
-    return use_y_ticks_on_plot_window_;
-  }
-
-
-  svg_2d_plot& y_ticks_left_on(bool cmd)
-  {
-    use_left_ticks = cmd;
-    return *this;
-  }
-
-  bool y_ticks_left_on()
-  {
-    return use_left_ticks;
-  }
-
-  svg_2d_plot& y_ticks_right_on(bool cmd)
-  {
-    use_right_ticks = cmd;
-    return *this;
-  }
-
-  bool y_ticks_right_on()
-  {
-    return use_right_ticks;
-  }
-  // Only need y_ticks_left_on & y_ticks_right_on in 2D
-
-
-  svg_2d_plot& y_major_grid_on(bool is)
-  {
-    use_y_major_grid_ = is;
-    return *this;
-  }
-
-  bool y_major_grid_on()
-  {
-    return use_y_major_grid_;
-  }
-
-  svg_2d_plot& y_minor_grid_on(bool is)
-  {
-    use_y_minor_grid_ = is;
-    return *this;
-  }
-
-  bool y_minor_grid_on()
-  {
-    return use_y_minor_grid_;
-  }
-
-  svg_2d_plot& y_minor_grid_width(double width)
-  {
-    y_minor_grid_width_ = width;
-    image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_width(width);
-    return *this;
-  }
-
-  double y_minor_grid_width()
-  {
-    return y_minor_grid_width_;
-  }
-
-  svg_2d_plot& y_major_grid_width(double width)
-  {
-    y_major_grid_width_ = width;
-    image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_width(width);
-    return *this;
-  }
-
-  double y_major_grid_width()
-  {
-    return y_major_grid_width_;
-  }
-
-  svg_2d_plot& y_label_font_size(unsigned int i)
-  { // May be best to tie label & unit font sizes together?
-    y_label_info.font_size(i);
-    // y_units_info.font_size(i);
-    return *this;
-  }
-
-  unsigned int y_label_font_size()
-  {
-    return y_label_info.font_size();
-  }
-
-  svg_2d_plot& y_label_weight(std::string s)
-  { // "bold2 is only one that works so far.
-    y_label_info.font_weight(s);
-    return *this;
-  }
-
-  const std::string& y_label_weight()
-  {
-    return y_label_info.font_weight();
-  }
-
-  svg_2d_plot& y_label_font_family(const std::string& family)
-  {
-    y_label_info.font_family(family);
-    return *this;
-  }
-
-  const std::string& y_label_font_family();
-  //const std::string& y_label_font_family()
-  //{
-  //  return y_label_info.font_family();
-  //}
-
-  // Example of declaration but definition below.
-  // TODO Probably better done this way,
-  // but wait until parameter system removed.
-
-  // plot member function, with several parameters, using Boost.Parameter,
-  // to add data series to the plot window.
-  // TODO replace this with chainable member functions.
+      const std::string& y_label_weight()
+      {
+        return y_label_info.font_weight();
+      }
+
+      svg_2d_plot& y_label_font_family(const std::string& family)
+      {
+        y_label_info.font_family(family);
+        return *this;
+      }
+
+      const std::string& y_label_font_family();
+      //const std::string& y_label_font_family()
+      //{
+      //  return y_label_info.font_family();
+      //}
+
+      // Example of declaration but definition below.
+      // TODO Probably better done this way,
+      // but wait until parameter system removed.
+
+      // plot member function, with several parameters, using Boost.Parameter,
+      // to add data series to the plot window.
+      // TODO replace this with chainable member functions.
 
 #if defined (BOOST_MSVC)
 #  pragma warning(push)
 #  pragma warning(disable: 4100) // "'boost_parameter_enabler_argument' : unreferenced formal parameter"
 #endif
 
-  BOOST_PARAMETER_MEMBER_FUNCTION
-    (
-    (void),
-    plot,
-    tag,
-    (required
-    (container, *)
-    (title, (const std::string&))
-    )
-    (optional
-    (fill_color, (const svg_color&), white)
-    (stroke_color, (const svg_color&), black)
-    (line_color, (const svg_color&), black)
-    (area_fill_color, (const svg_color&), true) // == is blank
-   // (area_fill_color, (svg_color_constant), blank)
-    (point_style, (point_shape), round)
-    (size, (int), 10)
-    (line_on, (bool), true)
-    (bezier_on, (bool), false)
-    (x_functor, *, detail::boost_default_2d_convert())
-    )
-    )
-  {
-    // This line has the error in GCC. Also, operator() in boost_default_2d_convert
-    // has been changed so that the value of i is not updated. I would like
-    // the start to be set, as well as i to update in operator().
-    // x_functor.start(1.);
-
-    plot_line_style line_style(line_color, blank, line_on, bezier_on);
-
-    line_style.area_fill = area_fill_color;
-
-    series.push_back(
-      svg_2d_plot_series(
-      boost::make_transform_iterator(container.begin(), x_functor),
-      boost::make_transform_iterator(container.end(),   x_functor),
-      title,
-      plot_point_style(fill_color, stroke_color, size, point_style),
-      line_style
-      ));
-  }
-}; // class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
-
-// sample of declared function, externally defined in another .cpp file.
-// TODO May be useful to refactor all functions this way.
-  const std::string& svg_2d_plot::y_label_font_family()
-  {
-    return y_label_info.font_family();
-  }
+      BOOST_PARAMETER_MEMBER_FUNCTION
+        (
+        (void),
+        plot,
+        tag,
+        (required
+        (container, *)
+        (title, (const std::string&))
+        )
+        (optional
+        (fill_color, (const svg_color&), white)
+        (stroke_color, (const svg_color&), black)
+        (line_color, (const svg_color&), black)
+        (area_fill_color, (const svg_color&), true) // == is blank
+        // (area_fill_color, (svg_color_constant), blank)
+        (point_style, (point_shape), round)
+        (size, (int), 10)
+        (line_on, (bool), true)
+        (bezier_on, (bool), false)
+        (x_functor, *, detail::boost_default_2d_convert())
+        )
+        )
+      {
+        // This line has the error in GCC. Also, operator() in boost_default_2d_convert
+        // has been changed so that the value of i is not updated. I would like
+        // the start to be set, as well as i to update in operator().
+        // x_functor.start(1.);
+
+        plot_line_style line_style(line_color, blank, line_on, bezier_on);
+
+        line_style.area_fill = area_fill_color;
+
+        series.push_back(
+          svg_2d_plot_series(
+          boost::make_transform_iterator(container.begin(), x_functor),
+          boost::make_transform_iterator(container.end(),   x_functor),
+          title,
+          plot_point_style(fill_color, stroke_color, size, point_style),
+          line_style
+          ));
+      }
+    }; // class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
+
+    // sample of declared function, externally defined in another .cpp file.
+    // TODO May be useful to refactor all functions this way.
+    const std::string& svg_2d_plot::y_label_font_family()
+    {
+      return y_label_info.font_family();
+    }
 
 
 #if defined (BOOST_MSVC)