$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80306 - sandbox/SOC/2007/visualization/boost/svg_plot/impl
From: pbristow_at_[hidden]
Date: 2012-08-29 14:07:33
Author: pbristow
Date: 2012-08-29 14:07:32 EDT (Wed, 29 Aug 2012)
New Revision: 80306
URL: http://svn.boost.org/trac/boost/changeset/80306
Log:
Add missing /impl folder
Added:
   sandbox/SOC/2007/visualization/boost/svg_plot/impl/
   sandbox/SOC/2007/visualization/boost/svg_plot/impl/axis_plot_frame.ipp   (contents, props changed)
   sandbox/SOC/2007/visualization/boost/svg_plot/impl/svg_1d_plot.ipp   (contents, props changed)
Added: sandbox/SOC/2007/visualization/boost/svg_plot/impl/axis_plot_frame.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/impl/axis_plot_frame.ipp	2012-08-29 14:07:32 EDT (Wed, 29 Aug 2012)
@@ -0,0 +1,4153 @@
+  /*!  \file axis_plot_frame.hpp
+  \brief SVG Plot functions common to 1D, 2D and Boxplots.
+  \details Functions are derived from base class axis_plot_frame.
+  \date Mar 2009
+  \author Jacob Voytko and Paul A. Bristow
+*/
+
+// Copyright Jacob Voytko 2007
+// Copyright Paul A. Bristow 2007, 2008, 2009, 2012
+
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_SVG_AXIS_PLOT_FRAME_IPP
+#define BOOST_SVG_AXIS_PLOT_FRAME_IPP
+
+namespace boost
+{
+  namespace svg
+  {
+    namespace detail
+    { //! \namespace detail Holds base class axis_plot_frame for 1D, 2D and Box plots.
+
+      //template <class Derived>
+      //class axis_plot_frame
+
+          template <class Derived>
+          void axis_plot_frame<Derived>::clear_all()
+          { //!  Clear all layers of the plot.
+            /*! \details
+              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.
+            */
+            clear_legend();
+            clear_background();
+            clear_x_axis();
+            clear_y_axis();
+            clear_title();
+            clear_points();
+            clear_plot_background();
+            clear_grids();
+          }
+
+          template <class Derived>
+          void axis_plot_frame<Derived>::clear_background()
+          { //! Clear the whole image background layer of the SVG plot.
+            derived().image_.g(PLOT_BACKGROUND).clear();
+          }
+
+          template <class Derived>
+         void axis_plot_frame<Derived>::clear_title()
+          { //! Clear the plot title layer of the SVG plot.
+            derived().image_.g(PLOT_TITLE).clear();
+          }
+
+          template <class Derived>
+         void axis_plot_frame<Derived>::clear_points()
+          {  //! Clear the data points layer of the SVG plot.
+            derived().image_.g(PLOT_DATA_POINTS).clear();
+          }
+
+          template <class Derived>
+         void axis_plot_frame<Derived>::clear_plot_background()
+          { //! Clear the plot area background layer of the SVG plot.
+            derived().image_.g(PLOT_WINDOW_BACKGROUND).clear();
+          }
+
+          template <class Derived>
+         void axis_plot_frame<Derived>::clear_legend()
+          { //! Clear the legend layer of the SVG plot.
+            derived().image_.g(PLOT_LEGEND_BACKGROUND).clear();
+            derived().image_.g(PLOT_LEGEND_POINTS).clear();
+            derived().image_.g(PLOT_LEGEND_TEXT).clear();
+          }
+
+          template <class Derived>
+         void axis_plot_frame<Derived>::clear_x_axis()
+          { //! Clear the X axis layer of the SVG plot.
+            derived().image_.g(PLOT_X_AXIS).clear();
+            derived().image_.g(PLOT_X_MINOR_TICKS).clear();
+            derived().image_.g(PLOT_X_MAJOR_TICKS).clear();
+            derived().image_.g(PLOT_X_LABEL).clear();
+            derived().image_.g(PLOT_X_TICKS_VALUES).clear();
+          }
+
+          template <class Derived>
+         void axis_plot_frame<Derived>::clear_y_axis()
+          { //! Clear the Y axis layer of the SVG plot.
+            derived().image_.g(PLOT_Y_AXIS).clear();
+            derived().image_.g(PLOT_Y_MINOR_TICKS).clear();
+            derived().image_.g(PLOT_Y_MAJOR_TICKS).clear();
+            derived().image_.g(PLOT_Y_LABEL).clear();
+          }
+
+          template <class Derived>
+          void axis_plot_frame<Derived>::clear_grids()
+          { //! Clear the  grids layer of the SVG plot.
+            derived().image_.g(PLOT_X_MAJOR_GRID).clear();
+            derived().image_.g(PLOT_X_MINOR_GRID).clear();
+            derived().image_.g(PLOT_Y_MAJOR_GRID).clear();
+            derived().image_.g(PLOT_Y_MINOR_GRID).clear();
+          }
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::transform_point(double& x, double& y)
+        { //! Scale & shift both X & Y to graph Cartesian coordinates.
+          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.
+        }
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::transform_point(double& x, double& y);
+        // Protected Member Functions Definitions in axis_plot_frame.ipp:
+        // 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?
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::transform_x(double& x)
+        { //! Scale and shift X value only.
+          x = derived().x_scale_ * x + derived().x_shift_;
+        }
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::transform_y(double& y)
+        { //! Scale and shift Y value only.
+          y = derived().y_scale_ * y + derived().y_shift_;
+        }
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::draw_x_minor_tick(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 x(value); // Tick position and tick value label,
+          transform_x(x); // Convert to svg.
+          double y_bottom(0.); // Start on the horizontal X-axis line.
+          double y_top(derived().image_.y_size()); // Image top.
+
+          // Draw the minor grid, if wanted.
+          if(derived().x_ticks_.minor_grid_on_)
+          {
+            if(!derived().plot_window_on_)
+            { // Use whole image.
+              // Make space for title and X-axis labels.
+              if(derived().title_on_)
+              { // Allow text_margin_ * font_size around text (pixels).
+                y_bottom += derived().title_info_.textstyle().font_size() * derived().text_margin_;
+              }
+              if(derived().x_axis_.label_on_)
+              {
+                y_top -= derived().x_label_info_.textstyle().font_size() * derived().text_margin_;
+              }
+            }
+            else
+            { // plot_window_on_ == true.
+              y_bottom = derived().plot_top_ + derived().plot_window_border_.width_; // Top.
+              y_top = derived().plot_bottom_ - derived().plot_window_border_.width_; // Bottom. Ensure *inside* window.
+            }
+            // Make sure that we are drawing inside the allowed window.
+            if((x >= derived().plot_left_) && (x <= derived().plot_right_)) // allow = too?
+            {
+              //std::cerr << "Writing draw_x_minor_tick grid inside plot window: x = "
+              //  << x << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
+              grid_path.M(x, y_bottom).L(x, y_top); // Draw grid line.
+            }
+            else
+            { // This will happen but is designed to be ignored!
+              // See comment in draw_x_axis
+              // std::cerr << "Writing draw_x_minor_tick grid OUTside plot window: x = "
+              //  << x << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
+            }
+          } // x_minor_grid
+
+          // Draw x minor ticks.
+          if (derived().x_ticks_.ticks_on_window_or_on_axis_ < 0)
+          { // Put minor ticks on the plot window border bottom.
+            y_bottom = derived().plot_bottom_; // on the window line.
+            y_top = derived().plot_bottom_; // y_bottom = upper, y_top = lower end of tick.
+          }
+          else if (derived().x_ticks_.ticks_on_window_or_on_axis_ > 0)
+          { // Put minor ticks on the plot window border top.
+            y_bottom = derived().plot_top_; // on the window line.
+            y_top = derived().plot_top_; // y_bottom = upper, y_top = lower end of tick.
+          }
+          else // derived().x_ticks_.ticks_on_window_or_on_axis_ == 0
+          { // Internal style, draw tick up and/or down from the X-axis line.
+            y_bottom = derived().x_axis_.axis_; // ON X-axis horizontal line.
+            y_top = derived().x_axis_.axis_;
+          }
+          if(derived().x_ticks_.up_ticks_on_)
+          {
+            y_bottom -= derived().x_ticks_.minor_tick_length_; // up
+          }
+          if (derived().x_ticks_.down_ticks_on_)
+          {
+            y_top += derived().x_ticks_.minor_tick_length_; // down.
+          }
+         // Make sure that we are drawing inside the allowed window.
+          if((x >= derived().plot_left_) && (x <= derived().plot_right_)) // TODO allow < or <=
+          {
+            tick_path.M(x, y_bottom).L(x, y_top);
+            // No value labels on minor ticks, at present.
+          }
+          else
+          { // This will happen but is designed to be ignored!
+            // See comment in draw_x_axis
+            //std::cerr << "Writing draw_x_minor_tick OUTside plot window: x = "
+            // << x << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
+          }
+        } // void draw_x_minor_tick
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::draw_x_major_tick(double value, path_element& tick_path, path_element& grid_path)
+        { //! Draw major ticks - and grid too if wanted.
+          //! If major_value_labels_side then value shown beside the major tick.
+          double x(value); //
+          transform_x(x); // x value in svg.
+          if((x < derived().plot_left_ - 0.01) || (x > derived().plot_right_ + 0.01))
+          // Allow a bit extra to allow for round-off errors.
+          { // tick value is way outside plot window, so nothing to do.
+            //std::cout << derived().plot_left_ << ' '<< x << std::endl;
+            // This *was* displayed for a plot.
+            return;
+          }
+          double y_up(0.); // upper end of tick.
+          double y_down(derived().image_.x_size()); // y_down = lower end of tick.
+          if(derived().x_ticks_.major_grid_on_)
+          { // Draw major grid vertical line.
+            if(!derived().plot_window_on_)
+            { // Allow a modest margin around text of title and X-axis labels, if in use.
+              if(derived().title_on_)
+              {
+                y_up += derived().title_info_.textstyle().font_size() * derived().text_margin_;
+              }
+              if(derived().x_ticks_.major_value_labels_side_ != 0)
+              { // Value may be shown either side the major tick.
+                y_down -= derived().x_label_info_.textstyle().font_size() * derived().text_margin_;
+              }
+            }
+            else
+            { // plot_window_on_ == true
+              y_up = derived().plot_top_; // Bottom of plot window.
+              y_down = derived().plot_bottom_; // Top of plot window.
+            }
+            //if((y_down <= derived().plot_bottom_) && (y_up >= derived().plot_top_) && (x >= derived().plot_left_) && (x <= derived().plot_right_))
+            //{ // Make sure that we are drawing inside the allowed window.
+              grid_path.M(x, y_up).L(x, y_down); // 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((x >= derived().plot_left_) && (x <= derived().plot_right_)) // now <=
+          //{ Removed these checks as round off causes trouble.
+            double x_tick_length = derived().x_ticks_.major_tick_length_;
+            if(derived().x_ticks_.ticks_on_window_or_on_axis_ < 0)
+            { // Put the ticks on the plot window border (was external).
+              y_up = derived().plot_bottom_; // on the window line.
+              y_down = derived().plot_bottom_; // y_up = upper, y_down = lower.
+              if(derived().x_ticks_.up_ticks_on_)
+              {
+                y_up -= x_tick_length; // up
+              }
+              if (derived().x_ticks_.down_ticks_on_)
+              {
+                y_down += x_tick_length; // down.
+              }
+            }
+            else if(derived().x_ticks_.ticks_on_window_or_on_axis_ > 0)
+            { // Put the ticks on the plot window border (was external).
+              y_up = derived().plot_top_; // on the window line.
+              y_down = derived().plot_top_; // y_up = upper, y_down = lower.
+              if(derived().x_ticks_.up_ticks_on_)
+              {
+                y_up -= x_tick_length; // up
+              }
+              if (derived().x_ticks_.down_ticks_on_)
+              {
+                y_down += x_tick_length; // down.
+              }
+            }
+            else
+            { // Draw tick from the central X axis line (Internal_style).
+              y_up = derived().x_axis_.axis_; // X-axis line.
+              y_down = derived().x_axis_.axis_;
+              if(derived().x_ticks_.up_ticks_on_)
+              {
+                y_up -=  x_tick_length; // up
+              }
+              if (derived().x_ticks_.down_ticks_on_)
+              {
+                y_down += x_tick_length; // down.
+              }
+            }
+            tick_path.M(x, y_up).L(x, y_down);
+            // Leaving current position at the bottom end of the tick.
+            // y_up and y-down are the ends of the tick.
+            // These may be on the axis line, or the plot window.
+
+            if(derived().x_ticks_.major_value_labels_side_ != 0)
+            { // Show a value by the horizontal X-axis tick as "1.2" or "3.4e+000"...
+              std::stringstream tick_value_label;
+              tick_value_label.precision(derived().x_ticks_.value_precision_);
+              tick_value_label.flags(derived().x_ticks_.value_ioflags_);
+              tick_value_label << value; // for tick "4", "1.2" or "3.4e+000"...
+              if (derived().x_ticks_.strip_e0s_)
+              { // Remove unecessary e, +, leadings 0s.
+                std::string v = strip_e0s(tick_value_label.str());
+                tick_value_label.str(v);
+              }
+              double y = 0; // Where to start writing from, at end of bottom or top tick, if any.
+              // = 0 is only to avoid unitialised warning.
+              align_style alignment = center_align;
+              // Adjustments to provide space from end of tick before or after writing label.
+              if (derived().x_ticks_.label_rotation_ == upward) // vertical writing up.
+              {  // Shift to center value digits and minus sign on tick.
+                x += derived().x_value_label_style_.font_size() * 0.2;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom, so start a little below y_down.
+                  y = y_down + derived().x_value_label_style_.font_size() * 0.6;
+                  alignment = right_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little above y_up.
+                  y = y_up - derived().x_value_label_style_.font_size() * 0.5;
+                  alignment = left_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == downward)
+              {  // Should handle other directions too.
+                x -= derived().x_value_label_style_.font_size() * 0.3;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom, so start a little below y_down.
+                  y = y_down + derived().x_value_label_style_.font_size() * 0.5;
+                  alignment = left_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little above y_up.
+                  y = y_up - derived().x_value_label_style_.font_size() * 0.5;
+                  alignment = right_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == steepup)
+              {  // Should handle other directions too.
+                x -= derived().x_value_label_style_.font_size() * 0.3;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels upward, so start a little below y_down.
+                  y = y_down + derived().x_value_label_style_.font_size() * 0.5;
+                  alignment = left_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little above y_up.
+                  y = y_up - derived().x_value_label_style_.font_size() * 0.5;
+                  alignment = right_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == uphill)
+              { // Assume some 45 slope, so need about sqrt(2) less space.
+                x += derived().x_value_label_style_.font_size() * 0.5;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom, so start a little to bottom of y_bottom.
+                  y = y_down + derived().x_value_label_style_.font_size() * sin45;
+                  // Seems to need a bit more space for top than bottom if rotated.
+                  alignment = right_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little to top of y_top.
+                  y = y_up - derived().x_value_label_style_.font_size() * 0.3;
+                  alignment = left_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == slopeup)
+              { // Assume for 30 degree slope, need about sqrt(2) less space.
+                x += derived().x_value_label_style_.font_size() * 0.5;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom, so start a little to bottom of y_bottom.
+                  y = y_down + derived().x_value_label_style_.font_size() * sin45;
+                  // Seems to need a bit more space for top than bottom if rotated.
+                  alignment = right_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little to top of y_top.
+                  y = y_up - derived().x_value_label_style_.font_size() * 0.2;
+                  alignment = left_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == downhill)
+              { // Assume some 45 slope, so need about sqrt(2) less space.
+                x -= derived().x_value_label_style_.font_size() * 0.3;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom, so start a little to bottom of y_down.
+                  y = y_down + derived().x_value_label_style_.font_size() * 0.7;
+                  // Seems to need a bit more space for top than bottom if rotated.
+                  alignment = left_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little to top of y_up.
+                 y = y_up - derived().x_value_label_style_.font_size() * 0.3;
+                  alignment = right_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == slopedownhill)
+              { // Assume some 30 slope, so need about sqrt(2) less space.
+                x -= derived().x_value_label_style_.font_size() * 0.3;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom, so start a little to bottom of y_down.
+                  y = y_down + derived().x_value_label_style_.font_size() * 0.7;
+                  // Seems to need a bit more space for top than bottom if rotated.
+                  alignment = left_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little to top of y_up.
+                 y = y_up - derived().x_value_label_style_.font_size() * 0.3;
+                  alignment = right_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == steepdown)
+              {  // Should handle other directions too.
+                x -= derived().x_value_label_style_.font_size() * 0.3;
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom, so start a little below y_down.
+                  y = y_down + derived().x_value_label_style_.font_size() * 0.5;
+                  alignment = left_align;
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little above y_up.
+                  y = y_up - derived().x_value_label_style_.font_size() * 0.5;
+                  alignment = right_align;
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == horizontal)
+              { // Tick value label on X-axis is normal default horizontal.
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { // labels to bottom of tick, so start a little below bottom of y_down.
+                  y = y_down + derived().x_value_label_style_.font_size() * 1.3; // 1.3 allows 1/3 font space.
+                  alignment = center_align; // center on the tick.
+                }
+                else if(derived().x_ticks_.major_value_labels_side_ > 0)
+                { // labels to top, so start a little to top of y_up.
+                 y = y_up - derived().x_value_label_style_.font_size() * 0.7;
+                  alignment = center_align;
+                }
+              }
+              else
+              { // upsidedown, backup... - can't see any conceivable use for these.
+                return; // Others not yet implemented.
+              } // rotations
+              if (x <= 0)
+              { // Sanity checks on svg coordinates.
+                throw std::runtime_error("X-tick X value wrong!");
+              }
+              if (y <= 0)
+              {
+                throw std::runtime_error("X-tick Y value wrong!");
+              }
+              // Draw the X ticks value labels, "1", "2" "3" ...
+              if(derived().x_ticks_.ticks_on_window_or_on_axis_ != 0)
+              { // External to plot window style bottom or top.
+                // Always want all values including "0", if labeling external to plot window.
+                // x_ticks_.ticks_on_window_or_on_axis_ == true != 0
+                derived().image_.g(detail::PLOT_X_TICKS_VALUES).text(
+                  x,
+                  y,
+                  tick_value_label.str(),
+                  derived().x_value_label_info_.textstyle(), // font, size etc
+                  alignment, derived().x_ticks_.label_rotation_);
+              }
+              else
+              {
+                if ((value != 0) && derived().x_axis_.axis_line_on_)
+                { // Avoid a "0" below the X-axis if it would be cut through by any internal vertical Y-axis line.
+                  derived().image_.g(detail::PLOT_X_TICKS_VALUES).text(
+                    x,
+                    y,
+                    tick_value_label.str(),
+                    derived().x_value_label_info_.textstyle(), // font, size etc
+                    alignment,
+                    derived().x_ticks_.label_rotation_);
+                }
+              } // on plot window or 'on axis'.
+          }
+          else
+          { // Outside plot window - so do nothing?  Warning?
+            //std::cerr << "Writing draw_x_major_tick OUTside plot window: "
+            //  "x = " << x << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
+          }
+        } // draw_x_major_tick
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::draw_x_axis()
+        { //! Draw horizontal X-axis line & plot window line to hold, and ticks and grids.
+          if(derived().x_axis_.axis_line_on_)
+          { // Want a horizontal X-axis line drawn.
+            double xleft = derived().plot_left_;
+            double xright = derived().plot_right_;
+            if (derived().x_axis_position_ == x_intersects_y)
+            { // Draw the horizontal X-axis line the full width of the plot window,
+              // perhaps including an addition in lieu of a major tick.
+              if (derived().y_ticks_.left_ticks_on_)
+              {
+                if (derived().y_ticks_.ticks_on_window_or_on_axis_ < 0) // left
+                { // Extend the horizontal line left in lieu of longest tick.
+                  xleft -= (std::max)(derived().y_ticks_.minor_tick_length_, derived().y_ticks_.major_tick_length_);
+                }
+              }
+              else if (derived().y_ticks_.right_ticks_on_)
+              {
+                if (derived().y_ticks_.ticks_on_window_or_on_axis_ > 0) // right
+                { // Extend the horizontal X-axis line right in lieu of longest tick.
+                  xright += (std::max)(derived().y_ticks_.minor_tick_length_, derived().y_ticks_.major_tick_length_);
+                }
+              }
+              double y = derived().x_axis_.axis_; // y = 0, (provided y range includes zero).
+              derived().image_.g(PLOT_X_AXIS).line(xleft, y, xright, y);
+              if (derived().x_ticks_.ticks_on_window_or_on_axis_ < 0) // bottom
+              { // Draw a vertical line holding the ticks on the top of plot window.
+                derived().image_.g(PLOT_X_AXIS).line(xleft, derived().plot_bottom_, xright, derived().plot_bottom_);
+              }
+              else if (derived().x_ticks_.ticks_on_window_or_on_axis_ > 0)  // top
+              {// Draw a vertical line holding the ticks on the bottom of plot window.
+                derived().image_.g(PLOT_X_AXIS).line(xleft, derived().plot_top_, xright, derived().plot_top_);
+              }
+            }
+            else if (derived().x_axis_position_ == top)
+            {
+               derived().image_.g(PLOT_X_AXIS).line(xleft, derived().plot_top_, xright, derived().plot_top_);
+            }
+            else if (derived().x_axis_position_ == bottom)
+            {
+               derived().image_.g(PLOT_X_AXIS).line(xleft, derived().plot_bottom_, xright, derived().plot_bottom_);
+            }
+            else
+            { // warn that things have gone wrong?
+            }
+          } // x_axis_.axis_line_on_
+
+          // Access the paths for the ticks & grids, ready for additions.
+          path_element& minor_tick_path = derived().image_.g(PLOT_X_MINOR_TICKS).path();
+          path_element& major_tick_path = derived().image_.g(PLOT_X_MAJOR_TICKS).path();
+          path_element& minor_grid_path = derived().image_.g(PLOT_X_MINOR_GRID).path();
+          path_element& major_grid_path = derived().image_.g(PLOT_X_MAJOR_GRID).path();
+
+          // x_minor_jump is the interval between minor ticks.
+          double x_minor_jump = derived().x_ticks_.major_interval_ /
+            (derived().x_ticks_.num_minor_ticks_ + 1.);
+
+          // Draw the ticks on the positive side (right of zero).
+          for(double x = 0.; x <= derived().x_axis_.max_; x += derived().x_ticks_.major_interval_)
+          {
+            for(double j = x + x_minor_jump;
+              j < (x + derived().x_ticks_.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_tick.
+              // 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_tick(j, minor_tick_path, minor_grid_path);
+            } // for j
+            if ((x != 0. || !derived().y_axis_.axis_line_on_) || (derived().x_ticks_.ticks_on_window_or_on_axis_ != 0))
+            { // 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_tick(x, major_tick_path, major_grid_path);
+            }
+          }
+
+          // Draw the ticks on the negative side (left of zero).
+          for(double x = 0.; x >= derived().x_axis_.min_; // ?? * (1. + 2 * std::numeric_limits<double>::epsilon());
+            x -= derived().x_ticks_.major_interval_) // Want a close to test here?
+          {
+            // Draw minor ticks.
+            for(double j = x - x_minor_jump;
+              j > (x - derived().x_ticks_.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().y_axis_.axis_line_on_)  || (derived().x_ticks_.ticks_on_window_or_on_axis_ != 0))
+              { // 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_tick(j, minor_tick_path, minor_grid_path);
+              }
+            }
+            if ((x != 0. || !derived().y_axis_.axis_line_on_) || (derived().x_ticks_.ticks_on_window_or_on_axis_ != 0))
+            { // 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_tick(x, major_tick_path, major_grid_path);
+            }
+          }
+        } // void draw_x_axis()
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::draw_x_axis_label()
+        { //! Draw the X-axis label text (for example, length),
+          //! and append any optional units (for example, km).
+          // X-label color default is set in constructor thus:
+          // image_.g(detail::PLOT_X_LABEL).style().stroke_color(black);
+          // and changed using x_label_color(color);
+          // Similarly for font family and size etc (must be same for both label and units).
+
+          std::string x_label = derived().x_label_info_.text(); // x_axis_ label, and optional units.
+          if (derived().x_axis_.label_units_on_ && (derived().x_units_info_.text() != ""))
+          { // Append the units, if any, user providing brackets () if required.
+            x_label += derived().x_units_info_.text(); // for example: "time (sec)".
+          }
+
+          double y = derived().plot_bottom_;
+          // Glyphs for western characters are aligned with the left bottom of capital letter,
+          // so need to allow 1/3 more below for any descenders.
+
+          // cout << "derived().x_ticks_.ticks_on_window_or_on_axis_ " << derived().x_ticks_.ticks_on_window_or_on_axis_ << endl;
+          // using derived(0 means debugging doesn't work!  So resort to old-fashioned print statements.
+          if (derived().x_ticks_.ticks_on_window_or_on_axis_ < 0) // -1 means ticks on bottom of plot window.
+          { // Ticks value labels below plot window.
+            if (derived().x_ticks_.major_value_labels_side_ < 0) // bottom
+            { // Shift down to allow for any tick value labels.
+              if ((derived().x_ticks_.label_rotation_ == downward) || (derived().x_ticks_.label_rotation_ == upward))
+              { // downward tick value label direction 90 up or down.
+                y += derived().x_ticks_.label_max_space_;
+                if (derived().x_ticks_.down_ticks_on_ == true)
+                {  // Move down for any downward ticks.
+                  y += 1.1 * (std::max)(derived().x_ticks_.major_tick_length_, derived().x_ticks_.minor_tick_length_); // And avoid macro max trap!
+                  // and a small space.
+                  y += 0.7 * (derived().x_label_info_.textstyle().font_size() + derived().x_value_label_info_.textstyle().font_size()); // best compromise?
+                }
+              }
+              else if ((derived().x_ticks_.label_rotation_ == steepdown) || (derived().x_ticks_.label_rotation_ == steepup))
+              { // downward tick value label direction 60 up or down.
+                y += derived().x_ticks_.label_max_space_;
+                if (derived().x_ticks_.down_ticks_on_ == true)
+                {  // Move down for any downward ticks.
+                  y += 1.1 * (std::max)(derived().x_ticks_.major_tick_length_, derived().x_ticks_.minor_tick_length_); // And avoid macro max trap!
+                  // and a small space.
+                  y += 0.5 * (derived().x_label_info_.textstyle().font_size() + derived().x_value_label_info_.textstyle().font_size()); // best compromise?
+                }
+              }
+              else if ((derived().x_ticks_.label_rotation_ == uphill)  || (derived().x_ticks_.label_rotation_ == downhill))
+              { // sloping 45 degrees up or down.
+                y += derived().x_ticks_.label_max_space_ * sin45; // Move down from end of tick.
+                if (derived().x_ticks_.down_ticks_on_ == true)
+                {  // Move down for any downward ticks.
+                  y += 1.1 * (std::max)(derived().x_ticks_.major_tick_length_, derived().x_ticks_.minor_tick_length_); // And avoid macro max trap!
+                  // and a small space.
+                  y += 0.7 * (derived().x_label_info_.textstyle().font_size() + derived().x_value_label_info_.textstyle().font_size()); // best compromise?
+                }
+              }
+              else if ((derived().x_ticks_.label_rotation_ == slopeup)  || (derived().x_ticks_.label_rotation_ == slopedownhill))
+              { // sloping 30 degrees.
+                y += derived().x_ticks_.label_max_space_ * sin45; // Move down from end of tick.
+                if (derived().x_ticks_.down_ticks_on_ == true)
+                {  // Move down for any downward ticks.
+                  y += 1.1 * (std::max)(derived().x_ticks_.major_tick_length_, derived().x_ticks_.minor_tick_length_); // And avoid macro max trap!
+                  // and a small space.
+                  y += 0.5 * (derived().x_label_info_.textstyle().font_size() + derived().x_value_label_info_.textstyle().font_size()); // best compromise?
+                }
+              }
+              else if (derived().x_ticks_.label_rotation_ == horizontal)
+              { // horizontal X ticks value labels (default).
+                if (derived().x_ticks_.major_value_labels_side_ < 0)
+                { //  Move down to allow space for font size of tick value labels below X-axis.
+                  y += derived().x_value_label_info_.textstyle().font_size() ;
+                }
+                y += derived().x_label_info_.textstyle().font_size() * 1.3; // Allow for the X-axis label font and space.
+                // See also 1.3 factor drawing ticks.
+              }
+              else
+              {
+                std::cout << " Rotation of X label rotation" << derived().x_ticks_.label_rotation_ << "not yet implemented!" << std::endl;
+              }
+            }
+            else if (derived().x_ticks_.major_value_labels_side_ > 0)
+            { // Tick labels above, only ticks below, so just move down for height of label font.
+              y += derived().x_label_info_.textstyle().font_size() * 1.3; // Allow for the X-axis label font and space.
+            }
+            else
+            { // derived().x_ticks_.major_value_labels_side_ == 0
+              // So no change for labels.
+              y += derived().x_label_info_.textstyle().font_size() * 1.3; // Allow for the X-axis label font and space.
+            }
+
+            if (derived().x_ticks_.down_ticks_on_)
+            { // Shift down for biggest of any ticks, and bit of space.
+              y += 1.1 * (std::max)(derived().x_ticks_.minor_tick_length_, derived().x_ticks_.major_tick_length_);
+            // y += derived().x_ticks_.value_label_style_.font_size() * 1.; // Shift down to suit tick labels?
+            }
+          }
+          else if (derived().x_ticks_.ticks_on_window_or_on_axis_ > 0)
+          {  // = +1 means ticks are on top of plot window.
+             // Shift down from plot window bottom to suit X-axis label.
+             y += derived().x_label_info_.textstyle().font_size() * 1.7;
+          }
+          else if (derived().x_ticks_.ticks_on_window_or_on_axis_ == 0)
+          { // Ticks are ON the X-axis line, so X label is just below the plot bottom.
+            // No space needed for ticks.
+             // Character starts at bottom of capital letter, so allow for descenders.
+             //y = derived().image_.y_size() - derived().image_border_width(); // Place X Label just above the image bottom.
+             //y -= derived().image_border_.margin_;
+             y += derived().x_label_info_.textstyle().font_size() * 1.7;
+          }
+
+          derived().image_.g(PLOT_X_LABEL).push_back(new text_element(
+            ( // x position relative to the x-axis which is middle of plot window.
+            derived().plot_right_ + derived().plot_left_) / 2,  // x coordinate - middle.
+            y, // Down from plot window.
+            x_label,
+            derived().x_label_info_.textstyle(),
+            center_align, horizontal)
+            );
+        } // void draw_x_axis_label()
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::adjust_limits(double& x, double& y)
+          { //! If value of a data point reaches limit of max, min, infinity,
+            //! use the appropriate plot min or max value instead.
+            if(detail::limit_max(x))
+            {
+              x = derived().plot_right_;
+            }
+            if(detail::limit_max(y))
+            {
+              y = derived().plot_top_;
+            }
+            if(detail::limit_min(x))
+            {
+              x = derived().plot_left_;
+            }
+            if(detail::limit_min(y))
+            {
+              y = derived().plot_top_;
+            }
+            // 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
+
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::draw_title()
+        { /*! Draw title (for the whole plot).
+            Update title_info_ with position.
+            Assumes align = center_align
+            Using center_align will ensure that title will center correctly
+            because the render engine does the centering.
+            (Even if the original string is made much longer because it contains Unicode,
+            Greek, math symbols etc, taking about 8 characters per symbol.
+            For example, the Unicode symbol for square root is "√" but takes only about one character width).
+          */
+          derived().title_info_.x(derived().image_.x_size() / 2.); // Center of image.
+          double y;
+          y = derived().title_info_.textstyle().font_size() * derived().text_margin_; // Leave a linespace above.
+          derived().title_info_.y(y);
+          derived().image_.g(PLOT_TITLE).push_back(new text_element(derived().title_info_));
+        } // void draw_title()
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::size_legend_box()
+        { //! Calculate how big the legend box needs to be.
+          if(derived().legend_on_ == false)
+          { // No legend wanted, so set values to show legend positions invalid?
+            //derived().legend_left_ = -1.;
+            //derived().legend_right_ = -1.;
+            //derived().legend_top_ = -1.;
+            //derived().legend_bottom_ = -1.;
+            derived().legend_height_ = 0.; // At least set the size to zero.
+            derived().legend_width_ = 0.;
+            return;
+          }
+          else
+          { // legend_on_ == true
+            // Work out the size the legend box needs to be to hold the
+            // header, markers, lines & text.
+            size_t num_series = derived().serieses_.size(); // How many data series.
+            int font_size = derived().legend_header_.textstyle().font_size();
+            int point_size =  derived().serieses_[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() != "");
+            //text_element legend_header_; // legend box header or title (if any).
+            //text_style legend_style_;
+            double longest = string_svg_length(derived().legend_header_.text(), derived().legend_style_);
+            //std::cout << "\nLegend header " << longest << " svg units." << std::endl;
+            derived().legend_width_ = 2 * (derived().legend_box_.margin() * derived().legend_box_.width());
+            // Don't plan to write on either side border, or on the 'forbidden' margins of the box.
+            for(size_t i = 0; i < num_series; ++i)
+            { // Find the longest text (if longer than header) in all the data series.
+              std::string s = derived().serieses_[i].title_;
+              double siz = string_svg_length(s, derived().legend_style_);
+              if (siz > longest)
+              {
+                longest = siz;
+              }
+            } // for
+            // std::cout << "\nLongest legend header or data descriptor " << longest << " svg units." << std::endl;
+            derived().legend_width_ += longest * 0.8; // Space for longest text.
+            // Kludge factor to allow for not knowing the real length.
+
+            // Allow width for a leading space, and trailing
+              derived().legend_width_ += spacing * 2.5;
+
+            // & trailing space before box margin.
+            // if (derived().serieses_[i].line_style_.line_on_) // line joining points.
+            if (derived().legend_lines_)
+            { // Add for colored line marker in legend.
+              derived().legend_width_ += spacing * 1.5;
+            }
+            if(derived().serieses_[0].point_style_.shape() != none)
+            { // Add for any colored data point marker, cross, round... & space.
+              derived().legend_width_ += 1.5 * derived().serieses_[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_header_.text() != "") )
+            {
+              derived().legend_height_ += 2 * font_size; // text & space after.
+            }
+            derived().legend_height_ += num_series * spacing * 2; // Space for the data point symbols & text.
+          } // legend_on_ == true
+
+         //std::cout << "Legend width " << derived().legend_width_ << ", height " << derived().legend_height_ << std::endl;
+        } //  void size_legend_box()
+
+        template <class Derived>
+        void axis_plot_frame<Derived>::place_legend_box()
+        { //! Place legend box (if required).
+          if(derived().legend_on_ == true) // Legend box required.
+          {
+            derived().outside_legend_on_ = true; // Unless proves to be inside.
+            //double spacing = derived().legend_box_.margin(); // Might be better to use this, but needs redoing.
+            double spacing = derived().y_axis_label_style_.font_size() * 1.; // Around any legend box - beyond any border.
+            switch (derived().legend_place_)
+            {
+            case nowhere:
+              return; // Actually places it at (0, 0), probably overwriting the plot.
+            case somewhere:
+              // Assume legend_top_left will place it somewhere where there is nothing else.
+               //derived().legend_left_; set by legend_top_left
+               //derived().legend_top_;
+               derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
+               derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+               break;
+            case inside:
+              derived().outside_legend_on_ = false;
+              if (derived().legend_left_ == -1)
+              { // Legend box position NOT been set by legend_top_left.
+                // Default inside position is top left level with plot window.
+              derived().legend_left_ = derived().image_border_.width_ + derived().image_border_.margin_; // left image edge + space.
+              derived().plot_left_ += derived().legend_width_ + spacing; // Push plot window right same amount to make room,
+              derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+              derived().legend_top_ = derived().plot_top_; // Level with top of plot window.
+              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: // Default legend position is outside_right,
+              // so that it isn't too close to the image edge or the plot window.
+              derived().plot_right_ -= derived().legend_width_ + spacing; // Narrow plot window from right.
+              derived().legend_left_ = derived().plot_right_  + spacing; // plot + border.
+              derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+              derived().legend_top_ = derived().plot_top_; // Level with top of plot window.
+              derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
+              break;
+            case outside_left:
+              derived().plot_left_ += derived().legend_width_ + spacing /2 ; // Push plot window right same amount to make room,
+              derived().legend_left_ = derived().image_border_.width_ + derived().image_border_.margin_; // left image edge + space.
+              derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+              derived().legend_top_ = derived().plot_top_; // Level with top of plot window.
+              derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
+             break;
+            case outside_top:
+              // Centered.
+               derived().legend_left_ = derived().image_.x_size() / 2. - derived().legend_width_ / 2; // Center.
+               derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+               derived().plot_top_ += derived().legend_height_ + spacing;
+               derived().legend_top_ = derived().title_info_.y() + derived().title_font_size() * derived().text_margin_;
+               derived().legend_top_ += spacing;
+               derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
+              break;
+            case outside_bottom:
+               // Centered.
+               derived().legend_bottom_ = derived().image_.y_size();
+               derived().legend_bottom_ -= (derived().image_border_.width_ + derived().image_border_.margin_); // up
+               derived().legend_top_ = derived().legend_bottom_ - derived().legend_height_;
+               derived().legend_left_ = derived().image_.x_size()/  2. - derived().legend_width_ / 2; // Center.
+               derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+               derived().plot_bottom_ = derived().legend_top_;
+               derived().plot_bottom_ -= 2 * spacing;
+              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;
+              }
+
+               derived().image_.g(detail::PLOT_LEGEND_BACKGROUND)
+              .style().fill_color(derived().legend_box_.fill()) //
+              .stroke_color(derived().legend_box_.stroke())
+              .stroke_width(derived().legend_box_.width())
+              .stroke_on(derived().legend_box_.border_on())
+              ;
+
+              // Draw border box round legend.
+              g_element* g_ptr = &(derived().image_.g(PLOT_LEGEND_BACKGROUND));
+              g_ptr->push_back(new
+                rect_element(derived().legend_left_, derived().legend_top_, derived().legend_width_, derived().legend_height_));
+            } // if legend_on_
+          } //  void calculate_legend_box()
+
+          template <class Derived>
+          void axis_plot_frame<Derived>::draw_legend()
+          { //! Draw the legend border, text header (if any) and marker lines and/or shapes.
+            // size_t num_points = derived().series.size();
+            // cout << derived().legend_box_.width() <<  ' ' << derived().legend_box_.margin() << endl;
+
+            int font_size = derived().legend_header_.textstyle().font_size();
+            int point_size =  derived().serieses_[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() != "");
+
+           // Assume legend box position has already been sized and positioned by function 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_.g(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 for example: "My Plot Legend".
+              derived().legend_header_.x(legend_x_start + legend_width / 2.); // / 2. to center in legend box.
+              // Might be better to use center_align here because will fail if legend contains symbols in Unicode.
+              derived().legend_header_.y(legend_y_pos);
+              derived().image_.g(PLOT_LEGEND_TEXT).push_back(new text_element(derived().legend_header_));
+              legend_y_pos += 2 * spacing; // Might be 1.5? - useful if many series makes the box too tall.
+            }
+
+            g_ptr = &(derived().image_.g(PLOT_LEGEND_POINTS));
+            g_element* g_inner_ptr = g_ptr;
+            g_inner_ptr = &(derived().image_.g(PLOT_LEGEND_TEXT));
+
+            for(unsigned int i = 0; i < derived().serieses_.size(); ++i)
+            { // Show point marker, perhaps line, & text info for each of the data series.
+
+              // cout << "Series " << i << endl;
+              // derived().serieses_[i].point_style_ << endl;
+              // cout << derived().serieses_[i].line_style_ << endl;
+
+              double legend_x_pos = legend_x_start;
+              legend_x_pos += spacing; // space before point marker and/or line & text.
+              g_inner_ptr = &(g_ptr->add_g_element());
+              // Use both stroke & fill colors from the points' style.
+              // Applies to both shape AND line.
+              g_inner_ptr->style().stroke_color(derived().serieses_[i].point_style_.stroke_color_);
+              g_inner_ptr->style().fill_color(derived().serieses_[i].point_style_.fill_color_);
+              g_inner_ptr->style().stroke_width(derived().serieses_[i].line_style_.width_);
+
+              //cout << "g_inner_ptr.style().stroke_color() " << g_inner_ptr->style() << endl;
+              plot_point_style& sty = derived().serieses_[i].point_style_;
+
+              if(sty.shape_ != none)
+              { // Is some data point marker shape to show in legend box.
+                bool was_unc_ellipse = false;
+                if (sty.shape_ == unc_ellipse)
+                {  // Problem here with unc_ellipse with calculation of a suitable size
+                   // and also, more fundamentally, the legend box overwrites the PLOT_DATA_UNC layers,
+                   // so as a hack, use a round or circlet instead.
+                  sty.shape_ =  circlet;
+                  was_unc_ellipse = true; // Note so restore after showing circle.
+                }
+
+                draw_plot_point( // Show a plot point like circlet (==round), square, vertical bar...
+                  legend_x_pos,
+                  legend_y_pos,
+                  *g_inner_ptr,
+                  sty, unc<false>(), unc<false>());
+                  //was derived().serieses_[i].point_style_, unc(0.), unc(0.));
+                legend_x_pos += 1.5 * spacing;
+                if (was_unc_ellipse)
+                { // Restore (or the data points won't use the unc_ellipse!
+                  sty.shape_ = unc_ellipse;
+                }
+              }
+
+              // Line markers are only really useful for 2-D lines and curves showing functions.
+              if (derived().legend_lines_)
+              { // Need to draw a short line to show color for that data series.
+                  // Line joining points option is true.
+                  if (derived().serieses_[i].line_style_.line_on_ || derived().serieses_[i].line_style_.bezier_on_)
+                  { // Use stroke color from line style.
+                     g_inner_ptr->style().stroke_color(derived().serieses_[i].line_style_.stroke_color_);
+                  }
+                  else
+                  { // Use point stroke color instead.
+                    g_inner_ptr->style().stroke_color(derived().serieses_[i].point_style_.stroke_color_); // OK with 1D
+                  }
+                  //std::cout << "line g_inner_ptr->style().stroke_color() " << g_inner_ptr->style().stroke_color() << std::endl;
+
+                  g_inner_ptr->push_back(new line_element( // Draw horizontal lines with appropriate color.
+                    legend_x_pos,
+                    legend_y_pos,
+                    legend_x_pos + spacing, // Line sample is one char long.
+                    legend_y_pos));
+                  legend_x_pos += 1.5 * spacing; // Total is short line & a space.
+              } // legend_lines_
+
+              // Legend text for each Data Series added to the plot.
+              g_inner_ptr = &(derived().image_.g(PLOT_LEGEND_TEXT));
+              g_inner_ptr->push_back(new text_element(
+                legend_x_pos, // allow space for the marker.
+                legend_y_pos,
+                derived().serieses_[i].title_, // Text for this data series.
+                derived().legend_header_.textstyle(),
+                left_align));
+              legend_y_pos += 2 * spacing;
+            } // for
+          } // void draw_legend()
+
+          template <class Derived>
+          void axis_plot_frame<Derived>::draw_plot_point(double x, double y, // X and Y values (in SVG coordinates).
+            g_element& g_ptr,
+            plot_point_style& sty,
+            unc<false> ux, unc<false> uy) // Default unc ux = 0. and uy = 0. ?
+          { /*! Draw a plot data point marker shape
+              whose size and stroke and fill colors are specified in plot_point_style,
+              possibly including uncertainty ellipses showing multiples of standard deviation.
+            */
+            /*
+              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.
+            */
+            int size = sty.size_;
+            double half_size = size / 2.;
+            //cout << "point style() "<< sty.style() << endl;
+            // Whatever shape, text or line, want to use the point style.
+            g_ptr.style().stroke_color(sty.stroke_color_);
+            g_ptr.style().fill_color(sty.fill_color_);
+
+            //cout << "g_ptr.style() " << g_ptr.style() << endl;
+
+            switch(sty.shape_) // from enum point_shape none, round, square, point, egg
+            {
+            case circlet:
+              g_ptr.circle(x, y, (int)half_size);
+              break;
+
+            case point:
+              g_ptr.circle(x, y, 1); // Fixed size round.
+              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;
+
+            case unc_ellipse:
+              { // std_dev horizontal (and, for 2D, vertical) ellipses for one, two and three standard deviations.
+                double xu = ux.value(); //
+                if (ux.std_dev() > 0)
+                { // std_dev is meaningful.
+                  xu +=  ux.std_dev();
+                }
+                transform_x(xu); // To SVG coordinates.
+                double x_radius = abs(xu - x);
+                if (x_radius <= 0.)
+                { // Make sure something is visible.
+                  x_radius = 1.; // Or size?
+                }
+
+                double yu = uy.value();
+                if (uy.std_dev() > 0)
+                { // std_dev is meaningful.
+                   yu += uy.std_dev();
+                }
+
+                transform_y(yu);
+                double y_radius = abs(yu - y);
+                if (y_radius <= 0.)
+                { // Make sure something is visible.
+                  y_radius = 1.;
+                }
+                //image_.g(PLOT_DATA_UNC).style().stroke_color(magenta).fill_color(pink).stroke_width(1);
+                // color set in svg_1d_plot         data at present.
+                g_element* gu3_ptr = &(derived().image_.g(PLOT_DATA_UNC3));
+                g_element* gu2_ptr = &(derived().image_.g(PLOT_DATA_UNC2));
+                g_element* gu1_ptr = &(derived().image_.g(PLOT_DATA_UNC1));
+                gu1_ptr->ellipse(x, y, x_radius, y_radius); //  Radii are one standard deviation.
+                gu2_ptr->ellipse(x, y, x_radius * 2, y_radius * 2); //  Radii are two standard deviation..
+                gu3_ptr->ellipse(x, y, x_radius * 3, y_radius * 3); //  Radii are three standard deviation..
+                g_ptr.circle(x, y, 1); // Show x and y values at center using stroke and fill color of data point marker.
+              }
+              break;
+
+             // Offset from center is not an issue with vertical or horizontal ticks.
+
+            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(), sty.style(), center_align, horizontal); // symbol(s), size and centre.
+
+              // Unicode symbols that work on most browsers are listed at
+              // boost\math\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, "♦", sty.symbols_style_, center_align, horizontal);
+              // 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., "∗", sty.symbols_style_, center_align, horizontal);
+              // asterisk is black filled.
+              // size /3 puts the bottom tip on the X-axis.
+              break;
+            case lozenge:
+              g_ptr.text(x, y - size / 3., "◊", sty.symbols_style_, center_align, horizontal);
+              // 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, "♣", sty.symbols_style_, center_align, horizontal);
+              // x, y, puts club just on the X-axis
+              break;
+            case spade:
+              g_ptr.text(x, y, "♠", sty.symbols_style_, center_align, horizontal);
+              //
+              break;
+            case heart:
+              g_ptr.text(x, y , "♥", sty.symbols_style_, center_align, horizontal);
+              //
+              break;
+            case cone: // Pointing down triangle.
+              {
+                bool fill = (sty.fill_color() != blank);
+                g_ptr.triangle(x - half_size, y - size, x + half_size, y - size, x, y, fill);
+              // Last point puts the bottom tip of the triangle on the X-axis (may not be wanted for 2-D).
+              }
+              break;
+            case cross: // Not X.
+              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
+
+          template <class Derived>
+          void axis_plot_frame<Derived>::draw_plot_point_value(double x, double y, g_element& g_ptr, value_style& val_style, plot_point_style& point_style, Meas uvalue)
+          { /*!
+          void draw_plot_point_value(double x, double y, g_element& g_ptr, value_style& val_style, plot_point_style& point_style, unc<false> uvalue)
+             Write one data point (X or Y) value as a string, for example "1.23e-2",
+             near the data point marker.
+             Unecessary e, +, \& leading exponent zeros may optionally be stripped,
+             and the position and rotation controlled.
+             std_dev estimate, typically standard deviation
+             (half conventional 95% confidence 'plus or minus') may be optionally be appended.
+             Degrees of freedom estimate (number of replicates) may optionally be appended.
+             ID or name of point, order in sequence, and datetime may also be added.
+             For example: "3.45 +-0.1(10)"\n
+             The precision and format (scientific, fixed), and color and font type and size can be controlled too.
+             */
+            double value = uvalue.value(); // Most likely value or mean.
+            double sd = uvalue.std_dev(); // Standard deviation for value.
+            double df = uvalue.deg_free(); // Degrees of freedom estimate for value.
+            unsigned short int types = uvalue.types();  //  unctypes_
+            distribution_type distrib;
+            if (types & UNC_UNIFORM)
+            {
+              distrib = uniform;
+            }
+            else if (types & UNC_TRIANGULAR)
+            {
+              distrib = triangular;
+            }
+            else
+            { // Default.
+              distrib = gaussian;
+            }
+
+            // Extra info from Meas.
+            int order = uvalue.order_;
+            std::string label_id = uvalue.id_;
+            using boost::posix_time::ptime;
+            ptime dt = uvalue.time_;
+
+            std::stringstream label;
+            label.precision(val_style.value_precision_);
+            std::string stripped;
+            if (val_style.value_precision_ <= 0)
+            { // Use uncertainty to automatically control number of digits.
+              int m = round_m(derived().epsilon_, sd, derived().uncSigDigits_, distrib);
+              // Assume no need for stripping unecessary e, +, & leading exponent zeros.
+              stripped = round_ms(value, m);
+            }
+            else
+            { // Use user's chosen precision etc.
+              label.flags(val_style.value_ioflags_);
+              label << value; // "1.2" or "3.4e+001"...
+              stripped =  (derived().x_ticks_.strip_e0s_) ?
+                // Default is to strip unecessary e, +, & leading exponent zeros.
+                strip_e0s(label.str())  // "1.2" or "3.4e1"...
+                :
+              stripped = label.str();
+            }
+            if (val_style.prefix_ != "")
+            { // Want a prefix like "[" or "time = ".
+              stripped = val_style.prefix_ + stripped;
+            }
+            int marker_size = point_style.size_; // point marker size
+            int label_size = val_style.values_text_style_.font_size();
+            // Offset of value label from point must be related mainly to
+            // size of the data marker, less the value label font size.
+            // May need to combine these two?
+
+            rotate_style rot = val_style.value_label_rotation_;
+            // http://www.w3.org/TR/SVG/coords.html#RotationDefined
+            // transform="rotate(-45)" == uphill
+
+            align_style al; // = center_align;
+            switch (rot)
+            {
+            case horizontal: // OK
+              al = center_align;
+              y -= marker_size * 2;  // Up marker font size;
+              // center_align means no x correction.
+              break;
+            case leftward: // horizontal but to left of marker.
+              al = right_align;
+              x -= marker_size * 1.3;  // left
+              y += label_size * 0.3;  // down label font size;
+              rot = horizontal;
+              break;
+            case rightward: // horizontal but to right of marker.
+              al = left_align;
+              x += marker_size * 1.1;  // right
+              y += label_size * 0.3;  // down label font size;
+              rot = horizontal;
+              break;
+            case upsidedown: // OK but upsidedown so not very useful!
+              al = center_align;
+              y += marker_size;  // Down marker font size;
+             break;
+            case slopeup: // -30 - OK
+            case steepup: // -45 - OK
+            case uphill: // -60 - OK
+              al = left_align;
+              x += label_size /3;  // Right third label font size - centers on marker.
+              y -= marker_size * 0.6;  // UP marker font size;
+              break;
+            case upward: // -90 vertical writing up - OK.
+              al = left_align;
+              x += label_size /3;  // Right third label font size - centers on marker.
+              y -= marker_size * 0.9;  // Up marker font size;
+              break;
+            case backup: // OK
+              al = right_align;
+              x -= marker_size * 1.5;  // Left
+              y -= marker_size * 0.8;  // Up
+              rot = downhill;
+              break;
+
+            case  slopedownhill: // 30 gentle slope down.
+            case downhill: // 45 down.
+            case steepdown: //  60 steeply down.
+             al = left_align;
+              x += marker_size * 0.4;  // Right;
+              y += marker_size * 0.9;  // Down
+              break;
+            case downward: // OK
+              al = left_align;
+              x -= marker_size;  // Left
+              y += marker_size;  // Up
+             break;
+            case backdown: // OK
+              al = right_align;
+              x -= marker_size * 0.5;  // Left
+              y += marker_size * 1.5;  // down
+              rot = uphill;
+             break;
+            } // switch
+            text_element& t = g_ptr.text(x, y, stripped, val_style.values_text_style_, al, rot);  // X or Y value "1.23".
+            int udf_font = static_cast<int>(val_style.values_text_style_.font_size() * reducer);
+            // TODO what does this reducer do?
+
+            std::string label_u; // std_dev or text_plusminus.
+            std::string label_df; // Degrees of freedom estimate.
+            std::string pm_symbol = " ±"; //! Unicode space text_plusminus glyph.
+            // Might also use ANSI symbol for text_plusminus 0xF1 == '\361' or char(241)
+            // but seems to vary with different codepages:
+            // LOCALE_SYSTEM_DEFAULT LOCALE_IDEFAULTANSICODEPAGE == 1252
+            // LOCALE_SYSTEM_DEFAULT  LOCALE_IDEFAULTCODEPAGE ==  850 for country 44 (UK)
+            // And seems to vary from console to printable files.
+            // Spaces seem to get lost, so use 00A0 as an explicit space glyph.
+            // Layout seems to vary with font - Times New Roman leaves no space after.
+            //text_element& t = g_ptr.text(x, y, label_v, val_style.values_text_style_, al, rot);
+           // Optionally, show std_dev as 95% confidence plus minus:  2.1 +-0.012 (23)
+
+            // Extra info from Meas.
+            using boost::posix_time::ptime;
+
+            if ((val_style.plusminus_on_ == true) // text_plusminus uncertainty is wanted,
+                && (sd > 0.) // and std_dev is a valid std_dev estimate.
+              )
+            {  // std_dev estimate usually expressed 67% confidence interval + or - standard deviation.
+              sd *= derived().text_plusminus_; // typically + or - standard deviation.
+              label_u = sv(sd, val_style, true); // stripped.
+              t.tspan(pm_symbol).fill_color(val_style.plusminus_color_);
+              t.tspan(label_u).fill_color(val_style.plusminus_color_).font_size(udf_font);
+            }
+            if (val_style.addlimits_on_ == true)
+            { // Want confidence interval appended, for example: <1.23, 1.45>
+              //alpha = 0.05; // oss.iword(confidenceIndex) / 1.e6; // Pick up alpha.
+              //double epsilon = 0.01; // = oss.iword(roundingLossIndex) / 1.e3; // Pick up rounding loss.
+              //int uncSigDigits = 2; // = oss.iword(setUncSigDigitsIndex);  // Pick up significant digits for uncertainty.
+              //bool isNoisyDigit = false; // Pick up?
+              if(derived().isNoisyDigit_)
+              {
+                derived().uncSigDigits_++;
+              }
+              std::pair<double, double> ci = conf_interval(value, sd, df, derived().alpha_, distrib);
+              int m = round_m(derived().epsilon_, sd, derived().uncSigDigits_, distrib);
+              using boost::lexical_cast;
+              std::stringstream label;
+              label << " <" // '<' 003C is an XML predefined entity, so use name.
+                  << lexical_cast<double>(round_ms(ci.first, m)) << ", "
+                  << lexical_cast<double>(round_ms(ci.second, m))
+                  << ">"; // '>' 003e is an XML predefined entity, so use name.
+              std::string label_limits = label.str(); // For example: "<1.23, 1.45>"
+              t.tspan(label_limits).fill_color(val_style.addlimits_color_).font_size(udf_font);
+            }
+            if (val_style.df_on_ == true // degrees of freedom is wanted.
+                  && (df != (std::numeric_limits<unsigned short int>::max)()) // and deg_free is defined OK.
+                )
+            { // Degrees of freedom or number of values-1 used for this estimate of value.
+              std::stringstream label;
+              label.precision(4); // Might need 5 to show 65535?
+              //label.flags(sty.value_ioflags_); // Leave at default.
+              label << " (" << df << ")"; // "123"
+              // Explicit space symbol "\ " seems necessary.
+              label_df = label.str();
+              t.tspan(label_df).fill_color(val_style.df_color_).font_size(udf_font);
+            }
+            if (val_style.id_on_) //
+            {  // Add ID or name string.
+              if (label_id.size() != 0)
+              {
+                label_id = " \"" + label_id + "\" ";
+                t.tspan(label_id).fill_color(val_style.id_color_).font_size(udf_font);
+              }
+            }
+
+            if (val_style.datetime_on_  && (dt != boost::posix_time::not_a_date_time)) // from uvalue.time_;
+            {  // Add date and time stamp (if valid).
+              std::ostringstream label_dt;
+              label_dt << dt;
+              t.tspan(label_dt.str()).fill_color(val_style.datetime_color_).font_size(udf_font);
+            }
+            if (val_style.order_on_) //
+            {  // Add order in sequence number.
+              std::ostringstream label_order;
+              label_order << " #" << order;
+              t.tspan(label_order.str()).fill_color(val_style.order_color_).font_size(udf_font);
+            }
+
+            if (val_style.suffix_ != "")
+            { // Add a suffix like "]" or " sec]".
+              t.tspan(val_style.suffix_);
+            }
+          } // void draw_plot_point_value(double x, double y, g_element& g_ptr, value_style& val_style, plot_point_style& point_style, Meas uvalue)
+
+
+          std::string sv(double v, const value_style& sty, bool precise = false)
+          { //! Strip from double value any unecessary e, +, & leading exponent zeros, reducing "1.200000" to "1.2" or "3.4e1"...
+            // TODO rename fo strip_value?
+            std::stringstream label;
+            // Precision of std_dev is usually less than precision of value,
+            // label.precision((unc) ? ((sty.value_precision_ > 3) ?  sty.value_precision_-2 : 1) : sty.value_precision_);
+            // Possible but simpler to fix at precision=2
+            label.precision((precise) ? 2 : sty.value_precision_);
+            label.flags(sty.value_ioflags_);
+            label << v; // "1.2" or "3.4e+001"...
+            return  (sty.strip_e0s_) ?
+              // Default is to strip unecessary e, +, & leading exponent zeros.
+              strip_e0s(label.str())  // reduce to "1.2" or "3.4e1"...
+              :
+              label.str();  // Leave unstripped.
+          } // std::string sv(double v, const value_style& sty)
+
+         template <class Derived>
+         void axis_plot_frame<Derived>::draw_plot_point_values(double x, double y, g_element& x_g_ptr, g_element& y_g_ptr, const value_style& x_sty, const value_style& y_sty, Meas uncx, unc<false> uncy)
+          { /*! \brief Write the \b pair of data points X and Y values as a string.
+               \details
+               The x parameter also carries the measurement information for the pair,
+               and so is a Meas, not just an unc<false> as is the Y parameter.
+               If a separator starting with newline,
+               then both on the same line, for example "1.23, 3.45", or "[5.6, 7.8]
+               X value_style is used to provide the prefix and separator, and Y value_style to provide the suffix.
+               For example,
+               */
+            /*!
+              \verbatim x_style prefix("[ X=", and separator ", Y= ", " and Y value_style = "]" will produce a value label like "[X=-1.23, Y=4.56]"\endverbatim
+
+              \note You need to use a Unicode space for get space for all browsers.
+              For a long a string you may need to make the total image size bigger,
+              and to orient the value labels with care.
+              draw_plot_point_values is only when both x and Y pairs are wanted.
+           */
+            // Avoid a warning about using   within Doxygen comment.
+            // And there is something funny about verbatim commands, henc eodd layout.
+            using std::string;
+            using std::stringstream;
+            double vx = uncx.value();
+            double vy = uncy.value();
+            double ux = uncx.std_dev();
+            double uy = uncy.std_dev();
+            double dfx = uncx.deg_free();
+            double dfy = uncy.deg_free();
+            unsigned short int types = uncx.types();  //  unctypes_
+            distribution_type distrib;
+            if (types & UNC_UNIFORM)
+            {
+              distrib = uniform;
+            }
+            else if (types & UNC_TRIANGULAR)
+            {
+              distrib = triangular;
+            }
+            else
+            { // Default.
+              distrib = gaussian;
+            }
+            std::string label_xv = sv(vx, x_sty); //! Also strip unnecessary e, + and leading exponent zeros, if required.
+            std::string label_yv = sv(vy, y_sty);
+            if (x_sty.prefix_ != "")
+            { // Want a prefix , for example, "["
+              label_xv = x_sty.prefix_ + label_xv;
+            }
+
+            int marker_size = derived().serieses_[0].point_style_.size_;
+            int label_size = x_sty.values_text_style_.font_size();
+            // Offset of value labels from point must be related mainly to
+            // size of the data marker, less the value label font size.
+
+            rotate_style rot = x_sty.value_label_rotation_;
+            align_style al; // = center_align;
+            switch (rot)
+            {
+            case horizontal: // OK
+              al = center_align;
+              y -= marker_size * 2;  // Up marker font size;
+              // center_align means no x correction.
+              break;
+            case leftward: // horizontal but to left of marker. OK
+              al = right_align;
+              x -= marker_size * 1.3;  // left
+              y += label_size * 0.3;  // down label font size;
+              rot = horizontal;
+              break;
+            case rightward: // horizontal but to right of marker.OK
+              al = left_align;
+              x += marker_size * 1.1;  // right
+              y += label_size * 0.3;  // down label font size;
+              rot = horizontal;
+              break;
+            case upsidedown: // OK but upsidedown so not very useful!
+              al = center_align;
+              y += marker_size;  // Down marker font size;
+             break;
+            case slopeup: // -30 - OK
+            case steepup: // -45 - OK
+            case uphill: // -60 - OK
+              al = left_align;
+              x += label_size /3;  // Right third label font size - centers on marker.
+              y -= marker_size * 0.6;  // UP marker font size;
+              break;
+            case upward: // -90 vertical writing up - OK.
+              al = left_align;
+              x += label_size /3;  // Right third label font size - centers on marker.
+              y -= marker_size * 0.9;  // Up marker font size;
+              break;
+            case backup: // OK
+              al = right_align;
+              x -= marker_size * 1.5;  // Left
+              y -= marker_size * 0.8;  // Up
+              rot = downhill;
+              break;
+            case  slopedownhill: // 30 gentle slope down.
+            case downhill: // 45 down.
+            case steepdown: //  60 steeply down.
+              al = left_align;
+              x += marker_size * 0.4;  // Right;
+              y += marker_size * 0.9;  // Down
+              break;
+            case downward: // OK
+              al = left_align;
+              x -= marker_size;  // Left
+              y += marker_size;  // Up
+             break;
+            case backdown: // OK
+              al = right_align;
+              x -= marker_size * 0.5;  // Left
+              y += marker_size * 1.5;  // down
+              rot = uphill;
+             break;
+            } // switch
+
+            // If would be simpler to prepare a single string like "1.23 +- -0.3, 3.45 +- -0.1(10)"
+            // but this would not allow change of font size, type and color
+            // something that proves to be very effective at visually separating
+            // value and std_dev, and degrees of freedom estimate,
+            // and other information like date_time, id or name, and order in sequence.
+            // So the coding complexity is judged with it
+            // (even if it may not always work right yet ;-)
+            // Tasteless colors and font changes are purely proof of concept!
+
+            int fx = static_cast<int>(x_sty.values_text_style_.font_size() * reducer);
+
+            // Make std_dev and df a bit smaller to distinguish from value by default (but make configurable).
+            // Write X value (and optional std_dev and df).
+            std::string label_xdf; // X degrees of freedom as string.
+
+            text_element& t = x_g_ptr.text(x, y, label_xv, x_sty.values_text_style_, al, rot);
+            // Optionally, show std_dev as 95% confidence plus minus:  2.1 +-0.012
+            // and also optionally show degrees of freedom (23).
+
+            string pm_symbol = " ±"; //! Unicode space text_plusminus glyph.
+            // Spaces seem to get lost, so use \&x00A0 as an explicit space glyph.
+            // Layout seems to vary with font - Times New Roman leaves no space after.
+            if ((x_sty.plusminus_on_ == true) && (ux > 0.) )
+            {  // std_dev estimate usually 67% confidence interval + or - standard deviation.
+              ux *= derived().text_plusminus_; // typically  + or - standard deviation.
+              std::string label_xu; // X std_dev as string.
+              label_xu = sv(ux, x_sty, true);
+              //t.tspan(pm_symbol).fill_color(darkcyan);
+              // Should this be stroke_color?
+              t.tspan(pm_symbol).fill_color(x_sty.plusminus_color_);
+              t.tspan(label_xu).fill_color(x_sty.plusminus_color_).font_size(fx); // .font_weight("bold")
+            }
+            if (x_sty.addlimits_on_ == true)
+            { // Want confidence interval appended, for example: <1.23, 1.45>
+              //double alpha = 0.05; // oss.iword(confidenceIndex) / 1.e6; // Pick up alpha.
+              //double epsilon = 0.01; // = oss.iword(roundingLossIndex) / 1.e3; // Pick up rounding loss.
+              //int uncSigDigits = 2; // = oss.iword(setUncSigDigitsIndex);  // Pick up significant digits for uncertainty.
+              //bool isNoisyDigit = false; // Pick up?
+              if(derived().isNoisyDigit_)
+              {
+                derived().uncSigDigits_++;
+              }
+              std::pair<double, double> ci = conf_interval(vx, ux, dfx, derived().alpha_, distrib);
+              int m = round_m(derived().epsilon_, ux, derived().uncSigDigits_, distrib);
+              using boost::lexical_cast;
+              std::stringstream label;
+              label << " <" // '<' 003C is an XML predefined entity, so use name.
+                  << lexical_cast<double>(round_ms(ci.first, m)) << ", "
+                  << lexical_cast<double>(round_ms(ci.second, m))
+                  << ">"; // '>' 003e is an XML predefined entity, so use name.
+              std::string label_limits = label.str(); // For example: "<1.23, 1.45>"
+              t.tspan(label_limits).fill_color(x_sty.addlimits_color_).font_size(fx);
+            }
+
+            if ((x_sty.df_on_ == true)  // Is wanted.
+                 &&
+                 (dfx != (std::numeric_limits<unsigned short int>::max)()) // and deg_free is defined OK.
+               )
+            { // Degrees of freedom (usually number of observations-1) used for this estimate of value.
+              stringstream label;
+              label.precision(4); // Might need 5 to show 65535?
+              //label.flags(sty.value_ioflags_); // Leave at default.
+              label << " (" << dfx << ")"; // "123.5"
+              // Explicit space "\ " seems necessary.
+              label_xdf = label.str();
+              t.tspan(label_xdf).fill_color(x_sty.df_color_).font_size(fx);
+            }
+
+            int fy = static_cast<int>(y_sty.values_text_style_.font_size() * reducer);
+            // If a newline is 1st char in separator, put values on the next line below the marker,
+            // else all on one line.
+            bool sameline = (x_sty.separator_[0] != '\n');
+            if (sameline)
+            { // On same line so use X style for separator, but Y style for any text.
+              t.tspan(x_sty.separator_).fill_color(x_sty.fill_color_).font_size(x_sty.values_text_style_.font_size());
+              t.tspan(y_sty.separator_).fill_color(y_sty.fill_color_).font_size(y_sty.values_text_style_.font_size());
+              if (y_sty.prefix_ != "")
+              { // Want a prefix, for example: "length ="
+                t.tspan(y_sty.prefix_).fill_color(y_sty.fill_color_).font_size(y_sty.values_text_style_.font_size());
+              }
+              t.tspan(label_yv, y_sty.values_text_style_); // Color.
+              if (
+                   (y_sty.plusminus_on_) // +/- is wanted.
+                   && (uy > 0.) // Is valid std_dev estimate.
+                 )
+              { // std_dev estimate (usually 95% confidence interval + or - standard deviation).
+                // Precision of std_dev is usually less than value,
+                uy *= derived().text_plusminus_; // Typically + or - standard deviation.
+                std::string label_yu;
+                label_yu = " " + sv(uy, y_sty, true);
+                t.tspan(pm_symbol).font_family("arial").font_size(fy).fill_color(green);
+                t.tspan(label_yu).fill_color(y_sty.plusminus_color_).font_size(fy);
+              }
+ //             value_style val_style = y_sty;
+              if (y_sty.addlimits_on_ == true)
+              { // Want confidence interval appended, for example: <1.23, 1.45>
+                //double alpha = 0.05; // oss.iword(confidenceIndex) / 1.e6; // Pick up alpha.
+                //double epsilon = 0.01; // = oss.iword(roundingLossIndex) / 1.e3; // Pick up rounding loss.
+                //int uncSigDigits = 2; // = oss.iword(setUncSigDigitsIndex);  // Pick up significant digits for uncertainty.
+                //bool isNoisyDigit = false; // Pick up?
+                if(derived().isNoisyDigit_)
+                {
+                  derived().uncSigDigits_++;
+                }
+                std::pair<double, double> ci = conf_interval(vy, uy, dfy, derived().alpha_, distrib);
+                int m = round_m(derived().epsilon_, uy, derived().uncSigDigits_, distrib);
+                using boost::lexical_cast;
+                std::stringstream label;
+                label << " <" // '<' 003C is an XML predefined entity, so use name.
+                    << lexical_cast<double>(round_ms(ci.first, m)) << ", "
+                    << lexical_cast<double>(round_ms(ci.second, m))
+                    << ">"; // '>' 003e is an XML predefined entity, so use name.
+                std::string label_limits = label.str(); // For example: "<1.23, 1.45>"
+                t.tspan(label_limits).fill_color(y_sty.addlimits_color_).font_size(fy);
+              }
+              if ((y_sty.df_on_ == true)
+                && (dfy != (std::numeric_limits<unsigned short int>::max)()) // Is valid df.
+                )
+              { // degrees of freedom or number of values -1 used for this estimate.
+                std::stringstream label;
+                label.precision(4);
+                //label.flags(sty.value_ioflags_); // Leave at default.
+                label <<" (" << dfy << ")"; // "123.5"
+                std::string label_ydf;
+                label_ydf = label.str();
+                t.tspan(label_ydf).fill_color(y_sty.df_color_).font_size(fy);
+              }
+              if (y_sty.suffix_ != "")
+              { // Want a suffix like "]" - with the Y values font size, (not reduced for std_dev info), and same color as prefix.
+                t.tspan(y_sty.suffix_).fill_color(y_sty.fill_color_).font_size(y_sty.values_text_style_.font_size());
+              }
+            } //
+            else
+            { // Move ready to put Y value on 'newline' below point marker.
+              // Problem here if orientation is changed? - Yes - doesn't line up :-(
+              //x_sty.separator_.substr(1); to ignore the \n newline indicator.
+              t.tspan(x_sty.separator_.substr(1)).fill_color(x_sty.fill_color_).font_size(x_sty.values_text_style_.font_size());
+              if (y_sty.prefix_ != "")
+              { //
+                label_yv = y_sty.prefix_ + label_yv;
+              }
+              double dy = y_sty.values_text_style_.font_size() * 1.2; // was 2.2 "newline"
+              // Need to start a new text_element here because tspan rotation doesn't apply to whole string?
+              text_element& ty = y_g_ptr.text(x, y + dy, label_yv, y_sty.values_text_style_, al, rot);
+
+              if ((y_sty.plusminus_on_ == true) // Is wanted.
+                  && (uy > 0.) // And is a valid std_dev estimate.
+                  )
+              {  // std_dev estimate usually 95% confidence interval + or - 2 standard deviation.
+                 // Precision of std_dev is usually less than value,
+                std::string label_yu = " " + sv(uy, y_sty, true);
+                ty.tspan(pm_symbol).font_family("arial").font_size(fy).fill_color(y_sty.plusminus_color_); // +/- sumbol.
+                ty.tspan(label_yu).fill_color(y_sty.plusminus_color_).font_size(fy);
+              }
+
+              if (y_sty.addlimits_on_ == true)
+              { // Want confidence interval appended, for example: <1.23, 1.45>
+                // TODO pick up alpha, epsilon from somewhere?
+                //double alpha = 0.05; // oss.iword(confidenceIndex) / 1.e6; // Pick up alpha.
+                //double epsilon = 0.01; // = oss.iword(roundingLossIndex) / 1.e3; // Pick up rounding loss.
+                //int uncSigDigits = 2; // = oss.iword(setUncSigDigitsIndex);  // Pick up significant digits for uncertainty.
+                //bool isNoisyDigit = false; // Pick up?
+                if(derived().isNoisyDigit_)
+                {
+                  derived().uncSigDigits_++;
+                }
+                std::pair<double, double> ci = conf_interval(vy, uy, dfy, derived().alpha_, distrib);
+                int m = round_m(derived().epsilon_, uy, derived().uncSigDigits_, distrib);
+                using boost::lexical_cast;
+                std::stringstream label;
+                label << " <" // '<' 003C is an XML predefined entity, so use name.
+                    << lexical_cast<double>(round_ms(ci.first, m)) << ", "
+                    << lexical_cast<double>(round_ms(ci.second, m))
+                    << ">"; // '>' 003e is an XML predefined entity, so use name.
+                std::string label_limits = label.str(); // For example: "<1.23, 1.45>"
+                ty.tspan(label_limits).fill_color(y_sty.addlimits_color_).font_size(fy);
+              }
+
+              if ((y_sty.df_on_ == true)  // Is wanted.
+                    && (dfy != (std::numeric_limits<unsigned short int>::max)()) // and deg_free is defined OK.
+                    )
+              { // degrees of freedom or number of values -1 used for this estimate.
+                std::stringstream label;
+                label.precision(4);
+                //label.flags(sty.value_ioflags_); // Leave at default.
+                label <<" (" << dfy << ")"; // "123.5"
+                std::string label_ydf = label.str();
+                ty.tspan(label_ydf).fill_color(y_sty.df_color_).font_size(fy);
+              }
+
+              if (y_sty.suffix_ != "")
+              { // Want a suffix like "]" or "sec]" or " sec]"
+                ty.tspan(y_sty.suffix_).fill_color(y_sty.fill_color_).font_size(y_sty.values_text_style_.font_size());
+              }
+            }  // Same or newline.
+
+            int udf_font = static_cast<int>(y_sty.values_text_style_.font_size() * reducer);
+
+            std::string label_id = uncx.id_;
+            if (x_sty.id_on_ && (label_id.size() != 0)) //
+            {  // Add ID or name string (in " quotes).
+              label_id = " \"" + label_id + "\" ";
+              t.tspan(label_id).fill_color(x_sty.id_color_).font_size(udf_font);
+            }
+
+            using boost::posix_time::ptime;
+            ptime dt = uncx.time_;
+            if (x_sty.datetime_on_ && (dt != boost::posix_time::not_a_date_time))
+            {  // Add date and time stamp (if date_time valid).
+              std::ostringstream label_dt;
+              label_dt << " " << dt;
+              t.tspan(label_dt.str()).fill_color(x_sty.datetime_color_).font_size(udf_font);
+            }
+
+            int order = uncx.order_;
+            if (x_sty.order_on_ && order >= 0) // If order < 0, then no order in sequence number.
+            {  // Add order in sequence number.
+              std::ostringstream label_order;
+              label_order << " #" << order;
+              t.tspan(label_order.str()).fill_color(x_sty.order_color_).font_size(udf_font);
+            }
+
+            if (x_sty.suffix_ != "")
+            { // Add a suffix like "]" or " sec]".
+              t.tspan(y_sty.suffix_);
+            }
+        } // void draw_plot_point_values(double x, double y, g_element& g_ptr, double value)
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::size(unsigned int x, unsigned int y)
+          { //! Set SVG image size (SVG units, default pixels).
+            // Check on sanity of these values?
+            derived().image_.size(x, y);
+            return derived();
+          }
+
+          template <class Derived>/*! \tparam Derived plot class, svg_1d_plot or svg_2d_plot or svg_boxplot. */
+          template <class T> /*! \tparam T an STL container: array, vector, list, map ...  */
+          Derived& axis_plot_frame<Derived>::x_autoscale(const T& begin, const T& end)
+          { //! Data series (range accessed using iterators) to use to calculate autoscaled X-axis values.
+              scale_axis(begin, end,
+              &derived().x_auto_min_value_, &derived().x_auto_max_value_, &derived().x_auto_tick_interval_, &derived().x_auto_ticks_,
+              derived().autoscale_check_limits_, derived().autoscale_plusminus_,
+              derived().x_include_zero_, derived().x_tight_, derived().x_min_ticks_, derived().x_steps_);
+
+            derived().x_autoscale_ = true; //! Default to use calculated values.
+            return derived();
+          } // x_autoscale(const T& begin, const T& end)
+
+                    template <class Derived>
+          template <class T> // T an STL container: array, vector...
+          Derived& axis_plot_frame<Derived>::x_autoscale(const T& container) // Use whole 1D data series.
+          { //! Data series (all values) to use to calculate autoscaled X-axis values.
+            //scale_axis(container.begin(), container.end(), // All the container.
+            scale_axis(container, // All the container.
+            &derived().x_auto_min_value_, &derived().x_auto_max_value_, &derived().x_auto_tick_interval_, &derived().x_auto_ticks_,
+            derived().autoscale_check_limits_, derived().autoscale_plusminus_,
+            derived().x_include_zero_, derived().x_tight_, derived().x_min_ticks_, derived().x_steps_);
+
+            derived().x_autoscale_ = true; // Default is to use calculated values.
+            return derived();
+          } // x_autoscale(const T& container)
+
+          template <class Derived>
+          std::pair<double, double> axis_plot_frame<Derived>::size()
+          { //! \return SVG image size, both horizontal width and vertical height (SVG units, default pixels).
+            return derived().image_.xy_sizes();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::image_x_size() //!< Obselete - deprecated.
+          { //! \return SVG image X-axis size as horizontal width (SVG units, default pixels).
+            return derived().image_.x_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_size(unsigned int i)
+          { //! Set SVG image X-axis size (SVG units, default pixels).
+            // Can't this be x_size(unsigned int i)
+            derived().image_.x_size(i);
+            return derived();
+          }
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::x_size()
+          { //! \return SVG image X-axis size as horizontal width (SVG units, default pixels).
+            return derived().image_.x_size();
+          }
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::image_x_size(unsigned int i) //!< Obselete - deprecated.
+          { //! Set SVG image X-axis size (SVG units, default pixels).
+            // Can't this be x_size(unsigned int i)
+            derived().image_.x_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::image_y_size() //!< Obselete - deprecated.
+          { //! \return SVG image Y-axis size as vertical height (SVG units, default pixels).
+            return derived().image_.y_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::image_y_size(unsigned int i) //!< Obselete - deprecated.
+          {//! Set SVG image Y-axis size (SVG units, default pixels).
+            derived().image_.y_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::y_size()
+          { //! \return SVG image Y-axis size as vertical height (SVG units, default pixels).
+            return derived().image_.y_size();
+          }
+
+                   template <class Derived>
+          Derived& axis_plot_frame<Derived>::y_size(unsigned int i)
+          {//! Set SVG image Y-axis size (SVG units, default pixels).
+            derived().image_.y_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::background_color()
+          { //! \return  plot background color.
+            return derived().image_.g(PLOT_BACKGROUND).style().fill_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::background_color(const svg_color& col)
+          { //! Set plot background color.
+            derived().image_.g(PLOT_BACKGROUND).style().fill_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::background_border_color(const svg_color& col)
+          { //! Set plot background border color.
+            derived().image_.g(PLOT_BACKGROUND).style().stroke_color(col);
+            /*!
+              background_border_color, for example:
+              \verbatim svg_2d_plot my_plot(my_data, "My Data").background_border_color(red).background_color(azure);
+              \endverbatim
+            */
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::background_border_color()
+          { //! \return  plot background border color.
+            return derived().image_.g(PLOT_BACKGROUND).style().stroke_color();
+          }
+
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::background_border_width(double w)
+          { //! Set plot background border width.
+            derived().image_.g(PLOT_BACKGROUND).style().stroke_width(w);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::background_border_width()
+          { //! \return  plot background border width.
+            return derived().image_.g(PLOT_BACKGROUND).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::description(const std::string d)
+          { /*! Writes description to the document for header, for example:
+              \verbatim
+                <desc> My Data </desc>
+              \endverbatim
+          */
+            derived().image_.description(d);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::description()
+          { //! \return  description of the document for header as \verbatim <desc> ... </desc> \endverbatim
+            return derived().image_.description();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::document_title(const std::string d)
+          { //! Write document title to the SVG document for header as \verbatim <title> My Title </title>  \endverbatim
+            derived().image_.document_title(d);
+            return derived();
+          }
+          template <class Derived>
+          std::string axis_plot_frame<Derived>::document_title()
+          { //! \return  document title to the document for header as \verbatim <title> My Title </title> \endverbatim
+            return derived().image_.document_title();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<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 \verbatim metadata: <meta name="copyright" content="Paul A. Bristow" /meta> \endverbatim
+            derived().image_.copyright_holder(d);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::copyright_holder()
+          { //! \return copyright holder.
+            return derived().image_.copyright_holder();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::copyright_date(const std::string d)
+          { //! Writes copyright date to the document.
+            //! and as \verbatim metadata <meta name="date" content="2007" /> \endverbatim
+            derived().image_.copyright_date(d);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::copyright_date()
+          { //! \return  copyright_date.
+            return derived().image_.copyright_date();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::license(std::string repro,
+            std::string distrib,
+            std::string attrib,
+            std::string commercial,
+            std::string derivative)
+          { //! Set license conditions for reproduction, attribution, commercial use, and derivative works,
+            //! usually "permits", "requires", or "prohibits",
+            //! and set license_on == true.
+            // Might check these are "permits", "requires", or "prohibits"?
+            derived().image_.license(repro, distrib, attrib, commercial, derivative);
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::license_on()
+          { //! \return true if license conditions should be included in the SVG document.
+            //! \see axis_plot_frame::license
+            return derived().image_.license_on();
+          }
+
+          template <class Derived>
+          Derived&  axis_plot_frame<Derived>::license_on(bool l)
+          { //! Set if license conditions should be included in the SVG document.
+            //! \see axis_plot_frame::license
+            derived().image_.license_on(l);
+            return derived();
+          }
+          template <class Derived>
+          bool axis_plot_frame<Derived>::boost_license_on()
+          { //! \return  if the Boost license conditions should be included in the SVG document.
+            //! To set see axis_plot_frame::boost_license_on(bool).
+            return derived().image_.boost_license_one();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::boost_license_on(bool l)
+          { //! Set if the Boost license conditions should be included in the SVG document.
+            derived().image_.boost_license_on(l);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::license_reproduction()
+          { //! \return  reproduction license conditions, usually "permits", "requires", or "prohibits".
+            return derived().image_.reproduction();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::license_distribution()
+          { //! \return  distribution license conditions, usually "permits", "requires", or "prohibits".
+            return derived().image_.distribution();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::license_attribution()
+          { //! \return  attribution license conditions, usually "permits", "requires", or "prohibits".
+            return derived().image_.attribution();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::license_commercialuse()
+          { //! \return  commercial use license conditions, usually "permits", "requires", or "prohibits".
+            return derived().image_.commercialuse();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::coord_precision(int digits)
+          { /*! Precision of SVG coordinates in decimal digits (default 3).
+              3 decimal digits precision is sufficient for small images.
+              4 or 5 decimal digits precision will give higher quality plots,
+              especially for larger images, at the expense of larger .svg files,
+              particularly if there are very many data points.
+           */
+            derived().image_.coord_precision(digits);
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::coord_precision()
+          { //! \return  precision of SVG coordinates in decimal digits.
+            return derived().image_.coord_precision();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_value_precision(int digits)
+          { /*! Precision of X tick label values in decimal digits (default 3).
+              3 decimal digits precision is sufficient for small images.
+              4 or 5 decimal digits precision will give more cluttered plots.
+              If the range of labels is very small, then more digits will be essential.
+            */
+
+            derived().x_ticks_.value_precision_ = digits;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_value_precision()
+          { //! \return  precision of X tick label values in decimal digits
+            return derived().x_ticks_.value_precision_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_value_ioflags(int flags)
+          { /*! Set iostream std::ios::fmtflags for X value label (default decimal == 0X201).
+              Mainly useful for changing to scientific, fixed or hexadecimal format.
+              For example: .x_value_ioflags(std::ios::dec | std::ios::scientific)
+            */
+            derived().x_ticks_.value_ioflags_ = flags;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_value_ioflags()
+          { //! \return  stream ioflags for control of format of X value labels.
+            return derived().x_ticks_.value_ioflags_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_labels_strip_e0s(bool cmd)
+          { //! Set if to strip redundant zeros, signs and exponents, for example, reducing "1.2e+000" to "1.2"
+            //! This markedly reduces visual clutter, and is the default.
+            derived().x_ticks_.strip_e0s_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::y_labels_strip_e0s()
+          { //! \return  if to strip redundant zeros, signs and exponents, for example, reducing "1.2e+000" to "1.2"
+            return derived().x_ticks_.strip_e0s_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title(const std::string title)
+          { /*!
+              Set a title for plot.
+              The string may include Unicode for greek letter and symbols.
+              For example a title that includes a greek omega and degree symbols:
+              \verbatim my_plot.title("Plot of Ω function (°C)"); \endverbatim
+
+              Unicode symbols are at http://unicode.org/charts/symbols.html .
+            */
+            // Plot title.  TODO
+            // new text parent code pushback
+            // effectively concatenates with any existing title.
+            // So clear the existing string first but doesn't work,
+            // so need to clear the whole g_element.
+            //derived().image_.g(PLOT_TITLE).clear();
+            derived().title_info_.text(title);
+            derived().title_on_ = true; // Assume display wanted, if bother to set title.
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::title()
+          { //! \return  a title for plot, whose string may include Unicode for greek letter and symbols.
+            return derived().title_info_.text();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_size(unsigned int i)
+          { //! Sets the font size for the title (svg units, default pixels).
+            derived().title_info_.textstyle().font_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::title_font_size()
+          { //! \return  the font size for the title (svg units, default pixels).
+            return derived().title_info_.textstyle().font_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_family(const std::string& family)
+          { //! Set the font family for the title (for example: .title_font_family("Lucida Sans Unicode");
+            derived().title_info_.textstyle().font_family(family);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::title_font_family()
+          { //! \return  the font family for the title
+            return derived().title_info_.textstyle().font_family();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_style(const std::string& style)
+          { //! Set the font style for the title (default normal).
+            derived().title_info_.textstyle().font_style(style);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::title_font_style()
+          { //! \return  the font style for the title (default normal).
+            return derived().title_info_.textstyle().font_style();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_weight(const std::string& weight)
+          { //! Set the font weight for the title (default normal).
+            derived().title_info_.textstyle().font_weight(weight);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::title_font_weight()
+          {//! \return  the font weight for the title.
+            return derived().title_info_.textstyle().font_weight();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_stretch(const std::string& stretch)
+          { //! Set the font stretch for the title (default normal), wider or narrow.
+            derived().title_info_.textstyle().font_stretch(stretch);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::title_font_stretch()
+          { //! \return  the font stretch for the title.
+            return derived().title_info_.textstyle().font_stretch();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_decoration(const std::string& decoration)
+          { //! Set the font decoration for the title (default normal, or underline, overline or strike-thru).
+            derived().title_info_.textstyle().font_decoration(decoration);
+            return derived();
+          }
+
+           template <class Derived>
+         const std::string& axis_plot_frame<Derived>::title_font_decoration()
+          { //! \return  the font decoration for the title (default normal, or underline, overline or strike-thru).
+            return derived().title_info_.textstyle().font_decoration();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_rotation(rotate_style rotate)
+          { //! Set the rotation for the title font (degrees, 0 to 360).
+            derived().title_info_.rotation(rotate);
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::title_font_rotation()
+          { //! \return  the rotation for the title font (degrees).
+            return derived().title_info_.rotation();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_font_alignment(align_style alignment)
+          { //! Set the alignment for the title.
+            derived().title_info_.alignment(alignment);
+            return derived();
+          }
+
+          template <class Derived>
+          align_style axis_plot_frame<Derived>::title_font_alignment()
+          { //! \return  the alignment for the title.
+            return derived().title_info_.alignment();
+          }
+
+          // Legend.
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_width(double width)
+          { //! Set the width for the legend.
+            derived().legend_width_ = width;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::legend_width()
+          { //! \return  the width for the legend.
+            return derived().legend_width_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_title(const std::string title)
+          { //! Set the title for the legend.
+            derived().legend_header_.text(title);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::legend_title()
+          { //! \return  the title for the legend.
+            return derived().legend_header_.text();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_font_weight(const std::string& weight)
+          { //! Set the font weight for the legend title.
+            derived().legend_header_.textstyle().font_weight(weight);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::legend_font_weight()
+          { //! \return  the font weight for the legend title.
+            return derived().legend_header_.textstyle().font_weight();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_font_family(const std::string& family)
+          { //! Set the font family for the legend title.
+            derived().legend_header_.textstyle().font_family(family);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::legend_font_family()
+          { //! \return  the font family for the legend title.
+            return derived().legend_header_.textstyle().font_family();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_title_font_size(unsigned int size)
+          { //! Set the font size for the legend title (svg units, default pixels).
+            derived().legend_header_.textstyle().font_size(size);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::legend_title_font_size()
+          { //! \return  the font size for the legend title (svg units, default pixels).
+            return derived().legend_header_.textstyle().font_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_top_left(double x, double y)
+          { //! Set position of top left of legend box (svg coordinates, default pixels).
+            //! Bottom right is controlled by contents, so the user cannot set it.
+            if((x < 0) || (x > derived().image_.x_size()) || (y < 0) || (y > derived().image_.y_size()))
+            {
+              throw std::runtime_error("Legend box position outside image!");
+            }
+            derived().legend_left_ = x;
+            derived().legend_top_ = y;
+            return derived();
+          }
+
+          template <class Derived>
+          const std::pair<double, double> axis_plot_frame<Derived>::legend_top_left()
+          { //! \return  svg coordinate (default pixels) of top left of legend box.
+            std::pair<double, double> r;
+            r.first = derived().legend_left_;
+            r.second = derived().legend_top_;
+            return r;
+          }
+
+          template <class Derived>
+          const std::pair<double, double> axis_plot_frame<Derived>::legend_bottom_right()
+          { //! \return  svg coordinate (default pixels) of Bottom right of legend box.
+            std::pair<double, double> r;
+            r.first = derived().legend_right_;
+            r.second = derived().legend_bottom_;
+            return r;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_lines(bool is)
+          { //! Set true if legend should include samples of the lines joining data points.
+            //! \details This allows different series of data points to be distinguished by different color and/or width.
+            //! This is especially useful to show plots of different functions and/or different parameters in different colors.
+            derived().legend_lines_ = is;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::legend_lines()
+          {//! \return  true if legend should include samples of the lines joining data points.
+            return derived().legend_lines_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_on(bool cmd)
+          { //! Set true if a legend is wanted.
+            derived().legend_on_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::legend_on()
+          { //! \return  true if a legend is wanted.
+            return derived().legend_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_axis_vertical(double fraction)
+          { //! Set vertical position of X-axis for 1D as fraction of plot window.
+            if((fraction < 0.0) || (fraction > 1.0))
+            {
+              std::cout << "Vertical position of X-axis must be a fraction of plot window 0 < value < 1!"
+              << std::endl;
+            }
+            else
+            {
+              derived().x_axis_vertical_ = fraction;
+            }
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_axis_vertical()
+          { //! \return vertical position of X-axis for 1D as fraction of plot window.
+            return derived().x_axis_vertical_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_place(legend_places l)
+          { //! Set the position of the legend, \see  boost::svg::legend_places
+            derived().legend_place_ = l;
+            return derived();
+          }
+
+          template <class Derived>
+          legend_places axis_plot_frame<Derived>::legend_place()
+          { //! \return  the position of the legend, \see  boost::svg::legend_places
+            return derived().legend_place_;
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::legend_outside()
+          { //! \return  if the legend should be outside the plot area.
+            return derived().outside_legend_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_header_font_size(int size)
+          { //! Set legend header font size (svg units, default pixels).
+            derived().legend_header_.textstyle().font_size(size);
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::legend_header_font_size()
+          { //! \return  legend header font size (svg units, default pixels).
+            return derived().legend_header_.textstyle().font_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::plot_window_on(bool cmd)
+          { //! Set true if a plot window is wanted (or false if the whole image is to be used).
+            derived().plot_window_on_ = cmd;
+            if(cmd)
+            { // Set plot window.
+              derived().image_.g(detail::PLOT_WINDOW_BACKGROUND).style()
+                .fill_color(derived().plot_window_border_.fill_) // background color and
+                .stroke_color(derived().plot_window_border_.stroke_); // border color.
+            }
+            //derived().legend_place_ = outside_right;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::plot_window_on()
+          {//! \return  true if a plot window is wanted (or false if the whole image is to be used).
+            return derived().plot_window_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::plot_border_color(const svg_color& col)
+          { //! Set the color for the plot window background.
+            derived().plot_window_border_.stroke_ = col;
+            derived().image_.g(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::plot_border_color()
+          { //! \return  the color for the plot window background.
+            return derived().image_.g(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::plot_border_width()
+          { //! \return  the width for the plot window border (svg units, default pixels).
+            return derived().image_.g(detail::PLOT_WINDOW_BACKGROUND).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::plot_border_width(double w)
+          { //! Set the width for the plot window border (svg units, default pixels).
+            derived().plot_window_border_.width_ = w;
+            derived().image_.g(detail::PLOT_WINDOW_BACKGROUND).style().stroke_width(w);
+            return derived();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::image_border_margin(double w)
+          { //! Set the margin around the plot window border (svg units, default pixels).
+            //! \details This prevents the plot window getting too close to other elements of the plot.
+            derived().image_border_.margin_ = w;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::image_border_margin()
+          { //! \return  the margin around the plot window border (svg units, default pixels).
+            return derived().image_border_.margin_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::image_border_width(double w)
+          { //! Set the svg image border width (svg units, default pixels).
+            derived().image_border_.width_ = w;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::image_border_width()
+          { //! \return  the svg image border width (svg units, default pixels).
+            return derived().image_border_.width_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::plot_window_x(double min_x, double max_x)
+          { //! Set the minimum and maximum (cartesian data units) for the plot window X axis.
+            //! This is normally calculated from other plot values.
+            if(max_x <= min_x)
+            {
+              throw std::runtime_error("plot_window X: x_max_ <= x_min_");
+            }
+            if((max_x - min_x) < std::numeric_limits<double>::epsilon() * 1000)
+            { // Range too small to display.
+              throw std::runtime_error("plot_window X range too small!" );
+            }
+            derived().plot_left_ = min_x;
+            derived().plot_right_ = max_x;
+            return derived();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::plot_window_y(double min_y, double max_y)
+          { //! Set the minimum and maximum (cartesian data units) for the plot window Y axis.
+            //! This is normally calculated from other plot values.
+
+            if(max_y <= min_y)
+            {
+              throw std::runtime_error("plot_window Y: y_max_ <= x_min_");
+            }
+            if(max_y <= min_y)
+            {
+              throw std::runtime_error("plot_window Y range too small!");
+            }
+            derived().plot_top_ = min_y;
+            derived().plot_bottom_ = max_y;
+            return derived();
+          }
+
+          // Get the minimum and maximum (cartesian data units) for the plot window axes.
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::plot_window_x_left()
+          { //! \return  left of the plot window.
+            return derived().plot_left_;
+          }
+          template <class Derived>
+          double axis_plot_frame<Derived>::plot_window_x_right()
+          { //! \return  right of the plot window.
+            return derived().plot_right_;
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::plot_window_y_top()
+          { //! \return  top of the plot window.
+            return derived().plot_top_;
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::plot_window_y_bottom()
+          { //! \return  top of the plot window.
+            return derived().plot_bottom_;
+          }
+
+          template <class Derived>
+          std::pair<double, double> axis_plot_frame<Derived>::plot_window_x()
+          { //! \return  both the left and right (X axis) of the plot window.
+            std::pair<double, double> r;
+            r.first = derived().plot_left_;
+            r.second = derived().plot_right_;
+            return r;
+          }
+
+          template <class Derived>
+          std::pair<double, double> axis_plot_frame<Derived>::plot_window_y()
+          { //! \return  both the top and bottom (Y axis) of the plot window.
+            std::pair<double, double> r;
+            r.first = derived().plot_top_;
+            r.second = derived().plot_bottom_;
+            return r;
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_minor_interval()
+          { //! \return  interval between X minor ticks.
+            return derived().x_ticks_.minor_interval_;  // interval
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::y_minor_interval()
+          { //! \return  interval between Y minor ticks.
+            return derived().y_ticks_.minor_interval_;  // interval
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_up_on(bool cmd)
+          { //! Set true if X major ticks should mark upwards.
+            derived().x_ticks_.up_ticks_on_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_ticks_up_on()
+          { //! \return  true if X major ticks should mark upwards.
+            return derived().x_ticks_.up_ticks_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_down_on(bool cmd)
+          { //! Set true if X major ticks should mark downwards.
+            derived().x_ticks_.down_ticks_on_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_ticks_down_on()
+          { //! \return  true if X major ticks should mark downwards.
+            return derived().x_ticks_.down_ticks_on_;
+          }
+          // Only need y_ticks_left_on & y_ticks_right_on in 2D, so not defined here.
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label_on(bool cmd)
+          { //! Set true if want to show X-axis label text.
+            //! \details Also switched on by setting label text.
+            //! (on the assumption that if label text is set, display is also wanted,
+            //! but can be switched off if \b not required).
+            derived().x_axis_.label_on_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_label_on()
+          { //! \return  true if want to show X-axis label text.
+            return derived().x_axis_.label_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label_font_size(unsigned int i)
+          { //! Set X axis label font size (svg units, default pixels).
+            derived().x_label_info_.textstyle().font_size(i);
+            // Also duplicated at
+            // derived().x_axis_label_style_.font_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::x_label_font_size()
+          { //! \return  X axis label font size (svg units, default pixels).
+            return derived().x_label_info_.textstyle().font_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_value_font_size(unsigned int i)
+          { //! Set X tick value label font size (svg units, default pixels).
+            derived().x_value_value.textstyle().font_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::x_value_font_size()
+          { //! \return  X tick value label font size (svg units, default pixels).
+            return derived().x_value_value.textstyle().font_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label_font_family(const std::string& family)
+          { //! Set X tick value label font family.
+            derived().x_label_info_.textstyle().font_family(family);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::x_label_font_family()
+          { //! \return  X tick value label font family.
+            return derived().x_label_info_.textstyle().font_family();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_axis_label_color(const svg_color& col)
+          { //! Set X axis label color.
+            derived().image_.g(detail::PLOT_X_LABEL).style().fill_color(col);
+            //derived().image_.g(detail::PLOT_X_LABEL).style().stroke_color(col);
+            // Setting the stroke color produces fuzzy characters :-(
+            // Set BOTH stroke and fill to the same color?
+           return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_axis_label_color()
+          { //! \return  X axis label color.
+            // But only return the fill color.
+            return derived().image_.g(detail::PLOT_X_LABEL).style().fill_color();
+          }
+
+          // X-axis tick label style.
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_values_color(const svg_color& col)
+          { //! Set X axis tick value label color.
+            // Set BOTH stroke and fill to the same color.
+            derived().image_.g(detail::PLOT_X_TICKS_VALUES).style().fill_color(col);
+            //derived().image_.g(detail::PLOT_X_TICK_VALUE_LABELS).style().stroke_color(col);
+            // Setting the stroke color produces fuzzy characters :-(
+            //derived().x_ticks_.color_ = col;
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_ticks_values_color()
+          { //! \return  X-axis ticks value label color.
+            // But only return the fill color.
+            return derived().image_.g(detail::PLOT_X_TICKS_VALUES).style().fill_color();
+            //return x_ticks_.color_ ;
+          }
+
+          // ticks_labels_style  x_ticks
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_values_precision(int p)
+          { //! Set iostream decimal digits precision of data point X values near data points markers.
+            derived().x_ticks_.value_precision_ = p;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_ticks_values_precision()
+          { //! \return  iostream decimal digits precision of data point X values near data points markers.
+            return derived().x_ticks_.value_precision_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_values_ioflags(std::ios_base::fmtflags f)
+          { //! Set iostream format flags of data point X values near data points markers.
+            //! Useful to set hexadecimal, fixed and scientific, (std::ios::scientific).
+            derived().x_ticks_.value_ioflags_ = f;
+            return derived();
+          }
+
+          template <class Derived>
+          std::ios_base::fmtflags axis_plot_frame<Derived>::x_ticks_values_ioflags()
+          { //! \return  iostream format flags of data point X values near data points markers.
+            //! Might be used to set hexadecimal, fixed and scientific, (std::ios::scientific).
+            return derived().x_ticks_.value_ioflags_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_values_font_size(unsigned int i)
+          { //! Set X ticks value label font size (svg units, default pixels).
+            //derived().x_ticks_.value_label_style_.font_size(i);
+            derived().x_value_label_info_.textstyle().font_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::x_ticks_values_font_size()
+          { //! \return  X ticks value label font size (svg units, default pixels).
+            // return derived().x_ticks_.value_label_style_.font_size();
+                   return     derived().x_value_label_info_.textstyle().font_size();
+
+            //return derived().x_ticks_.value_label_info_.font_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_values_font_family(const std::string& family)
+          { //! Set X ticks value label font family.
+            //derived().x_ticks_.value_label_style_.font_family(family); // is effect same as:
+            derived().x_value_label_info_.textstyle().font_family(family);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::x_ticks_values_font_family()
+          { //! \return  X ticks value label font family.
+            return derived().x_ticks_.value_label_style_.font_family();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_ticks_on_window_or_axis(int cmd)
+          { /*!  Set  X ticks on window or axis
+              \arg cmd -1 bottom of plot window,
+              \arg cmd 0 on X axis.
+              \arg cmd +1 top of plot window.
+            */
+            derived().x_ticks_.ticks_on_window_or_on_axis_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_ticks_on_window_or_axis()
+          { //! \return if X axis ticks wanted on the window (rather than on axis).\n
+            //! -1 bottom of plot window, 0 on X axis, +1 top of plot window.
+            return derived().x_ticks_.ticks_on_window_or_on_axis_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label_units_on(bool cmd)
+          { //! Set true if want X axis label to include units (as well as label like "length").
+            //! \see x_label_units which also sets true.
+            derived().x_axis_.label_units_on_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_label_units_on()
+          { //! Set true if want X axis label to include units (as well as label like "length").
+            return derived().x_axis_.label_units_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_labels_side(int place)
+          { /*! Position of labels for major ticks on horizontal X axis line.
+               \arg \c place > 0 labels to left of Y axis line (default),
+               \arg \c place = 0 (false) no major tick labels on Y axis.
+               \arg \c place > 0 labels to right of Y axis line.
+            */
+            derived().x_ticks_.major_value_labels_side_ = place;
+            return derived(); //! \return reference to svg_2d_plot to make chainable.
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_major_labels_side()
+          { //! \return the side for X ticks major value labels.
+            return derived().x_ticks_.major_value_labels_side_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_label_rotation(rotate_style rot)
+          { /*! Set rotation for X ticks major value labels. (Default horizontal).
+               \see rotate_style
+            */
+            derived().x_ticks_.label_rotation_ = rot;
+            return derived();
+          }
+
+          template <class Derived>
+          rotate_style axis_plot_frame<Derived>::x_major_label_rotation()
+          { /*! \return rotation for X ticks major value labels.
+                \see rotate_style
+             */
+            return derived().x_ticks_.label_rotation_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_on(bool cmd)
+          { //! If set true, show a title for the plot.
+            derived().title_on_ = cmd;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::title_on()
+          {//! If true, will show a title for the plot.
+            return derived().title_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_grid_on(bool is)
+          { //! If set true, will include a major X-axis grid.
+            derived().x_ticks_.major_grid_on_ = is;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_major_grid_on()
+          { //! If true, will include a major X-axis grid.
+            return derived().x_ticks_.major_grid_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_minor_grid_on(bool is)
+          { //! If set true, will include a minor X-axis grid.
+            derived().x_ticks_.minor_grid_on_ = is;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_minor_grid_on()
+          {//! If true, will include a minor X-axis grid.
+            return derived().x_ticks_.minor_grid_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::axes_on(bool is)
+          { //! If set true, draw \b both x and y axes (note plural axes).
+            derived().x_axis_.axis_line_on_ = is;
+            derived().y_axis_.axis_line_on_ = is; // No meaning for 1D, but set anyway?
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::axes_on()
+          { //! \return true if \b both x and y axis on.
+            return derived().x_axis_.axis_line_on_ && derived().y_axis_.axis_line_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_axis_on(bool is)
+          { //! If set true, draw a horizontal X-axis line.
+            derived().x_axis_.axis_line_on_ = is;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_axis_on()
+          { //! If true, draw a horizontal X-axis line.
+          // Use X in preference to Y for 1D.
+            return derived().x_axis_.axis_line_on_;
+          }
+
+
+
+          ////////////////////////////////
+
+
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::y_axis_on(bool is)
+          { //! If set true, draw a vertical Y-axis line.
+            derived().y_axis_.axis_line_on_ = is;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::y_axis_on()
+          { //! If true, draw a vertical Y-axis line.
+            // Should be always false for 1D.
+            return derived().y_axis_.axis_line_on_;
+          }
+
+          // enums like PLOT_TITLE provide a std:string like "title"
+          // colors .stroke_color, .stroke_width and font are set in the appropriate g_element.
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::title_color(const svg_color& col)
+          { //! Set the color of any title of the plot.
+            // Function title_color could set both fill (middle) and stroke (outside),
+            // but just setting fill if simplest,
+            // but does not allow separate inside & outside colors.
+            derived().image_.g(PLOT_TITLE).style().fill_color(col);
+            //derived().image_.g(PLOT_TITLE).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::title_color()
+          { //! \return the color of any title of the plot.
+            // Function title_color could get either fill and stroke,
+            // return derived().image_.g(PLOT_TITLE).style().stroke_color();
+            return derived().image_.g(PLOT_TITLE).style().fill_color();
+          }
+
+          //Derived& title_font_width(double width)
+          //{ // Set the width of the font for the title of the plot.
+          // width of text is effectively the boldness.
+          //  // Not useful with current browsers, setting this may cause lower quality graphic fonts
+          //  // perhaps because the font is created using graphics rather than a built-in font.
+          //  derived().image_.g(PLOT_TITLE).style().stroke_width(width);
+          //  return derived();
+          //}
+
+         //Derived& legend_font_width(double width)
+          //{ //! \return  the width of the font for the title of the plot.
+            // width of text is effectively the boldness.
+          //  derived().image_.g(PLOT_LEGEND_TEXT).style().stroke_width(width);
+          //  return derived();
+          //}
+
+          //double legend_font_width()
+          //{ // Set the width of the font for the title of the legend.
+          // Probably not useful at present (se above).
+          //  return derived().image_.g(PLOT_LEGEND_TEXT).style().stroke_width();
+          //}
+          //double legend_font_width()
+          //{ //! \return  the width of the font for the title of the legend.
+          //  return derived().image_.g(PLOT_TITLE).style().stroke_width();
+          //}
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_color(const svg_color& col)
+          { //! Set the color of the title of the legend.
+            // derived().image_.g(PLOT_LEGEND_TEXT).style().stroke_color(col);
+            derived().image_.g(PLOT_LEGEND_TEXT).style().fill_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::legend_color()
+          { //! \return  the color of the title of the legend.
+            // Function legend_color sets only stroke, assuming that 'filled' text is not being used.
+            // (It produces much lower quality fonts on some browsers).
+            return derived().image_.g(PLOT_LEGEND_TEXT).style().fill_color();
+            // return derived().image_.g(PLOT_LEGEND_TEXT).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_background_color(const svg_color& col)
+          { //! Set the background fill color of the legend box.
+            derived().legend_box_.fill(col);
+            derived().image_.g(PLOT_LEGEND_BACKGROUND).style().fill_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::legend_background_color()
+          { //! \return  the background fill color of the legend box.
+            return derived().image_.g(PLOT_LEGEND_BACKGROUND).style().fill_color();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::legend_box_fill_on()
+          { //! \return true if legend box has a background fill color.
+            return derived().legend_box_.fill_on();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::legend_border_color(const svg_color& col)
+          { //! Set the border stroke color of the legend box.
+            derived().legend_box_.stroke(col);
+            derived().image_.g(PLOT_LEGEND_BACKGROUND).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::legend_border_color()
+          { //! \return  the border stroke color of the legend box.
+            return  derived().legend_box_.stroke();
+            // return derived().image_.g(PLOT_LEGEND_BACKGROUND).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::plot_background_color(const svg_color& col)
+          { //! Set the fill color of the plot window background.
+            derived().image_.g(PLOT_WINDOW_BACKGROUND).style().fill_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::plot_background_color()
+          { //! \return  the fill color of the plot window background.
+            return derived().image_.g(PLOT_WINDOW_BACKGROUND).style().fill_color();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::x_axis_position()
+          { //! \return  the position (or intersection with Y-axis) of the X-axis.
+            switch(derived().x_axis_position_)
+            {
+            case top:
+              return "x_axis_position top (all Y values < 0)"; break;
+            case x_intersects_y:
+              return "x_axis_position intersects Y axis (Y range includes zero)"; break;
+            case bottom:
+              return "x_axis_position bottom (all Y values > 0)"; break;
+            default:
+              return "?"; break;
+            }
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_axis_color(const svg_color& col)
+          { //! Set the color of the X-axis line.
+            // Note only stroke color is set.
+            derived().image_.g(PLOT_X_AXIS).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_axis_color()
+          { //! \return  the color of the X-axis line.
+            return derived().image_.g(PLOT_X_AXIS).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::y_axis_color(const svg_color& col)
+          { //! Set the color of the Y-axis line.
+            derived().image_.g(PLOT_Y_AXIS).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::y_axis_color()
+          { //! \return  the color of the Y-axis line.
+            return derived().image_.g(PLOT_Y_AXIS).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label_color(const svg_color& col)
+          { //! Set the color of X-axis label (including any units).
+            // add fill as well PAB Oct 07
+            derived().image_.g(PLOT_X_LABEL).style().fill_color(col);
+            derived().image_.g(PLOT_X_LABEL).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_label_color()
+          { //! \return  the color of X-axis label (including any units).
+            return derived().image_.g(PLOT_X_LABEL).style().fill_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label_width(double width)
+          { //! Set the width (boldness) of X-axis label (including any units).
+            //! (not recommended until browsers implement better).
+            // width of text is effectively the boldness.
+            derived().image_.g(PLOT_X_LABEL).style().stroke_width(width);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_label_width()
+          { //! \return  the width (boldness) of X-axis label (including any units).
+            return derived().image_.g(PLOT_X_LABEL).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::y_label_color(const svg_color& col)
+          { //! Set the color of Y-axis label (including any units).
+            derived().image_.g(PLOT_Y_LABEL).style().fill_color(col);
+            derived().image_.g(PLOT_Y_LABEL).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::y_label_color()
+          { //! \return  the color of Y-axis label (including any units).
+            return derived().image_.g(PLOT_Y_LABEL).style().fill_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_tick_color(const svg_color& col)
+          { //! Set the color of X-axis major ticks.
+            derived().image_.g(PLOT_X_MAJOR_TICKS).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_major_tick_color()
+          { //! \return  the color of X-axis major ticks.
+            return derived().image_.g(PLOT_X_MAJOR_TICKS).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_minor_tick_color(const svg_color& col)
+          { //! Set the color of X-axis minor ticks.
+            derived().image_.g(PLOT_X_MINOR_TICKS).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_minor_tick_color()
+          { //! \return  the color of X-axis minor ticks.
+            return derived().image_.g(PLOT_X_MINOR_TICKS).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_grid_color(const svg_color& col)
+          { //! Set the color of X-axis major grid lines.
+            derived().image_.g(PLOT_X_MAJOR_GRID).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_major_grid_color()
+          { //! \return  the color of X-axis major grid lines.
+            return derived().image_.g(PLOT_X_MAJOR_GRID).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_grid_width(double w)
+          { //! Set the width of X-axis major grid lines.
+            derived().image_.g(PLOT_X_MAJOR_GRID).style().stroke_width(w);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_major_grid_width()
+          { //! \return  the color of X-axis major grid lines.
+            return derived().image_.g(PLOT_X_MAJOR_GRID).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_minor_grid_color(const svg_color& col)
+          { //! Set the color of X-axis minor grid lines.
+            derived().image_.g(PLOT_X_MINOR_GRID).style().stroke_color(col);
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_minor_grid_color()
+          { //! \return  the color of X-axis minor grid lines.
+            return derived().image_.g(PLOT_X_MINOR_GRID).style().stroke_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_minor_grid_width(double w)
+          { //! Set the width of X-axis minor grid lines.
+            derived().image_.g(PLOT_X_MINOR_GRID).style().stroke_width(w);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_minor_grid_width()
+          { //! \return  the width of X-axis minor grid lines.
+            return derived().image_.g(PLOT_X_MINOR_GRID).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_axis_width(double width)
+          { //! Set the width of X-axis lines.
+            derived().image_.g(PLOT_X_AXIS).style().stroke_width(width);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_axis_width()
+          { //! \return  the width of X-axis lines.
+            return derived().image_.g(PLOT_X_AXIS).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::data_lines_width(double width)
+          { //! Set the width of lines joining data points.
+            derived().image_.g(PLOT_DATA_LINES).style().stroke_width(width);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::data_lines_width()
+          { //! \return  the width of lines joining data points.
+            return derived().image_.g(PLOT_DATA_LINES).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label(const std::string& str)
+          { //! Set the text to label the X-axis (and set x_label_on(true)).
+            derived().x_label_info_.text(str);
+            derived().x_axis_.label_on_ = true; // Assume want x_label string displayed.
+            // Might switch label_on false if null string?
+            return derived();
+          }
+
+          template <class Derived>
+          std::string axis_plot_frame<Derived>::x_label()
+          { //! \return  the text to label the X-axis.
+            return derived().x_label_info_.text();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_label_units(const std::string& str)
+          { //! Set the text to add units to the X-axis label.
+            derived().x_units_info_.text(str);
+            derived().x_axis_.label_on_ = true; // Assume want x_label string displayed.
+            return derived();
+          }
+
+          template <class Derived>
+          std::string axis_plot_frame<Derived>::x_label_units()
+          { //! \return  the text to add units to the X-axis label.
+            //! The label will only be shown if  x_label_on() == true.
+            return derived().x_units_info_.text();
+          }
+
+          // y_label not needed in 1D.
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::y_label(const std::string& str)
+          { //! Set the text for the Y-axis label (and set y_label_on(true)).
+            derived().y_label_info_.text(str);
+            derived().y_axis_.label_on_ = true; // Assume want y_label string displayed.
+            return derived();
+          }
+
+          template <class Derived>
+          std::string axis_plot_frame<Derived>::y_label()
+          { //! \return  the text for the Y-axis label.
+            //! The label will only be shown if  y_label_on() == true.
+            return derived().y_label_info_.text();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::y_label_units(const std::string& str)
+          { //! Set the text to add units to the Y-axis label.
+            derived().y_units_info_.text(str);
+            derived().y_axis_.label_on_ = true; // Assume want y_label string displayed.
+            return derived();
+          }
+
+          template <class Derived>
+          std::string axis_plot_frame<Derived>::y_label_units()
+          { //! \return  the text to add units to the X-axis label.
+            return derived().y_units_info_.text();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_values_on(bool b)
+          { //! \return true if values of X data points are shown (for example: 1.23).
+            // (Want override xy_values_on that would otherwise cause overwriting).
+            // So the last values_on setting will prevail.
+            // But this is only defined in 2D
+            //if(derived().xy_values_on())
+            //{ // Would be overwritten by XY pair.
+            //  derived().xy_values_on(false);
+            //}
+            derived().x_values_on_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_values_on()
+          { //! If true, show data point values near data points markers.
+            return derived().x_values_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_values_font_size(unsigned int i)
+          { //! Set font size of data point X values near data points markers.
+            derived().x_values_style_.values_text_style_.font_size(i);
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::x_values_font_size()
+          { //! \return  font size of data point X values near data points markers.
+            return derived().x_values_style_.values_text_style_.font_size();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_values_font_family(const std::string& family)
+          { //! Set font family of data point X values near data points markers.
+            derived().x_values_style_.values_text_style_.font_family(family);
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string& axis_plot_frame<Derived>::x_values_font_family()
+          { //! Set font family of data point X values near data points markers.
+            return derived().x_values_style_.values_text_style_.font_family();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_interval(double inter)
+          { //! Set the interval between X-axis major ticks.
+            derived().x_ticks_.major_interval_ = inter;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_major_interval()
+          { //! \return  the interval between X-axis major ticks.
+            return derived().x_ticks_.major_interval_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_values_color(const svg_color& col)
+          { //! Set the color of data point X values near data points markers.
+            // Function could set both fill (middle) and stroke (outside),
+            // but just setting fill is simplest,
+            // but does not allow separate inside & outside colors.
+            // Might be better to set in x_values_style
+            derived().image_.g(PLOT_X_POINT_VALUES).style().fill_color(col);
+            //derived().image_.g(PLOT_X_POINT_VALUES).style().stroke_color(col);
+
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_values_color()
+          { //! \return  the color of data point X values near data points markers.
+            // Function could get either fill and stroke,
+            // return derived().image_.g(PLOT_X_POINT_VALUES).style().stroke_color();
+            return derived().image_.g(PLOT_X_POINT_VALUES).style().fill_color();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_values_rotation(rotate_style rotate)
+          { //! \return  the rotation (rotate_style) of data point X values near data points markers.
+            //! (Degrees: 0 to 360 in 45 steps).
+            derived().x_values_style_.value_label_rotation_ = rotate;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_values_rotation()
+          { //! \return  the rotation of data point X values near data points markers.
+            return derived().x_values_style_.value_label_rotation_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_values_precision(int p)
+          { //! Set iostream decimal digits precision of data point X values near data points markers.
+            derived().x_values_style_.value_precision_ = p;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_values_precision()
+          { //! \return  iostream decimal digits precision of data point X values near data points markers.
+            return derived().x_values_style_.value_precision_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_values_ioflags(std::ios_base::fmtflags f)
+          { //! Set iostream format flags of data point X values near data points markers.
+            //! Useful to set hexadecimal, fixed and scientific, (std::ios::scientific).
+            derived().x_values_style_.value_ioflags_ = f;
+            return derived();
+          }
+
+          template <class Derived>
+          std::ios_base::fmtflags axis_plot_frame<Derived>::x_values_ioflags()
+          { //! \return  iostream format flags of data point X values near data points markers.
+            //! Might be used to set hexadecimal, fixed and scientific, (std::ios::scientific).
+            return derived().x_values_style_.value_ioflags_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_plusminus_on(bool b)
+          { //! Set if to append std_dev estimate to data point X values near data points markers.
+            //! (May not be implemented yet).
+            derived().x_values_style_.plusminus_on_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_plusminus_on()
+          { //! \return  if to append std_dev estimate to data point X values near data points markers.
+            //! (May not be implemented yet).
+            return derived().x_values_style_.plusminus_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_plusminus_color(const svg_color& col)
+          { //! Set the color of X std_dev of value, for example, the color of 0.02 in "1.23 +-0.02 (9)".
+            derived().x_values_style_.plusminus_color_ = col;
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_plusminus_color()
+          { //! Get the color of X std_dev of value, for example, the color of 0.02 in "1.23 +-0.02 (9)".
+            return derived().x_values_style_.plusminus_color_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_addlimits_on(bool b)
+          { //! Set if to append confidence limits to data point X values near data points markers.
+            //! (May not be implemented yet).
+            derived().x_values_style_.addlimits_on_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_addlimits_on()
+          { //! \return  if to append confidence limits to data point X values near data points markers.
+            //! (May not be implemented yet).
+            return derived().x_values_style_.addlimits_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_addlimits_color(const svg_color& col)
+          { //! Set the color of X confidence limits value, for example, the color of "<1.23 , 1.34>".
+            derived().x_values_style_.addlimits_color_ = col;
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_addlimits_color()
+          { //! Get the color of X confidence limits of value, for example, the color of "<1.23 , 1.34>"".
+            return derived().x_values_style_.addlimits_color_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_df_on(bool b)
+          { //! Set true if to append a degrees of freedom estimate to data point X values near data points markers.
+            derived().x_values_style_.df_on_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_df_on()
+          { //! \return true if to append a degrees of freedom estimate to data point X values near data points markers.
+            //! (May not be implemented yet).
+            return derived().x_values_style_.df_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_df_color(const svg_color& col)
+          { //! Set the color of X degrees of freedom, for example, the color of 9 in "1.23 +-0.02 (9)".
+            derived().x_values_style_.df_color_ = col;
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_df_color()
+          { //! Get the color of X degrees of freedom, for example, the color of 9 in "1.23 +-0.02 (9)".
+            return derived().x_values_style_.df_color_;
+          }
+
+          // Additional for Meas
+
+         template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_id_on(bool b)
+          { //! Set true if to append a id or name to data point X values near data points markers.
+            //! (May not be implemented yet).
+            derived().x_values_style_.id_on_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_id_on()
+          { //! \return true if to append an ID or name to data point X values near data points markers.
+            //! (May not be implemented yet).
+            return derived().x_values_style_.id_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_id_color(const svg_color& col)
+          { //! Set the color of X ID or name, for example, the color of text in "My_id".
+            derived().x_values_style_.id_color_ = col;
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_id_color()
+          { //! Get the color of X ID or name, for example, the color of text in "My_id".
+            return derived().x_values_style_.id_color_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_datetime_on(bool b)
+          { //! Set true if to append a datetime to data point X values near data points markers.
+            //! (May not be implemented yet).
+            derived().x_values_style_.datetime_on_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_datetime_on()
+          { //! \return true if to append a ID or name to data point X values near data points markers.
+            //! (May not be implemented yet).
+            return derived().x_values_style_.datetime_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_datetime_color(const svg_color& col)
+          { //! Set the color of X point datetime, for example, the color of text in "2004-Jan-1 05:21:33.20".
+            derived().x_values_style_.datetime_color_ = col;
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_datetime_color()
+          { //! Get the color of X point date time, for example, the color of text in "2004-Jan-1 05:21:33.20".
+            return derived().x_values_style_.datetime_color_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_order_on(bool b)
+          { //! Set true if to append an order # to data point X values near data points markers.
+            derived().x_values_style_.order_on_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_order_on()
+          { //! \return true if to append an order # to data point X values near data points markers.
+            return derived().x_values_style_.order_on_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_order_color(const svg_color& col)
+          { //! Set the color of X point order in sequence, for example, #3.
+            derived().x_values_style_.order_color_ = col;
+            return derived();
+          }
+
+          template <class Derived>
+          svg_color axis_plot_frame<Derived>::x_order_color()
+          { //! Get the color of X point order in sequence, for example, #3.
+            return derived().x_values_style_.order_color_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_decor(const std::string& pre, const std::string& sep, const std::string& suf)
+          { /*! Set prefix, separator and suffix for x_style
+            \note if you want a space, you must use a Unicode space "\ ",
+            for example, ",\ " rather than just ", ".
+            */
+            derived().x_values_style_.prefix_ = pre;
+            derived().x_values_style_.separator_ = sep;
+            derived().x_values_style_.suffix_ = suf;
+            return derived();
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::x_prefix()
+          { //! Get the prefix (only used if separator != "")
+            return derived().x_values_style_.prefix_;
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::x_suffix()
+          { //! Get the suffix (only used if separator != "")
+            return derived().x_values_style_.suffix_;
+          }
+
+          template <class Derived>
+          const std::string axis_plot_frame<Derived>::x_separator()
+          { //! Get separator (also controls use of the prefix & suffix - they are only used if separator != "").
+            //! Note For a space, you must use a Unicode space "\ ",
+            //! for example, ",\ " rather than ", ".
+            return derived().x_values_style_.separator_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_tick_length(double length)
+          { //! Set length of X major ticks.
+            derived().x_ticks_.major_tick_length_ = length;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_major_tick_length()
+          {//! \return  length of X major ticks.
+            return derived().x_ticks_.major_tick_length_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_tick_width(double width)
+          { //! Set width of X major ticks.
+            derived().x_ticks_.major_tick_width_ = width; // Redundant?
+            derived().image_.g(PLOT_X_MAJOR_TICKS).style().stroke_width(width);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_major_tick_width()
+          {//! \return  width of X major ticks.
+            return derived().image_.g(PLOT_X_MAJOR_TICKS).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_minor_tick_length(double length)
+          { //! Set length of X minor ticks.
+            derived().x_ticks_.minor_tick_length_ = length;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_minor_tick_length()
+          { //! \return  length of X minor ticks.
+            return derived().x_ticks_.minor_tick_length_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_minor_tick_width(double width)
+          { //! Set width of X minor ticks.
+            derived().x_ticks_.minor_tick_width_ = width;
+            derived().image_.g(PLOT_X_MINOR_TICKS).style().stroke_width(width);
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_minor_tick_width()
+          { //! \return  width of X minor ticks.
+            // return derived().x_minor_tick_width_; // should be the same but store in stroke_width is definitive.
+            return derived().image_.g(PLOT_X_MINOR_TICKS).style().stroke_width();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_major_tick(double d)
+          { //! Set interval (Cartesian units) between major ticks.
+            derived().x_ticks_.major_interval_ = d;
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_major_tick()
+          { //! \return  interval (Cartesian units) between major ticks.
+            return derived().x_ticks_.major_interval_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_minor_interval(double interval)
+          { //! Set interval between X-axis minor ticks.
+            // aka x_minor_tick
+            derived().x_ticks_.minor_interval_ = interval;
+            return derived();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_num_minor_ticks(unsigned int num)
+          { //! Set number of X-axis minor ticks between major ticks.
+            derived().x_ticks_.num_minor_ticks_ = num;
+            return derived();
+          }
+
+          template <class Derived>
+          unsigned int axis_plot_frame<Derived>::x_num_minor_ticks()
+          { //! \return  number of X-axis minor ticks between major ticks.
+            //! Note: NOT float or double!
+            return derived().x_ticks_.num_minor_ticks_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_range(double min_x, double max_x)
+          { //! Set the range of values on the X-axis.
+            //! The minimum and maximum values must be finite and not too near
+            //! to the minima or maxima that can be represented by floating point doubles,
+            //! and the range must not be too small.
+            if (!boost::math::isfinite(min_x))
+            {
+              throw std::runtime_error("X range: min not finite!");
+            }
+            if (!boost::math::isfinite(max_x))
+            {
+              throw std::runtime_error("X range: max not finite!");
+            }
+            if(max_x <= min_x)
+            { // max_x <= min_x.
+              std::stringstream message("X range: max <= min! ");
+              message << max_x << " <= " << min_x << std::ends;
+              throw std::runtime_error(message.str());
+              //throw std::runtime_error("X range: max <= min!");
+            }
+            if( (abs(max_x - min_x) < std::numeric_limits<double>::epsilon() * 1000 * abs(max_x))
+              || (abs(max_x - min_x) < std::numeric_limits<double>::epsilon() * 1000 * abs(min_x))
+              )
+            { // Range too small to display.
+              throw std::runtime_error("X range too small!" );
+            }
+            derived().x_axis_.min_ = min_x;
+            derived().x_axis_.max_ = max_x;
+            //derived().x_ticks_.max_ = min_x;
+            //derived().y_ticks_.max_ = max_x;
+            // done in calculate_plot_window, so need to duplicate here.
+            derived().x_autoscale_ = false; // Because explicit range has just been set.
+            return derived();
+          }
+
+          template <class Derived>
+          std::pair<double, double> axis_plot_frame<Derived>::x_range()
+          { //! \return  the range of values on the X-axis.
+            //! (Need to use boost::svg::detail::operator<< to display this).
+            std::pair<double, double> r;
+            r.first = derived().x_axis_.min_;
+            r.second = derived().x_axis_.max_;
+            return r;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_min(double min_x)
+          { //! Set the minimum value on the X-axis.
+            // Not useful to check here that x_max_ > x_min_ because may not have set x_min_ yet.
+            derived().x_axis_.min_ = min_x;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_min()
+          { //! \return  the minimum value on the X-axis.
+            //! (Can also get both minimum and maximum as a std::pair).
+            return derived().x_axis_.min_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_max(double x)
+          { //! Set the maximum value on the X-axis.
+            // Not useful to check here that x_max_ > x_min_ because may not have set x_min_ yet.
+            derived().x_axis_.max_ = x;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::x_max()
+          { //! \return  the maximum value on the X-axis.
+            //! (Can also get both minimum and maximum as a std::pair).
+            return derived().x_axis_.max_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::autoscale_check_limits(bool b)
+          { //! Set to check that values used for autoscale are within limits.
+            //! Default is true, but can switch off checks for speed.
+            derived().autoscale_check_limits_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::autoscale_check_limits()
+          { //! \return  to check that values used for autoscale are within limits.
+            //! Default is true, but can switch off checks for speed.
+            return derived().autoscale_check_limits_;
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_autoscale()
+          { //! \return  true if to use autoscale value for X-axis.
+           return derived().x_autoscale_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_autoscale(bool b)
+          { //! Set true if to use autoscale values for X-axis.
+             if (b && derived().x_auto_tick_interval_ < 0)
+             { // No autoscale values have been calculated, so not safe to make x_autoscale true.
+                throw std::runtime_error("X autoscale has not been calculated yet!" );
+             }
+            derived().x_autoscale_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::autoscale()
+          { //! \return true if to use autoscale values for X-axis.
+            //! autoscale() is same as x_autoscale.
+           return derived().x_autoscale_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::autoscale(bool b)
+          { //! Set whether to use X autoscaled values.
+            //! Same as x_autoscale, and used by boxplot too.
+             if (derived().x_auto_tick_interval_ < 0)
+             { // No autoscale values have been calculated, so not safe to make x_autoscale true.
+                throw std::runtime_error("X-axis autoscale has not been calculated yet!" );
+             }
+            derived().x_autoscale_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::autoscale_plusminus(double pm)
+          { //! Set how many std_dev or standard deviation to allow for ellipse when autoscaling.
+            //! Default is 3 for 99% confidence.
+            derived().autoscale_plusminus_ = pm;
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::autoscale_plusminus()
+          { //! \return  how many std_dev or standard deviation to allow for ellipse when autoscaling.
+            //! Default is 3 for 99% confidence.
+            return derived().autoscale_plusminus_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::confidence(double alpha)
+          { //! Set alpha for displaying confidence intervals.
+            //! Default is 0.05 for 95% confidence.
+            if (alpha <= 0.)
+            { // Warn and leave alpha_ unchanged.
+               std::cout << "alpha must be > 0." << std::endl;
+            }
+            else if (alpha > 0.5)
+            { // Warn and leave alpha_ unchanged.
+               std::cout << "alpha must be fraction < 0.5 (for example, 0.05 for 95% confidence)" << std::endl;
+            }
+            else
+            {
+              derived().alpha_ = alpha;
+            }
+            return derived();
+          }
+
+          template <class Derived>
+          double axis_plot_frame<Derived>::confidence()
+          { //! \return  alpha for displaying confidence intervals.
+            //! Default is 0.05.
+            return derived().alpha_;
+          }
+
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_autoscale(std::pair<double, double> p)
+          { //! Set to use X min & max pair of double values to autoscale X-axis.
+            scale_axis(p.first, p.second, // double min and max from pair.
+              &derived().x_auto_min_value_, &derived().x_auto_max_value_, &derived().x_auto_tick_interval_, &derived().x_auto_ticks_,
+              derived().autoscale_check_limits_, derived().autoscale_plusminus_,
+              derived().x_include_zero_, derived().x_tight_, derived().x_min_ticks_, derived().x_steps_);
+            derived().x_autoscale_ = true; // Default to use any calculated values?
+            return derived();
+          } // autoscale(pair<double, double> p)
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_with_zero(bool b)
+          { //! Set X-axis autoscale to include zero (default = false).
+            //! Must preceed x_autoscale(data) call.
+            derived().x_include_zero_ = b;
+            return derived();
+          }
+
+          template <class Derived>
+          bool axis_plot_frame<Derived>::x_with_zero()
+          { //! \return  true if X-axis autoscale to include zero (default = false).
+           return derived().x_include_zero_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_min_ticks(int min_ticks)
+          { //! Set X-axis autoscale to include at least minimum number of ticks (default = 6).
+            //! Must preceed x_autoscale(data) call.
+            derived().x_min_ticks_ = min_ticks;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_min_ticks()
+          { //! \return  X-axis autoscale minimum number of ticks.
+           return derived().x_min_ticks_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_steps(int steps)
+          { /*! Set autoscale to set ticks in steps multiples of:\n
+             2,4,6,8,10, if 2\n
+             or 1,5,10 if 5\n
+             or 2,5,10 if 10.\n
+             default = 0 (none).
+             \note: Must \b preceed x_autoscale(data) call).
+             */
+            derived().x_steps_ = steps;
+            return derived();
+          }
+
+          template <class Derived>
+          int axis_plot_frame<Derived>::x_steps()
+          { //! \return  autoscale to set ticks in steps.
+           return derived().x_steps_;
+          }
+
+          template <class Derived>
+          Derived& axis_plot_frame<Derived>::x_tight(double tight)
+          { //! Set tolerance to autoscale to permit data points slightly outside both end ticks.
+            //! default 0.
+            //! Must preceed x_autoscale(data) call.
+            derived().x_tight_ = tight;
+            return derived();
+          }
+
+         template <class Derived>
+         double axis_plot_frame<Derived>::x_tight()
+         { //! \return  tolerance given to autoscale to permit data points slightly outside both end ticks.
+           return derived().x_tight_;
+         }
+
+         template <class Derived>
+         double axis_plot_frame<Derived>::x_auto_min_value()
+         { //! \return  the X-axis minimum value computed by autoscale.
+           return derived().x_auto_min_value_;
+         }
+
+         template <class Derived>
+         double axis_plot_frame<Derived>::x_auto_max_value()
+         { //! \return  the X-axis maximum value computed by autoscale.
+           return derived().x_auto_max_value_;
+         }
+
+         template <class Derived>
+         double axis_plot_frame<Derived>::x_auto_tick_interval()
+         { //! \return  the X-axis major tick interval computed by autoscale.
+           return derived().x_auto_tick_interval_;
+         }
+
+        template <class Derived>
+        int axis_plot_frame<Derived>::x_auto_ticks()
+        { //! \return  the X-axis number of major ticks computed by autoscale.
+         return derived().x_auto_ticks_;
+        }
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::limit_color(const svg_color& col)
+        { //! Set the color for 'at limit' point stroke color.
+          // Need to set the series
+          derived().image_.g(detail::PLOT_LIMIT_POINTS).style().stroke_color(col);
+          // derived().serieses_[0].limit_point_color(col); // Would require to add some data first!
+          return derived();
+        }
+
+        template <class Derived>
+        svg_color axis_plot_frame<Derived>::limit_color()
+        { //! \return  the color for the 'at limit' point stroke color.
+          return derived().image_.g(detail::PLOT_LIMIT_POINTS).style().stroke_color();
+        }
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::limit_fill_color(const svg_color& col)
+        { //! Set the color for 'at limit' point fill color.
+          derived().image_.g(detail::PLOT_LIMIT_POINTS).style().fill_on(true);
+          derived().image_.g(detail::PLOT_LIMIT_POINTS).style().fill_color(col);
+          //derived().serieses_[0].limit_point_style_.fill_color(col);
+          return derived();
+        }
+
+        template <class Derived>
+        svg_color axis_plot_frame<Derived>::limit_fill_color()
+        { //! \return  the color for the 'at limit' point fill color.
+          return derived().image_.g(detail::PLOT_LIMIT_POINTS).style().fill_color();
+        }
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::one_sd_color(const svg_color& col)
+        { //! Set the color for the one standard deviation (~67% confidence) ellipse fill.
+          derived().image_.g(detail::PLOT_DATA_UNC1).style().fill_on(true);
+          derived().image_.g(detail::PLOT_DATA_UNC1).style().fill_color(col);
+          derived().image_.g(detail::PLOT_DATA_UNC1).style().stroke_color(blank);
+          return derived();
+        }
+
+       template <class Derived>
+       svg_color axis_plot_frame<Derived>::one_sd_color()
+       { //! \return Color for the one standard deviation (~67% confidence) ellipse fill.
+         return derived().image_.g(detail::PLOT_DATA_UNC1).style().fill_color();
+       }
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::two_sd_color(const svg_color& col)
+        { //! Set the color for two standard deviation (~95% confidence) ellipse fill.
+          derived().image_.g(detail::PLOT_DATA_UNC2).style().fill_on(true);
+          derived().image_.g(detail::PLOT_DATA_UNC2).style().fill_color(col);
+          derived().image_.g(detail::PLOT_DATA_UNC2).style().stroke_color(blank);
+          return derived();
+        }
+
+       template <class Derived>
+       svg_color axis_plot_frame<Derived>::two_sd_color()
+       { //! \return Color for two standard deviation (~95% confidence) ellipse fill.
+         return derived().image_.g(detail::PLOT_DATA_UNC2).style().fill_color();
+       }
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::three_sd_color(const svg_color& col)
+        { //! Set the color for three standard deviation (~99% confidence) ellipse fill.
+          derived().image_.g(detail::PLOT_DATA_UNC3).style().fill_on(true);
+          derived().image_.g(detail::PLOT_DATA_UNC3).style().fill_color(col);
+          derived().image_.g(detail::PLOT_DATA_UNC3).style().stroke_color(blank);
+          return derived();
+        }
+
+       template <class Derived>
+       svg_color axis_plot_frame<Derived>::three_sd_color()
+       { //! \return Color for three standard deviation (~99% confidence) ellipse fill.
+         return derived().image_.g(detail::PLOT_DATA_UNC3).style().fill_color();
+       }
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::draw_note(double x, double y, std::string note, rotate_style rot /*= horizontal*/, align_style al/* = center_align*/, const svg_color& col /* black */, text_style& tsty/* = no_style*/)
+        { /*! \brief Annotate plot with a  text string (perhaps including Unicode), putting note at SVG Coordinates X, Y.
+            \details Defaults color black, rotation horizontal and align = center_align
+            Using center_align is recommended as it will ensure that will center correctly
+            (even if original string is made much longer because it contains Unicode,
+            for example Greek or math symbols, taking about 6 characters per symbol)
+            because the render engine does the centering.
+          */
+           g_element* g = &(derived()).image_.add_g_element(); // New group.
+           g->style().fill_color(col); // Set its color
+           g->push_back(new text_element(x, y, note, tsty, al, rot)); // Add to document image.
+          // No checks on X or Y - leave to SVG to not draw outside image.
+          // Could warn if X and/or Y outside - but even if OK, then text could still stray outside image.
+          return derived();
+        } // void draw_note()
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::draw_line(double x1, double y1, double x2, double y2, const svg_color& col /* black */)
+        { /*! \brief Annotate plot with a line from SVG Coordinates X1, Y1 to X2, Y2.
+              \details Default color black.
+          */
+          g_element* g = &(derived()).image_.add_g_element(); // New group.
+          g->style().stroke_color(col);
+          //g->style().width(w); // todo
+          g->push_back(new line_element(x1, y1, x2, y2));
+          // No checks on X or Y - leave to SVG to not draw outside image.
+          // Could warn if X and/or Y outside ?
+          return derived();
+        } // void draw_line()
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::draw_plot_line(double x1, double y1, double x2, double y2, const svg_color& col /* black */)
+        { /*! \brief Annotate plot with a line from user's Cartesian Coordinates X1, Y1 to X2, Y2.
+              \details For example, -10, -10, +10, +10, Default color black.
+          */
+          derived().calculate_plot_window(); // To ensure the scale and shift are setup for transform.
+          // It would be better to store the line (and curve and text) information like plot data series to
+          // ensure that transform works correctly.
+          // This assumes that the notes, lines and curves are the last item before the write.
+          transform_point(x1, y1);
+          transform_point(x2, y2);
+          g_element* g = &(derived()).image_.add_g_element(); // New group.
+          g->style().stroke_color(col);
+          g->push_back(new line_element(x1, y1, x2, y2));
+          // No checks on X or Y - leave to SVG to not draw outside image.
+          // Actually we want to use clip_path for the plot area.
+          // Could warn if X and/or Y outside ?
+          return derived();
+        } // void draw_plot_line()
+
+        template <class Derived>
+        Derived& axis_plot_frame<Derived>::draw_plot_curve(double x1, double y1, double x2, double y2, double x3, double y3, const svg_color& col /* black */)
+        { /*! \brief Annotate plot with a line from user's Cartesian Coordinates X1, Y1 via X2, Y2 to X3, Y3.
+              \details For example, -10, -10, +10, +10, Default color black.
+          */
+          derived().calculate_plot_window(); // To ensure the scale and shift are setup for transform.
+          // It would be better to store the line (and curve and text) information like plot data series to
+          // ensure that transform works correctly.
+          // This assumes that the notes, lines and curves are the last item before the write.
+          transform_point(x1, y1);
+          transform_point(x2, y2);
+          transform_point(x3, y3);
+          g_element* g = &(derived()).image_.add_g_element(); // New group.
+          g->style().stroke_color(col);
+          g->push_back(new qurve_element(x1, y1, x2, y2, x3, y3));
+          // No checks on X or Y - leave to SVG to not draw outside image.
+          // Actually we want to use clip_path for the plot area.
+          // Could warn if X and/or Y outside ?
+          return derived();
+        } // void draw_plot_curve
+
+
+
+      } // detail
+    } // svg
+  } // boost
+
+#endif BOOST_SVG_AXIS_PLOT_FRAME_IPP
Added: sandbox/SOC/2007/visualization/boost/svg_plot/impl/svg_1d_plot.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/impl/svg_1d_plot.ipp	2012-08-29 14:07:32 EDT (Wed, 29 Aug 2012)
@@ -0,0 +1,795 @@
+/*!
+  \file
+  \brief Create 1D plots in Scalable Vector Graphic (SVG) format.
+  \details Definitions
+ */
+
+// svg_1d_plot.ipp
+// Copyright Jacob Voytko 2007
+// Copyright Paul A. Bristow 2008, 2009, 2011
+
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_SVG_SVG_1D_PLOT_IPP
+#define BOOST_SVG_SVG_1D_PLOT_IPP
+
+#include <boost/svg_plot/svg_1d_plot.hpp>
+
+namespace boost
+{
+namespace svg
+{
+
+//! class svg_1d_plot_series Constructor.
+template <typename C> //! \tparam C an iterator into STL container: array, vector<double>, vector<unc>, vector<Meas> set, map ...
+svg_1d_plot_series::svg_1d_plot_series(C begin, C end, const std::string& title)
+: // Constructor.
+title_(title),
+point_style_(black, blank, 5, vertical_line), // Default point style.
+limit_point_style_(lightgrey, red, 10, cone), // Default limit (inf or NaN) point style.
+//limit_point_style_(lightgrey, whitesmoke, 10, cone), // Default limit (inf or NaN) point style.
+line_style_(black, blank, 2, false, false) // Default line style, black, no fill, width, line_on, bezier_on false
+{
+  /*
+    cout << "typeid(C).name() = " << typeid(C).name() << endl;
+    typeid(C).name() =
+    class boost::transform_iterator
+    <
+      class boost::svg::detail::unc_1d_convert, class std::_Vector_const_iterator
+      <
+        class std::_Vector_val
+        <
+          class boost::svg::unc, class std::allocator
+          <
+            class boost::svg::unc
+          >
+        >
+      >,
+      struct boost::use_default, struct boost::use_default
+    >
+  */
+
+  for(C i = begin; i != end; ++i)
+  {  // Might be useful to have defaults for begin and end? But unclear how.
+    //double temp = *i; // assume type is just double.
+    //boost::svg::unc temp = *i; // Assumes unc type.
+    // So use auto to automatically make temp the right type.
+
+    auto temp = *i; // Should provide double, unc, meas ... type.
+
+    //cout << "typeid(temp).name() = " << typeid(temp).name() << endl;
+    //   typeid(temp).name() = class Meas
+    //   typeid(temp).name() = class boost::svg::unc
+    if(detail::is_limit(temp.value()))
+    {
+      series_limits_.push_back(temp.value()); // 'limit' values: too big, too small or NaN.
+      // This assumes that uncertainty info is meaningless?
+    }
+    else
+    {
+      series_.push_back(temp); // Normal 'OK to plot' data values (including uncertainty info).
+      // Should copy name and other info too if applicable.
+    }
+  }
+} // svg_plot_series constructor.
+
+// Definitions of svg_plot_series Member Functions.
+svg_1d_plot_series& svg_1d_plot_series::fill_color(const svg_color& col_)
+{ //! Set fill color for plot point marker(s) (chainable).
+  point_style_.fill_color_ = col_;
+  return *this; //! \return reference to svg_1d_plot_series to make chainable.
+}
+
+svg_1d_plot_series& svg_1d_plot_series::stroke_color(const svg_color& col_)
+{ //! Set stroke color for plot point marker(s) (chainable).
+  point_style_.stroke_color_ = col_;
+  return *this; //! \return reference to svg_1d_plot_series to make chainable.
+}
+
+svg_1d_plot_series& svg_1d_plot_series::shape(point_shape shape_)
+{ //! Set shape for plot point marker(s) (chainable).
+  point_style_.shape_ = shape_;
+  return *this; //! \return reference to svg_1d_plot_series to make chainable.
+}
+
+point_shape svg_1d_plot_series::shape()
+{ //! \return  shape for plot point marker(s).
+  return point_style_.shape_;
+}
+
+svg_1d_plot_series& svg_1d_plot_series::symbols(const std::string s)
+{ //! Set symbol for plot point marker(s).
+  point_style_.symbols_ = s;
+  return *this; //! \return reference to svg_1d_plot_series to make chainable.
+}
+
+svg_1d_plot_series& svg_1d_plot_series::size(int size_)
+{ //! Set size of plot point marker(s).
+  //point_style_.size_ = size_;
+  //point_style_.symbols_style_.font_size(i); // in case using a symbol.
+  point_style_.size(size_);
+  return *this; //! \return reference to svg_1d_plot_series to make chainable.
+}
+
+int svg_1d_plot_series::size()
+{ //! \return  size of plot point marker(s).
+  return point_style_.size();
+}
+
+const std::string svg_1d_plot_series::symbols()
+{ //! \return  symbol for plot point marker(s).
+  return point_style_.symbols_;
+}
+
+svg_1d_plot_series& svg_1d_plot_series::line_color(const svg_color& col_)
+{ //! Set color of any line joining plot points.
+  line_style_.stroke_color_ = col_;
+  return *this; // Make chainable.
+}
+
+svg_1d_plot_series& svg_1d_plot_series::line_width(double wid_)
+{ /*! Set width of any line joining plot points.
+   \return @c *this to make chainable.
+   */
+  line_style_.width_ = wid_;
+  return *this; // Make chainable.
+}
+
+double svg_1d_plot_series::line_width()
+{ //! \return  Width of any line joining plot points.
+  return line_style_.width_;
+}
+
+svg_1d_plot_series& svg_1d_plot_series::line_on(bool on_)
+{ /*! Set @c true if to draw a line joining plot points.
+   \return @c *this to make chainable.
+   */
+  line_style_.line_on_ = on_;
+  return *this; // Make chainable.
+}
+
+bool svg_1d_plot_series::line_on()
+{ //! \return @c true if to draw a line joining plot points.
+  return line_style_.bezier_on_;
+}
+
+svg_1d_plot_series& svg_1d_plot_series::bezier_on(bool on_)
+{ //! Set @c true if to draw bezier curved line joining plot points.
+  line_style_.bezier_on_ = on_;
+  return *this; // Make chainable.
+}
+
+bool svg_1d_plot_series::bezier_on()
+{ //! \return @c true if to draw bezier curved line joining plot points.
+  return line_style_.bezier_on_;
+}
+
+size_t svg_1d_plot_series::series_count()
+{ //! \return Number of normal 'OK to plot' data values in data series.
+  return series_.size();
+}
+
+size_t svg_1d_plot_series::series_limits_count()
+{ //!  \return Number of  'at limit' values: too big, too small or NaN data values in data series.
+  return series_limits_.size();
+}
+
+svg_1d_plot_series& svg_1d_plot_series::limit_point_color(const svg_color& col_)
+{ //! Set of stroke color of 'at limits' points.
+  limit_point_style_.stroke_color_ = col_;
+  return *this; // Make chainable.
+}
+
+void svg_1d_plot::update_image()
+{ //! Calls functions to add all plot information to the image, including
+  //! plot window, axes, ticks, labels, grids, legend, and finally all the data series.
+
+  clear_all(); // Removes all elements that will show up in a subsequent draw.
+
+  // Draw plot background.
+  image_.g(detail::PLOT_BACKGROUND).push_back(
+    new rect_element(0, 0, image_.x_size(),  image_.y_size()));
+
+  calculate_plot_window();
+  calculate_transform();
+  draw_title(); // Call after above to the plot_x and y are defined.
+  if(x_axis_.axis_line_on_)
+  {
+    draw_axes();
+  }
+  if(legend_on_)
+  {
+    draw_legend();
+  }
+  if(x_axis_.label_on_)
+  {
+    draw_x_axis_label();
+  }
+  double y(0.); // All 1-D points are plotted are on the horizontal X axis (y = 0) axis.
+  transform_y(y);
+  if ((y < plot_top_) || (y > plot_bottom_))
+  { // Should never happen!
+    throw std::runtime_error("transform_y(y=0) outside plot window!");
+  }
+
+  for(unsigned int i = 0; i < serieses_.size(); ++i)
+  { // Plot the data points for each of the data series.
+    g_element& g_ptr = image_.g(detail::PLOT_DATA_POINTS).add_g_element();
+    g_ptr.style().stroke_color(serieses_[i].point_style_.stroke_color_);
+    g_ptr.style().fill_color(serieses_[i].point_style_.fill_color_);
+
+    for(unsigned int j = 0; j < serieses_[i].series_.size(); ++j)
+    { // Draw jth point for ith serieses.
+      Meas ux = serieses_[i].series_[j];
+      // unc<false> ux = serieses_[i].series_[j];
+      double x = ux.value();
+      // TODO symbols are offset downwards because
+      // the origin of the point is the top left of the glyph.
+      // Need to offset by the height and width of the font size?
+      transform_x(x);
+      if((x >= plot_left_) && (x <= plot_right_)) // Check point is inside plot_window.
+      // May need a margin here to avoid points just over the window not being shown.
+      {
+        draw_plot_point(x, y, g_ptr, serieses_[i].point_style_, ux, Meas()); // Marker.
+        // (y uncertainty is zero for 1d X values).
+        // draw_plot_point(x, y, g_ptr, serieses_[i].point_style_, ux, unc<false>()); // Marker.
+        // (y uncertainty is zero).
+        if (x_values_on_)
+        { // Show the value (& perhaps uncertainty) of the data point too.
+          g_element& g_ptr_v = image_.g(detail::PLOT_X_POINT_VALUES).add_g_element();
+          draw_plot_point_value(x, y, g_ptr_v, x_values_style_, serieses_[i].point_style_, ux);
+          // TODO Might separate X and Y colors?
+        }
+        else
+        { // Don't plot anything?  Might leave a marker to show an 'off the scale' value?
+        }
+      } // if in window
+    } // for j
+  } // for i all normal
+
+  // Draw all the 'bad' or at_limit points.
+  for(unsigned int i = 0; i < serieses_.size(); ++i)
+  {
+    g_element& g_ptr = image_.g(detail::PLOT_LIMIT_POINTS);
+
+    for (unsigned int j = 0; j != serieses_[i].series_limits_.size(); ++j)
+    {
+      double x = serieses_[i].series_limits_[j];
+      if (limit_NaN(x))
+      { // is NaN rather than too big or too small.
+        double x = 0.;
+        transform_x(x);
+        // If include zero, OK, else plot on left or right as appropriate.
+        if (x < plot_left_)
+        {
+          x = plot_left_;
+        }
+        else if (x > plot_right_)
+        {
+          x = plot_right_;
+        }
+        //else X axis includes zero, so x is OK.
+        draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, Meas(), Meas());
+        // draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc<false>(), unc<false>());
+      }
+      else
+      { // Not NaN
+        transform_x(x);
+        if (x < plot_left_)
+        {
+          x = plot_left_;
+        }
+        else if (x > plot_right_)
+        {
+          x = plot_right_;
+        }
+        // else is inside plot window, so draw a limit point marker.
+        // draw_plot_point(x, y, g_ptr, plot_point_style(lightgray, whitesmoke, s, cone)); default.
+        serieses_[i].limit_point_style_.stroke_color_ = image_.g(detail::PLOT_LIMIT_POINTS).style().stroke_color();
+        serieses_[i].limit_point_style_.fill_color_ = image_.g(detail::PLOT_LIMIT_POINTS).style().fill_color();
+        // This is a kludge.  limit_point_style_ should probably be common to all data series.
+
+        draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, Meas(), Meas());
+        //draw_plot_point(x, y, g_ptr, serieses_[i].limit_point_style_, unc<false>(), unc<false>());
+      }
+    } // for j
+  } // for i limits point
+} //   void update_image()
+
+  /* Default constructor.
+      Many ( but not all - see below) default values here.
+      See documentation for default settings rationale.
+  */
+  svg_1d_plot::svg_1d_plot()  :
+  title_style_(18, "Verdana", "", ""),  // last "bold" ?
+  legend_style_(14, "Verdana", "", ""), // 2nd "italic"?
+  x_axis_label_style_(14, "Verdana", "", ""),
+  x_value_label_style_(12, "Verdana", "", ""),
+  point_symbols_style_(12, "Lucida Sans Unicode"), // Used for data point marking.
+  value_style_(10, "Verdana", "", ""), // Used for data point values.
+
+  title_info_(0, 0, "", title_style_, center_align, horizontal),
+  //title_info_(0, 0, "Plot of data", title_style_, center_align, horizontal), when text concatenation solved?
+  //x_label_info_(0, 0, "X Axis", x_axis_label_style_, center_align, horizontal),
+  //x_units_info_(0, 0, " (units)", x_value_label_style_, center_align, horizontal),
+  x_label_info_(0, 0, "", x_axis_label_style_, center_align, horizontal), // Null strings for now.
+  x_value_label_info_(0, 0, "", x_value_label_style_, center_align, horizontal), // X-axis tick value label, for example: "1.2" or "1.2e1".
+  x_units_info_(0, 0, "", x_value_label_style_, center_align, horizontal),
+  x_axis_(X, -10., +10., black, 1, 0, true, false, true),
+  y_axis_(Y, 0., +1., black, 1, 0, false, false, false), // Not used for 1D.
+
+  // Might fill in all values, but there are rather many for ticks_labels_style,
+  x_ticks_(X, x_value_label_style_),// so for defaults see ticks_labels_style.
+  text_margin_(2.), // for text as a multiplier of the font size.
+  image_border_(yellow, white, 1, 10, true, true), // margin should be about axis label font size.
+  plot_window_border_(lightgoldenrodyellow, svg_color(255, 255, 255), 1, 3, true, false),
+  legend_box_(yellow, white, 1, 2, true, true),
+  legend_header_(0, 0, "", legend_style_, center_align, horizontal),
+  legend_width_(200), // width of legend box (pixels) // TODO isn't this calculated?
+  legend_height_(0), // height of legend box (pixels)
+  legend_left_(-1), legend_right_(-1),legend_top_(-1),legend_bottom_(-1), // Default top left of plot window.
+  x_axis_vertical_(0.5), // Vertical position of 1D horizontal X-axis line as fraction of window.
+  legend_place_(outside_right), // default but interacts with using plot_window.
+  legend_on_(false),
+  legend_longest_(0),
+  outside_legend_on_(true),
+  legend_lines_(false), // Not very useful for 1 D as already showing data point marker shapes.
+  plot_window_clip_("plot_window"), // for <clipPath id="plot_window" ...
+  title_on_(true),
+  plot_window_on_(true),
+  x_values_on_(false), // By default, don't label point values.
+  x_values_style_(horizontal, 3, std::ios::dec, true, value_style_, black, black, false, false),
+  // Confidence interval parameters.
+  // (Could provide functions for the user to control these).
+  alpha_(0.05), // oss.iword(confidenceIndex) / 1.e6; 95% confidence.
+  epsilon_(0.05), // = oss.iword(roundingLossIndex) / 1.e3; // = allow 5% rounding loss.
+  uncSigDigits_(2), // = oss.iword(setUncSigDigitsIndex); // ISO standard =2 by default.
+  isNoisyDigit_(false), // Add extra digit to display?
+  // Autoscaling.
+  autoscale_check_limits_(true), // Do check all value for limits, infinity, max, min, NaN.
+  autoscale_plusminus_(3.), // Allow 3 uncertainty (standard deviation) for 99% confidence ellipse.
+  text_plusminus_(1.), // Nominal factor of 1. (default) corresponds to 67% confidence limit.
+  x_autoscale_(false),
+  x_include_zero_(false), // If autoscaled, include zero.
+  x_min_ticks_(6),  // If autoscaled, set a minimum number of ticks, default 6.
+  x_steps_(0),  // If autoscaled, set any prescaling to decimal 1, 2, 5, 10 etc, default none.
+  x_tight_(1e-6), // margin that point can lie outside top and bottom tick.
+  y_autoscale_(false), // Not used for 1-D.
+  // Used to transform Cartesian to SVG.
+  x_scale_(1.), x_shift_(0.),
+  y_scale_(1.), y_shift_(0.),
+  x_axis_position_(0) // Move into axis_style?
+{
+  size(500, 200); // Default image size.
+  // Only needs to be quite shallow (y_size) for a 1-D plot.
+  // (But may need more height (y_size) if long value labels are used, for example: "[time = 1.23 +-0.02 sec]").
+  // 200 barely leaves enough room for five data series in any legend box).
+  // (2-D usually needs to be much more rectangular).
+
+  using namespace boost::svg::detail; // Avoid detail:: specification.
+
+  // Build the document tree & add all the children of the root node.
+  for(int i = 0; i < detail::SVG_PLOT_DOC_CHILDREN; ++i)
+  {
+    image_.add_g_element();
+  }
+  set_ids();
+
+  // Set other SVG color, stroke & width defaults for various child PLOT nodes.
+  image_.g(PLOT_BACKGROUND).style().stroke_color(image_border_.stroke_);
+  image_.g(PLOT_BACKGROUND).style().stroke_width(image_border_.width_); //
+  image_.g(PLOT_BACKGROUND).style().fill_color(image_border_.fill_);
+  image_.g(PLOT_WINDOW_BACKGROUND).style().fill_color(plot_window_border_.fill_);
+  image_.g(PLOT_WINDOW_BACKGROUND).style().stroke_width(plot_window_border_.width_).stroke_color(plot_window_border_.stroke_);
+  image_.g(PLOT_LIMIT_POINTS).style().stroke_color(lightslategray).fill_color(antiquewhite);
+  image_.g(PLOT_X_AXIS).style().stroke_color(black).stroke_width(x_axis_.width());
+  image_.g(PLOT_DATA_UNC3).style().stroke_color(lightgoldenrodyellow).fill_color(lightgoldenrodyellow).stroke_width(1);
+  image_.g(PLOT_DATA_UNC2).style().stroke_color(peachpuff).fill_color(peachpuff).stroke_width(1);
+  image_.g(PLOT_DATA_UNC1).style().stroke_color(magenta).fill_color(pink).stroke_width(1);
+
+  // Note that widths are stored in member data *and* copied here.
+  // Not sure if this is wise but ...
+  // Font info defaults are set by the constructor above.
+  // Ticks.
+
+  y_ticks_.left_ticks_on_ = false; // Needed to ensure don't extend X-axis line.
+  y_ticks_.right_ticks_on_ = false;
+
+  if(x_ticks_.use_up_ticks() || x_ticks_.use_down_ticks())
+  {
+    image_.g(PLOT_X_MAJOR_TICKS).style().stroke_width(x_ticks_.major_tick_width_).stroke_color(black);
+    image_.g(PLOT_X_MINOR_TICKS).style().stroke_width(x_ticks_.minor_tick_width_).stroke_color(black);
+  }
+  // Grids.
+  // Default color & width for grid, used or not.
+  image_.g(PLOT_X_MAJOR_GRID).style().stroke_width(x_ticks_.major_grid_width_).stroke_color(svg_color(200, 220, 255));
+  image_.g(PLOT_X_MINOR_GRID).style().stroke_width(x_ticks_.minor_grid_width_).stroke_color(svg_color(200, 220, 255));
+  //image_.g(PLOT_DATA_LINES).style().stroke_width(2); // default width.
+  // Alter with, for example: plot.data_lines_width(4);
+
+  legend_place_ = (plot_window_on_) ? 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?)
+
+  x_ticks_on_ = x_ticks_.up_ticks_on_ || x_ticks_.down_ticks_on_;
+  // Only 2D has left and right y ticks.
+  x_ticks_.ticks_on_window_or_on_axis_ = 0; // Make ticks (and ticks value labels) on X-axis line the default.
+  // This will place the labels just under the horizontal X-axis line,
+  // rather than below the plot window border.
+  // This over-rides the default in class ticks_labels_style.
+  //
+
+  if (title_info_.text() == "")
+  { // Avoid leaving unnecessary space etc for a title.
+    title_on_ = false;
+  }
+  else
+  {
+    title_on_ = true; // Can be switched off later with `my_1d_plot.title_on(true);`
+  }
+} // svg_1d_plot::svg_1d_plot() Default constructor.
+
+
+void svg_1d_plot::calculate_plot_window()
+{ //! Calculate the size and position of the plot window,
+  //! taking account of the length and font size of axes labels, axis ticks, title and legend box.
+  //! This version is only for 1-D.
+  //! All calculations use SVG units, pixels by default.
+
+  // Start by assuming we can use all the svg image,
+  // but reduce by the width of any image border.
+  plot_left_ = 0 + image_border_width(); // Top left of image.
+  plot_top_ = 0 + image_border_width();
+  plot_right_ = image_.x_size() - image_border_width(); // Bottom right of image.
+  plot_bottom_ = image_.y_size() - image_border_width();
+
+  if(title_on_ && title_info_.text() != "")
+  { // Leave space at top for title.
+    // Title at bottom (or sides even) option not implemented.
+    plot_top_ += title_font_size() * (text_margin_ + 0.5);
+  }
+
+  // Assume that X-axis labels are always at bottom for 1D plot.
+  if(x_axis_.label_on_ == true && x_label_info_.text() != "")
+  { // Leave space below plot window at bottom for X axis label (unless empty string).
+      plot_bottom_ -= x_axis_label_style_.font_size() * text_margin_;
+  }
+  if(plot_window_on_ == true)
+  { // Needed to allow any plot window border rectangle to show OK.
+    // A small margin is to prevent it overlapping the image border.
+    // Also allows for axis value labels that mark the min and max
+    // that must extend about half a font width beyond the plot window border.
+    plot_left_ +=  image_border_.margin_;
+    plot_right_ -=  image_border_.margin_;
+    plot_top_ += image_border_.margin_;
+    plot_bottom_ -=  image_border_.margin_;
+  }
+
+  // Size if necessary - else (re-)initialise to zero.
+  size_legend_box(); // depending on its contents.
+  place_legend_box();
+
+  // Because there may be several datasets,
+  // and the scaling can be done by any one or all of them.
+  // my_plot.autoscale(my_data1) // for 1 dataset.
+  // or my_plot.autoscale(my_datas) // for a vector of several datasets.
+  // calculates the min & max, increments & ticks.
+  if (x_autoscale_)
+  { // Use calculated autoscale values.
+    // Autoscale has been done in my_data.autoscale(my_data);
+    // and saved in x_auto_min_value_, x_auto_max_value_, & x_auto_tick_interval_,
+    // so copy these values to use them:
+    x_axis_.min_ = x_auto_min_value_;
+    x_axis_.max_ = x_auto_max_value_;
+    x_ticks_.major_interval_  = x_auto_tick_interval_;
+  }
+  else
+  { // Ignore auto values, even if they have been calculated.
+  }
+  // Copy X-axis min & max to ticks.
+  x_ticks_.min_ = x_axis_.min_;
+  x_ticks_.max_ = x_axis_.max_;
+  // Ensure both axis and ticks have the *same* range.
+  // (To use them separately (designed to give the potential for different ranges)
+  // one would have to *not* do this,
+  // but to make sure they are both assigned correctly).
+
+  //x_axis_.axis_ = (plot_bottom_) * x_axis_vertical_ + plot_top_ ;  // too low
+  //x_axis_.axis_ = (plot_bottom_) * x_axis_vertical_ - plot_top_ ;  // too high
+  //x_axis_.axis_ = (plot_bottom_) * x_axis_vertical_;  // tiny amount too  high.
+  // x_axis_.axis_ = (plot_bottom_ + plot_top_) * x_axis_vertical_;
+    x_axis_.axis_ = (plot_bottom_ - plot_top_) * x_axis_vertical_ + plot_top_;
+  // Put X-axis fraction of way up plot window.
+  // 0.5 is at middle(useful if no labels),
+  // 0.8 is near bottom (useful if value labels go upward),
+  // 0.2 is near top (useful if value labels go downward).
+
+  if(plot_window_on_ == true)
+  { // Using a plot window and NOT using all image.
+    // Calculate the number of chars of the longest tick value label.
+    x_ticks_.longest_label(); // Updates label_max_length_
+    x_ticks_.label_max_space_ = 0; // Work out the longest tick value label for X-Axis.
+    if (x_ticks_.label_rotation_ == horizontal)
+    { // Only 1 char height & 1 space needed if labels are horizontal.
+      x_ticks_.label_max_space_ = 2 * x_value_label_style_.font_size() * wh; // SVG chars.
+      // Should this be just 2 * font_size
+    }
+    else if ((x_ticks_.label_rotation_ == upward) || (x_ticks_.label_rotation_ == downward))
+    { // ! horizontal so will need more than 2 chars worth.
+        x_ticks_.label_max_space_+= x_ticks_.label_max_length_ * x_value_label_style_.font_size() * wh; // SVG chars.
+    }
+    else
+    { // Assume label is sloping, say 45, so * sin(45) = 0.707.
+        x_ticks_.label_max_space_+= x_ticks_.label_max_length_ * x_value_label_style_.font_size() * wh * sin45; // SVG 'chars'.
+    }
+
+    // Make space for any ticks pointing below the plot window.
+    if(x_ticks_.down_ticks_on_)
+    { // Start bottom of plot higher to give space for any external down ticks.
+      plot_bottom_ -= (std::max)(x_ticks_.major_tick_length_, x_ticks_.minor_tick_length_);// And avoid macro max trap!
+    }
+
+    if (x_axis_.axis_line_on_)
+    { // Want a X-axis line, so check if range includes zero, meaning that X and Y axes intersect,
+      // and x_axis_ is svg coordinate of Y-axis (usually y = 0).
+      // If not fix axis to bottom of the plot window.
+      if ((x_axis_position_ == bottom) // All X data values definitely > zero.
+        && !(x_ticks_.ticks_on_window_or_on_axis_ < 0) ) // & not already on bottom of plot window.
+      { // y_min_ > 0 so X-axis will not intersect Y-axis, so use plot window border.
+        plot_bottom_ -= x_ticks_.label_max_space_; // Move up for the value labels.
+        x_axis_.axis_ = plot_bottom_; // Put X-axis on bottom on plot window.
+      }
+      else if ((x_axis_position_ == top)  // All x data values definitely < zero.
+        && !(x_ticks_.ticks_on_window_or_on_axis_ > 0) ) // & not already on top of plot window.
+      { // // y_max_ < 0 so X-axis will not intersect Y-axis, so use plot window border.
+          plot_top_ += x_ticks_.label_max_space_; // Move down for labels.
+          x_axis_.axis_ = plot_top_; // Put X-axis on top of plot window border.
+      }
+      else
+      { // y_axis_position_ == y_intersects_x
+        // Calculate below after transform is calculated.
+      }
+    } // if (use_x_axis_line_)
+
+    // Make space for any tick value labels.
+    if (x_ticks_.major_value_labels_side_ != 0)
+    { // There are some tick value labels.
+      // If ticks and value labels are on plot window border, the need to allow space for them.
+      if ((x_ticks_.ticks_on_window_or_on_axis_ < 0) // ticks on bottom of plot window.
+          && (x_ticks_.major_value_labels_side_ < 0) ) // & tick value labels below axis line too.
+      {  // Contract plot window bottom edge up to make space for X tick value labels on bottom.
+        plot_bottom_ -= x_ticks_.label_max_space_; // Move up.
+      }
+      else if ((x_ticks_.ticks_on_window_or_on_axis_ > 0) //
+          && (x_ticks_.major_value_labels_side_ > 0) ) // & X tick value labels to top of plot window.
+      { // Move top of plot window down to give space for X tick value labels.
+        plot_top_ += x_ticks_.label_max_space_; // Move window top down.
+      }
+      else // (x_ticks_.major_value_labels_side_ == 0)
+      { // X-ticks on the X-axis line (not on plot window border).
+        // Don't need to allow any extra space.
+        // (But if X-axis is near plot window border, may overlap it, and any X-axis labels!)
+      }
+    } // x_ticks_. major_value_labels_side
+  } // plot_window_on_
+  if(plot_window_on_ == true)
+  { // Draw plot window border as a rectangular box.
+    image_.g(detail::PLOT_WINDOW_BACKGROUND).push_back(
+      new rect_element(plot_left_, plot_top_, (plot_right_ - plot_left_), plot_bottom_ - plot_top_));
+  } // plot_window_on_
+} //  void calculate_plot_window()
+
+void svg_1d_plot::draw_axes()
+{ //! Add information to the plot image for X-axis lines.
+  //! (For 1-D, there is, of course, only the horizontal X-axis,
+  //! but there can be a vertical Y-axis line at x = 0).
+  double x(0.);
+  transform_x(x);
+  double y1(0.);
+  double y2(image_.y_size());
+  // Draw origin, making sure it is in the plot window.
+  if(x_axis_.axis_line_on_ && (x >= plot_left_) && (x <= plot_right_))
+  {
+    if(!plot_window_on_)
+    { // Use whole image.
+      if(title_on_)
+      { // Allow space for title, taking account of font size.
+        y1 += title_info_.textstyle().font_size() * text_margin_;
+      }
+      if(x_axis_.label_on_)
+      {// Allow space for x tick values, taking account of font size.
+        y2 -= x_label_info_.textstyle().font_size() * text_margin_;
+      }
+    }
+    else
+    { // Use plot window.
+      y1 = plot_top_;
+      y2 = plot_bottom_;
+    }
+    image_.g(detail::PLOT_X_AXIS).line(x, y1, x, y2); // Draw vertical Y-axis line.
+  }
+  else
+  { // Won't fit into window.  Throw or warning message?
+  }
+  draw_x_axis(); // Draw horizontal X-axis line.
+} //  draw_axes()
+
+void svg_1d_plot::set_ids()
+{ //! Document ids for use in identifying group elements, for example: <g id = "PLOT_TITLE".../g>
+  for(int i = 0; i < detail::SVG_PLOT_DOC_CHILDREN; ++i)
+  {
+    svg_1d_plot::image_.g(i).id(detail::document_ids_[i]);
+  }
+} //  void set_ids()
+
+void  svg_1d_plot::calculate_transform()
+{ //! Calculate scale and shift factors for transforming from Cartesian to SVG plot.
+  //! SVG image is (0, 0) at top left, Cartesian (0, 0) at bottom left.
+  x_scale_ = (plot_right_ - plot_left_) / (x_axis_.max_ - x_axis_.min_);
+  x_shift_ = plot_left_ - (x_axis_.min_ * (plot_right_ - plot_left_) / (x_axis_.max_ - x_axis_.min_));
+  y_scale_ = 1.;
+  // y_shift_ = plot_top_ - (plot_top_ - plot_bottom_) / 2.;
+  // y_shift_ = plot_top_ - (plot_top_ - plot_bottom_)  * x_axis_vertical_;  // OK at 0.5
+  y_shift_ = plot_top_ - (plot_top_ - plot_bottom_) * x_axis_vertical_;
+} // void calculate_transform()
+
+// svg_1d_plot Member functions definitions.
+
+svg_1d_plot& svg_1d_plot::write(const std::string& file)
+{ /*! Write SVG image to the specified file, providing the suffix .svg if none given.
+
+  \details write() has two versions: to an ostream and to a file.
+  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.
+
+  \note This file version opens an ostream, and calls the ostream version of write.
+
+  \return *this to make chainable.
+  */
+  std::string filename(file); // Copy to avoid problems with const if need to append.
+  if (filename.find(".svg") == std::string::npos)
+  { // No file type suffix, so provide the default .svg.
+    filename.append(".svg");
+  }
+  std::ofstream fout(filename.c_str());
+  if(fout.fail())
+  {
+    throw std::runtime_error("Failed to open " + filename);
+  }
+  image_.image_filename(filename);
+  // Note filename for optional output as comment in the .svg file.
+  svg_1d_plot::write(fout); // Use the ostream version.
+  return *this;
+}
+
+svg_1d_plot& svg_1d_plot::write(std::ostream& s_out)
+{ /*! Write SVG image to the specified std::ostream.
+      \note This function also is used by the write to file function.
+      \return @c *this to make chainable.
+  */
+  update_image();
+  /*!
+    The default stream precision of 6 decimal digits is probably excessive.
+    4.1 Basic data types, integer or float in decimal or scientific (using E format).
+    If image size is under 1000 x 1000, the SVG plot default precision of 3 is probably sufficient.
+    This reduces .svg file sizes significantly for curves represented with many data points.
+    For example, if a curve is shown using 100 points,
+    reducing to coord_precision(3) from default of 6 will reduce file size by 300 bytes.
+  */
+  image_.write(s_out);
+  return (svg_1d_plot&) *this;
+} // write
+
+template <typename T> //! \tparam T Floating-point type of the data (@c T must be convertible to double).
+svg_1d_plot_series& svg_1d_plot::plot(const T& container, const std::string& title /*= "" */)
+{ /*! Add a data series to the plot (by default, converting to unc doubles), with optional title.
+    \code
+std::vector<float> my_data; // my container.
+my_data.pushback(2.f); // Fill container with some data.
+my_data.pushback(3.f);
+my_data.pushback(4.f);
+my_1d_plot.plot(my_data, "All data in my container"); // Plot all data in container.
+    \endcode
+
+    \param container Container (for example vector) for the data to be added to the plot.
+    \param title Optional title for the data series (default none).
+
+    \return Reference to data series just added (to make chainable).
+
+    \note This version assumes that \b ALL the data values in the container are used.
+  */
+  serieses_.push_back(
+    svg_1d_plot_series(
+    boost::make_transform_iterator(container.begin(), detail::meas_1d_convert()),
+    boost::make_transform_iterator(container.end(), detail::meas_1d_convert()),
+    //boost::make_transform_iterator(container.begin(), detail::unc_1d_convert<false>()),
+    //boost::make_transform_iterator(container.end(), detail::unc_1d_convert<false>()),
+    title)
+  );
+  return serieses_[serieses_.size() - 1];
+} // plot(const T& container, const std::string& title)
+
+template <class T>  //!  \tparam T floating-point type of the data (T must be convertable to double).
+svg_1d_plot_series& svg_1d_plot::plot(const T& begin, const T& end, const std::string& title)
+{ /*! Add a data series to the plot (by default, converting to unc doubles), with optional title.
+    \note This version permits a partial range of the container, from begin to end, to be used.
+    \return a reference to the data series just added.
+    \param begin Iterator to 1st data item in container.
+    \param end Iterator to one-beyond-end of data in container.
+    \param title Optional title for the plot (default is no title).
+  */
+  serieses_.push_back(
+    svg_1d_plot_series(
+    boost::make_transform_iterator(begin, detail::unc_1d_convert<false>()),
+    boost::make_transform_iterator(end, detail::unc_1d_convert<false>()),
+    title)
+  );
+  /*! For example:\n
+    @c my_1d_plot.plot(my_data.begin(), my_data.end(), "My container");\n
+    @c my_1d_plot.plot(&my_data[1], &my_data[4], "my_data 1 to 4"); // Add part of data series
+
+    \warning last == end  which is one past the last, so this only does 1, 2 & 3 -  \b not 4!
+    */
+  return serieses_[serieses_.size() - 1]; // Reference to data series just added.
+} // plot
+
+
+template <typename T, typename U> /*!
+    \tparam T floating-point type of the data (which must be convertable to double).
+    \tparam U functor floating-point type (default is @c double_1d_convert).
+  */
+svg_1d_plot_series& svg_1d_plot::plot(const T& container, const std::string& title /* = "" */, U functor/*= double_1d_convert*/)
+{ //! Add a data series to the plot, with optional title.
+/*!
+  This version of plot includes a functor, allowing other than just convert data values to double(the default).
+  \param container Container for data (for example vector) that contains the data to be added to the plot.
+  \param title Optional title for the plot (default is no title).
+  \param functor Custom functor to convert data value to double.
+
+
+  \return a reference to data series just added (to make chainable).
+*/
+  serieses_.push_back(
+    svg_1d_plot_series(
+    boost::make_transform_iterator(container.begin(), functor),
+    boost::make_transform_iterator(container.end(),   functor),
+    title)
+  );
+  return serieses_[serieses_.size() - 1]; // Reference to data series just added.
+} // plot
+
+
+template <typename T, typename U> /*!
+      \tparam T floating-point type of the data (which must be convertable to double).
+      \tparam U functor floating-point type (default is double_1d_convert).
+    */
+svg_1d_plot_series& svg_1d_plot::plot(const T& begin, const T& end, const std::string& title /* = ""*/, U functor /* = double_1d_convert */)
+{ /*! Add a data series to the plot, with optional title. (Version with custom functor, rather than to double).
+    \note This version permits a @b partial range, begin to end, of the container to be used.
+
+    \param begin Iterator to 1st data item in container.
+    \param end Iterator to one-beyond-end of data in container.
+    \param title Optional title for the plot (default is no title).
+    \param functor Custom functor.
+    \return a reference to data series just added (to make chainable).
+  */
+
+  serieses_.push_back(
+    svg_1d_plot_series(
+      boost::make_transform_iterator(begin, functor),
+      boost::make_transform_iterator(end,   functor),
+      title)
+  );
+  return serieses_[serieses_.size() - 1]; //!< \return Reference to data series just added.
+} // plot
+
+// End Definitions of svg_plot_series Public Member Functions.
+} // namespace svg
+} // namespace boost
+
+#endif // BOOST_SVG_SVG_1D_PLOT_IPP