$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: pbristow_at_[hidden]
Date: 2008-05-24 12:21:10
Author: pbristow
Date: 2008-05-24 12:21:09 EDT (Sat, 24 May 2008)
New Revision: 45714
URL: http://svn.boost.org/trac/boost/changeset/45714
Log:
Revised for major update of 1D, 2D and Boxplot
Text files modified: 
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp         |   689 +++++++++++++++++++++++++++++++++++---- 
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp |    27                                         
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_boxplot_detail.hpp      |    49 ++                                      
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style_detail.hpp        |     7                                         
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp                 |   292 ++++++++++++----                        
   5 files changed, 902 insertions(+), 162 deletions(-)
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp	2008-05-24 12:21:09 EDT (Sat, 24 May 2008)
@@ -14,6 +14,11 @@
 #include "../svg.hpp"
 #include "svg_tag.hpp"
 #include "numeric_limits_handling.hpp"
+//using boost::math::fpclassify for
+// boost::math::
+// template <class T>bool isfinite (T);
+// template <class T>bool isinf (T);
+// template <class T> bool isnan (T);
 
 #include <string>
 // using std::string;
@@ -21,6 +26,9 @@
 #include <iostream> // for testing only.
 // using std::cerr and std::endl
 
+#include <utility>
+// using std::pair
+
 namespace boost
 {
   namespace svg
@@ -46,7 +54,7 @@
       nowhere = 0,
       inside = -1,  // Default place for inside is top left of plot window,
       // exact location controlled by legend_top_left().
-      outside_left = 1, // Outside 
+      outside_left = 1, // Outside
       outside_right = +2,  // Default for outside.
       outside_top = +3,
       outside_bottom = +4,
@@ -73,8 +81,8 @@
         // void transform_point(double &x, double &y);
         // void transform_x(double &x);
         // void transform_y(double &y);
-        // void draw_x_minor_ticks(double j, path_element& tick_path, path_element& grid_path); // (& grid).
-        // void draw_x_major_ticks(double i, path_element& tick_path, path_element& grid_path); // (& grid).
+        // void draw_x_minor_tick(double j, path_element& tick_path, path_element& grid_path); // (& grid).
+        // void draw_x_major_tick(double i, path_element& tick_path, path_element& grid_path); // (& grid).
         // void draw_x_axis();
         // void draw_legend();
         // void draw_title();
@@ -111,7 +119,7 @@
           y = derived().y_scale_ * y + derived().y_shift_;
         }
 
-        void draw_x_minor_ticks(double value, path_element& tick_path, path_element& grid_path)
+        void 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 value label,
@@ -142,14 +150,14 @@
             // 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_ticks grid inside plot window: x = "
+              //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_ticks grid OUTside plot window: x = "
+              // 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
@@ -187,12 +195,12 @@
           else
           { // This will happen but is designed to be ignored!
             // See comment in draw_x_axis
-            //std::cerr << "Writing draw_x_minor_ticks OUTside plot window: x = "
+            //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_ticks
+        } // void draw_x_minor_tick
 
-        void draw_x_major_ticks(double value, path_element& tick_path, path_element& grid_path)
+        void draw_x_major_tick(double value, path_element& tick_path, path_element& grid_path)
         { // draw ticks - and grid too if wanted.
           // If major_value_labels_side then value shown beside the major tick.
           double x(value); //
@@ -200,7 +208,8 @@
           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;
+            //std::cout << derived().plot_left_ << ' '<< x << std::endl;
+            // This *was* displayed for a plot.
             return;
           }
           double y_up(0.); // upper end of tick.
@@ -231,7 +240,7 @@
 
           // 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 <= 
+          //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_axis_ < 0)
@@ -404,15 +413,15 @@
           }
           else
           { // Outside plot window - so do nothing?  Warning?
-            //std::cerr << "Writing draw_x_major_ticks OUTside plot window: "
+            //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_ticks
+        } // draw_x_major_tick
 
         void draw_x_axis()
         { // Draw horizontal X-axis line & plot window line to hold.
           if(derived().x_axis_.axis_line_on_)
-          { // Want an X-axis line.
+          { // Want a horiztonal X-axis line drawn.
             double xleft = derived().plot_left_;
             double xright = derived().plot_right_;
             if (derived().x_axis_position_ == x_intersects_y)
@@ -472,20 +481,20 @@
             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 
+              // Reduce test value by a few bits to avoid accumulated rounding error
               // that intermittently puts minor ticks *at same value as* major ticks.
             { // This will output 'orphaned' minor ticks that are beyond the plot window,
               // if the last major tick does not coincide with the plot window.
-              // These are just ignored in draw_x_minor_ticks.
+              // 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_ticks(j, minor_tick_path, minor_grid_path);
+              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_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_ticks(x, major_tick_path, major_grid_path);
+              draw_x_major_tick(x, major_tick_path, major_grid_path);
             }
           }
 
@@ -494,9 +503,9 @@
             x -= derived().x_ticks_.major_interval_) // Want a close to test here?
           {
             // Draw minor ticks.
-            for(double j = x - x_minor_jump; 
+            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 
+              // 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)
             {
@@ -504,14 +513,14 @@
               { // Avoid a minor tick at x == 0 where there *is* a vertical Y-axis line.
                 // (won't be Y-axis line for 1-D where the zero tick is always wanted).
                 // But no tick means no value label 0 either unless on_plot_window.
-                draw_x_minor_ticks(j, minor_tick_path, minor_grid_path);
+                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_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_ticks(x, major_tick_path, major_grid_path);
+              draw_x_major_tick(x, major_tick_path, major_grid_path);
             }
           }
         } // void draw_x_axis()
@@ -576,7 +585,7 @@
             // 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;
 
@@ -598,7 +607,7 @@
             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.
@@ -618,7 +627,7 @@
             {
             case nowhere:
               return; // Actually places it at (0, 0), probably overwriting the plot.
-            case somewhere: 
+            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_;
@@ -666,7 +675,7 @@
                derived().legend_top_ += spacing;
                derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
               break;
-            case outside_bottom: 
+            case outside_bottom:
                // Centered.
                derived().legend_bottom_ = derived().image.y_size();
                derived().legend_bottom_ -= (derived().image_border_.width_ + derived().image_border_.margin_); // up
@@ -678,7 +687,7 @@
               break;
               } // switch
 
-            //std::cout << "Legend: left " << derived().legend_left_ 
+            //std::cout << "Legend: left " << derived().legend_left_
             //    << ", right " << derived().legend_right_
             //    << ", top " << derived().legend_top_
             //    << ", bottom " << derived().legend_bottom_
@@ -708,7 +717,7 @@
               }
 
                derived().image.g(detail::PLOT_LEGEND_BACKGROUND)
-              .style().fill_color(derived().legend_box_.fill()) // 
+              .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())
@@ -736,12 +745,12 @@
            // Assume legend box position has already been sized by calculate_legend_box.
             double legend_x_start = derived().legend_left_; // Saved box location.
             double legend_width = derived().legend_width_;
-            double legend_y_start = derived().legend_top_; 
+            double legend_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));
 
@@ -783,8 +792,8 @@
               if (derived().legend_lines_)
               { // Need to draw a short line to show color for that data series.
                 g_inner_ptr->style() // Use stroke colors from line style.
-                  .stroke_color(derived().series[i].line_style_.color_);
-               // Use stroke colors from line style. 
+                  .stroke_color(derived().series[i].line_style_.stroke_color_);
+               // Use stroke colors from line style.
                // == image.g(PLOT_DATA_LINES).style().stroke_width(width);
                 // but this sets width for BOTH point and line :-(
                 g_inner_ptr->push_back(new line_element(
@@ -809,21 +818,21 @@
 
           void draw_x_label()
           {
-            // X-label color is set in constructor thus: 
+            // X-label color is set in constructor thus:
             // image.g(detail::PLOT_X_LABEL).style().stroke_color(black);
             // and changed using x_label_color(color);
 
             std::string 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, use providing brackets () if required.
+            { // Append the units, if any, user providing brackets () if required.
               label += derived().x_units_info_.text();
             }
 
             double y = derived().plot_bottom_;
             y += derived().x_ticks_.value_label_style_.font_size() * 2.; // Shift down to suit.
-            if (derived().x_ticks_.ticks_on_window_or_axis_ < 0)
+            if (derived().x_ticks_.ticks_on_window_or_axis_ < 0) // bottom
             { // Ticks & value labels below X-axis.
-              if (derived().x_ticks_.major_value_labels_side_ < 0)
+              if (derived().x_ticks_.major_value_labels_side_ < 0) // bottom
               { // Shift down to allow for any value labels.
                 y += derived().x_ticks_.label_max_space_;
               }
@@ -876,7 +885,7 @@
             }
           } // void adjust_limits
 
-          void draw_plot_point(double x, double y, // SVG ?
+          void draw_plot_point(double x, double y, // SVG coordinates.
             g_element& g_ptr,
             plot_point_style& sty)
           {
@@ -979,12 +988,258 @@
               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
 
+          void draw_plot_point_value(double x, double y, g_element& g_ptr, value_style& sty, double value)
+          { // Write the value as string of a data point, X or Y .
+            std::stringstream label;
+            label.precision(sty.value_precision_);
+            label.flags(sty.value_ioflags_);
+            label << value; // "1.2" or "3.4e+001"...
+            std::string 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();
+            //plot_point_style& sty)
+            //int size = sty.size_;
+            int marker_size = derived().series[0].point_style_.size_;
+            int label_size = sty.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.
+
+            //enum rotate_style
+            //{ // Rotation in degrees from horizontal.
+            //  horizontal = 0, // normal left to right.
+            //  uphill = -45, // slope up.
+            //  upward = -90, // vertical writing up.
+            //  backup = -135, // slope up backwards - upside down!
+            //  downhill = 45, // slope down.
+            //  downward = 90,  // vertical writing down.
+            //  backdown = 135, // slope down backwards.
+            //  upsidedown = 180 // == -180
+            //};
+            rotate_style rot = sty.value_label_rotation_;
+            // http://www.w3.org/TR/SVG/coords.html#RotationDefined
+            // transform="rotate(-45)"
+
+            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 uphill: // -45 - 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 downhill: // OK
+              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
+
+             g_ptr.text(x, y, stripped, sty.values_text_style_, al, rot);
+             //g_ptr.text(x, y, stripped, derived().x_values_style_, al, rot);
+          } // void draw_plot_point_value(double x, double y, g_element& g_ptr, double value)
+
+          // TODO draw_plot_point_values function should probably be in svg_2d_plot as never used in 1D.
+
+          std::string sv(double v, const value_style& sty, bool unc = false)
+          { // Build // Strip unecessary e, +, & leading exponent zeros, reducing to "1.2, 3.4" or "3.4e1, 5.6e1"...
+            std::stringstream label;
+            // Precision of uncertainty 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((unc) ? 2 : sty.value_precision_);
+            label.flags(sty.value_ioflags_);
+            label << v; // "1.2, 3.4" or "3.4e+001, 5.6e+001"...
+            return  (sty.strip_e0s_) ?
+              // Default is to strip unecessary e, +, & leading exponent zeros.
+              strip_e0s(label.str())  // reduce to "1.2, 3.4" or "3.4e1, 5.6e1"...
+              :
+              label.str();  // Unstripped.
+          } // std::string sv(double v, const value_style& sty)
+
+          void 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, double vx, double vy)
+          { // Write the *pair* of values as string of a data point.
+
+            std::string label_xv = sv(vx, x_sty);
+            std::string label_yv = sv(vy, y_sty);
+            std::string label_xu;
+            std::string label_yu;
+            std::string label_xdf;
+            std::string label_ydf;
+
+            int marker_size = derived().series[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 uphill: // -45 - 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 downhill: // OK
+              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
+
+
+            // Unclear how to get this uncertainty information into this function,
+            // so these arepurely imaginary for now.
+            double ux = 0.0123;
+            double uy = 0.00321;
+            double dfx = 23;
+            double dfy = 6;
+
+            // Tasteless colors and font changes are purely proof of concept.
+
+             int fx = static_cast<int>(y_sty.values_text_style_.font_size() * 0.8);
+           // X value, & optional uncertainty & df.
+            text_element& t = x_g_ptr.text(x, y,
+              label_xv, x_sty.values_text_style_, al, rot);
+           // Optionally, show uncertainty as 95% confidence plus minus:  2.1 +-0.012 (23)
+           // TODO comma separator ? might want inside brackets [], or another separator?
+
+            std::string pm = " ±"; // Unicode space plusminus glyph.
+            // 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.
+            if (x_sty.plusminus_on_)
+            {  // Uncertainty estimate usually 95% confidence interval + or - 2 standard deviation.
+              label_xu = sv(ux, x_sty, true);
+              t.tspan(pm).fill_color(darkcyan);
+              t.tspan(label_xu).fill_color(darkcyan).font_weight("bold").font_size(fx);
+            }
+            if (x_sty.df_on_)
+            { // Degrees of freedom or number of values-1 used for this estimate of value.
+              std::stringstream label;
+              label.precision(4);
+              //label.flags(sty.value_ioflags_); // Leave at default.
+              label << " (" << dfx << ")"; // "123.5"
+              label_xdf = label.str();
+              t.tspan(label_xdf + ',').fill_color(brown).font_size(fx);
+            }
+
+            // Put Y value on the line below using font_size.
+            // Problem here if orientation is changed!
+            text_element& ty = y_g_ptr.text(x, y + y_sty.values_text_style_.font_size() * 1.2,
+              label_yv, y_sty.values_text_style_, al, rot);
+
+            int fy = static_cast<int>(y_sty.values_text_style_.font_size() * 0.8);
+            if (y_sty.plusminus_on_)
+            {  // Uncertainty estimate usually 95% confidence interval + or - 2 standard deviation.
+               // Precision of uncertainty is usually less than value,
+              label_yu = " " + sv(uy, y_sty, true);
+              ty.tspan(pm).font_family("arial").font_size(fy).fill_color(green);
+              ty.tspan(label_yu).fill_color(green).font_size(fy);
+            }
+            if (y_sty.df_on_)
+            { // 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"
+              label_ydf = label.str();
+              ty.tspan(label_ydf).fill_color(lime).font_size(fy);
+            }
+          } // void draw_plot_point_values(double x, double y, g_element& g_ptr, double value)
+
           // -----------------------------------------------------------------
           // Clear Functions.
           // When writing to multiple documents, the contents of the plot
@@ -1167,7 +1422,12 @@
           //Derived& background_color(const svg_color& col)
           //Derived& legend_background_color(const svg_color& col)
           //Derived& legend_border_color(const svg_color& col)
+          //Derived& legend_title_font_size(unsigned int size)
+          //Derived& legend_color(const svg_color& col)
+          //Derived& legend_font_family(const std::string& family)
+          //Derived& legend_font_weight(const std::string& weight)
           //Derived& background_border_color(const svg_color& col)
+          //Derived& background_border_width(double width)
           //Derived& plot_background_color(const svg_color& col)
           //Derived& x_axis_color(const svg_color& col)
           //Derived& y_axis_color(const svg_color& col)
@@ -1313,9 +1573,10 @@
           Derived& license(std::string repro = "permits",
             std::string distrib = "permits",
             std::string attrib = "requires",
-            std::string commercial = "permits")
+            std::string commercial = "permits",
+            std::string derivative = "permits")
           { // Might check these are "permits", "requires", or "prohibits"?
-            derived().image.license(repro, distrib, attrib, commercial);
+            derived().image.license(repro, distrib, attrib, commercial, derivative);
             return derived();
           }
 
@@ -1396,17 +1657,23 @@
           Derived& x_labels_strip_e0s(bool cmd)
           {
             derived().x_ticks_.strip_e0s_ = cmd;
-            return *this;
+            return derived();
           }
 
           bool y_labels_strip_e0s()
           {
             return derived().x_ticks_.strip_e0s_;
           }
-          
+
           Derived& title(const std::string title)
-          { // Plot title.
+          { // 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();
           }
 
@@ -1459,17 +1726,6 @@
             return derived().title_info_.style().font_weight();
           }
 
-          Derived& legend_font_weight(const std::string& weight)
-          {
-            derived().legend_header_.style().font_weight(weight);
-            return derived();
-          }
-
-          const std::string& legend_font_weight()
-          {
-            return derived().legend_header_.style().font_weight();
-          }
-
           Derived& title_font_stretch(const std::string& stretch)
           {
             derived().title_info_.style().font_stretch(stretch);
@@ -1514,6 +1770,8 @@
             return derived().title_info_.alignment();
           }
 
+          // Legend.
+
           Derived& legend_width(double width)
           {
             derived().legend_width_ = width;
@@ -1536,6 +1794,17 @@
             return derived().legend_header_.text();
           }
 
+          Derived& legend_font_weight(const std::string& weight)
+          {
+            derived().legend_header_.style().font_weight(weight);
+            return derived();
+          }
+
+          const std::string& legend_font_weight()
+          {
+            return derived().legend_header_.style().font_weight();
+          }
+
           Derived& legend_font_family(const std::string& family)
           {
             derived().legend_header_.style().font_family(family);
@@ -1573,7 +1842,7 @@
           const std::pair<double, double> legend_top_left()
           {// Top left of legend box.
             std::pair<double, double> r;
-            r.first = derived().legend_left_; 
+            r.first = derived().legend_left_;
             r.second = derived().legend_top_;
             return r;
           }
@@ -1581,7 +1850,7 @@
           const std::pair<double, double> legend_bottom_right()
           {// Bottom right of legend box.
             std::pair<double, double> r;
-            r.first = derived().legend_right_; 
+            r.first = derived().legend_right_;
             r.second = derived().legend_bottom_;
             return r;
           }
@@ -1600,13 +1869,6 @@
           Derived& legend_on(bool cmd)
           {
             derived().legend_on_ = cmd;
-            //if(cmd)
-            //{
-            //  derived().image.g(detail::PLOT_LEGEND_BACKGROUND)
-            //    .style().fill_color(white) // defaults.
-            //    .stroke_color(black).
-            //    .stroke_on(derived().legend_box_.border_on());
-            //}
             return derived();
           }
 
@@ -1655,7 +1917,7 @@
             }
             //derived().legend_place_ = outside_right;
             return derived();
-          } 
+          }
 
           bool plot_window_on()
           {
@@ -1670,7 +1932,7 @@
           }
 
           svg_color plot_border_color()
-          { 
+          {
             return derived().image.g(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color();
           }
 
@@ -1725,7 +1987,7 @@
 
           Derived& plot_window_y(double min_y, double max_y)
           { // This is normally calculated from other plot values.
-            
+
             if(max_y <= min_y)
             {
               throw std::runtime_error("plot_window Y: y_max_ <= x_min_");
@@ -1807,6 +2069,9 @@
 
           Derived& x_label_on(bool cmd)
           { // Show X-axis label text, or not.
+            // 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 *not* required).
             derived().x_axis_.label_on_ = cmd;
             return derived();
           }
@@ -1817,7 +2082,7 @@
           }
 
           Derived& x_label_font_size(unsigned int i)
-          { 
+          {
             derived().x_label_info_.style().font_size(i);
             return derived();
           }
@@ -1828,7 +2093,7 @@
           }
 
           Derived& x_value_font_size(unsigned int i)
-          { 
+          {
             derived().x_value_value.style().font_size(i);
             return derived();
           }
@@ -2006,7 +2271,7 @@
           //{ // 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); 
+          //  derived().image.g(PLOT_TITLE).style().stroke_width(width);
           //  return derived();
           //}
 
@@ -2041,8 +2306,8 @@
           //}
 
           Derived& background_color(const svg_color& col)
-          { // 
-            derived().legend_box_.fill(col);
+          { // plot background
+            derived().plot_window_border_.fill(col);
             derived().image.g(PLOT_BACKGROUND).style().fill_color(col);
             return derived();
           }
@@ -2059,6 +2324,11 @@
             return derived().image.g(PLOT_LEGEND_BACKGROUND).style().fill_color();
           }
 
+          bool legend_box_fill_on()
+          {
+            return derived().legend_box_.fill_on();
+          }
+
           Derived& legend_border_color(const svg_color& col)
           {
             derived().legend_box_.stroke(col);
@@ -2105,7 +2375,7 @@
           }
 
           svg_color x_axis_color()
-          { 
+          {
             return derived().image.g(PLOT_X_AXIS).style().stroke_color();
           }
 
@@ -2247,6 +2517,8 @@
           Derived& x_label(const std::string& str)
           {
             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();
           }
 
@@ -2258,6 +2530,7 @@
           Derived& x_label_units(const std::string& str)
           {
             derived().x_units_info_.text(str);
+            derived().x_axis_.label_on_ = true; // Assume want x_label string displayed.
             return derived();
           }
 
@@ -2270,6 +2543,7 @@
           Derived& y_label(const std::string& str)
           {
             derived().y_label_info_.text(str);
+            derived().y_axis_.label_on_ = true; // Assume want y_label string displayed.
             return derived();
           }
 
@@ -2281,6 +2555,7 @@
           Derived& y_label_units(const std::string& str)
           {
             derived().y_units_info_.text(str);
+            derived().y_axis_.label_on_ = true; // Assume want y_label string displayed.
             return derived();
           }
 
@@ -2289,12 +2564,114 @@
             return derived().y_units_info_.text();
           }
 
+          Derived& x_values_on(bool b)
+          { // Show values near data points.
+            derived().x_values_on_ = b;
+            return derived();
+          }
+
+          bool x_values_on()
+          { // Label data points with X values.
+            return derived().x_values_on_;
+          }
+
+          Derived& x_values_font_size(unsigned int i)
+          {
+            derived().x_values_style_.values_text_style_.font_size(i);
+            return derived();
+          }
+
+          unsigned int x_values_font_size()
+          {
+            return derived().x_values_style_.values_text_style_.font_size();
+          }
+
+          Derived& x_values_font_family(const std::string& family)
+          {
+            derived().x_values_style_.values_text_style_.font_family(family);
+            return derived();
+          }
+
+          const std::string& x_values_font_family()
+          {
+            return derived().x_values_style_.values_text_style_.font_family();
+          }
+
           Derived& x_major_interval(double inter)
           {
             derived().x_ticks_.major_interval_ = inter;
             return derived();
           }
 
+          Derived& x_values_color(const svg_color& col)
+          { // Function 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_X_POINT_VALUES).style().fill_color(col);
+            //derived().image.g(PLOT_X_POINT_VALUES).style().stroke_color(col);
+            return derived();
+          }
+
+          svg_color x_values_color()
+          { // 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();
+          }
+
+          Derived& x_values_rotation(rotate_style rotate)
+          { // Degrees (0 to 360).
+            derived().x_values_style_.value_label_rotation_ = rotate;
+            return derived();
+          }
+
+          int x_values_rotation()
+          {
+            return derived().x_values_style_.value_label_rotation_;
+          }
+
+          Derived& x_values_precision(int p)
+          { // set iostream precision
+            derived().x_values_style_.value_precision_ = p;
+            return derived();
+          }
+
+          int x_values_precision()
+          {
+            return derived().x_values_style_.value_precision_;
+          }
+
+          Derived& x_values_ioflags(std::ios_base::fmtflags f)
+          { // set iostream format flags
+            derived().x_values_style_.value_ioflags_ = f;
+            return derived();
+          }
+
+          std::ios_base::fmtflags x_values_ioflags()
+          {
+            return derived().x_values_style_.value_ioflags_;
+          }
+
+          Derived& x_plusminus_on(bool b)
+          { // set if uncertainty to be append to X values labels.
+            derived().x_values_style_.plusminus_on_ = b;
+            return derived();
+          }
+
+          bool x_plusminus_on()
+          {
+            return derived().x_values_style_.plusminus_on_;
+          }
+          Derived& x_df_on(bool b)
+          { // set if uncertainty to be append to X values labels.
+            derived().x_values_style_.df_on_ = b;
+            return derived();
+          }
+
+          bool x_df_on()
+          {
+            return derived().x_values_style_.df_on_;
+          }
+
           double x_major_interval()
           {
             return derived().x_ticks_.major_interval_;
@@ -2376,11 +2753,21 @@
 
           Derived& x_range(double min_x, double max_x)
           {
+            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.
               throw std::runtime_error("X range: max <= min!");
             }
-            if((max_x - min_x) < std::numeric_limits<double>::epsilon() * 1000)
+            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!" );
             }
@@ -2388,13 +2775,14 @@
             derived().x_axis_.max_ = max_x;
             //derived().x_ticks_.max_ = min_x;
             //derived().y_ticks_.max_ = max_x;
-            // done in calculate_plot_window. 
+            // done in calculate_plot_window.
             // TODO May be best to combine these?
+            derived().x_autoscale_ = false; // because range has just been set.
             return derived();
           }
 
           std::pair<double, double> x_range()
-          {
+          { // 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_;
@@ -2425,6 +2813,157 @@
             return derived().x_axis_.max_;
           }
 
+          bool autoscale_check_limits()
+          {
+            return derived().autoscale_check_limits_;
+          }
+
+          Derived& autoscale_check_limits(bool b)
+          { // Default is true, but can switch off checks for speed.
+            derived().autoscale_check_limits_ = b;
+            return derived();
+          }
+
+          bool x_autoscale()
+          { // Get autoscale setting.
+           return derived().x_autoscale_;
+          }
+
+          Derived& x_autoscale(bool b)
+          { // set whether to use autoscaled values.
+             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();
+          }
+
+          bool autoscale()
+          { // AKA x_autoscale.
+           return derived().x_autoscale_;
+          }
+
+          Derived& autoscale(bool b)
+          { // AKA x_autoscale - set whether to use X autoscaled values.
+
+             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();
+          }
+
+          Derived& x_autoscale(std::pair<double, double> p)
+          { // Use X min & max pair values to autoscale.
+              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().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 T> // T an STL container: array, vector ...
+          Derived& x_autoscale(const T& begin, const T& end) // Data series using iterators
+          { // to calculate autoscaled 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().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 T> // T an STL container: array, vector ...
+          Derived& x_autoscale(const T& container) // Whole data series.
+          { // to use to calculate autoscaled 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().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& container)
+
+          // Set & get autoscale parameters,
+          // Note: all these *MUST* preceed x_autoscale(data) call.
+
+          Derived& x_with_zero(bool b)
+          { // Set autoscale to include zero (default = false).
+            // Must preceed x_autoscale(data) call.
+            derived().x_include_zero_ = b;
+            return derived();
+          }
+
+          bool x_with_zero()
+          { //
+           return derived().x_include_zero_;
+          }
+
+          Derived& x_min_ticks(int min_ticks)
+          { // Set autoscale to include at least min_ticks (default = 6).
+            // Must preceed x_autoscale(data) call.
+            derived().x_min_ticks_ = min_ticks;
+            return derived();
+          }
+
+          int x_min_ticks()
+          { //
+           return derived().x_min_ticks_;
+          }
+
+          Derived& x_steps(int steps)
+          { // Set autoscale to set ticks in steps 2,4,6,8,10, or 1,5,10 or 2,5,10.
+            // default = 0 (none)
+            // Must preceed x_autoscale(data) call.
+            derived().x_steps_ = steps;
+            return derived();
+          }
+
+          int x_steps()
+          { //
+           return derived().x_steps_;
+          }
+
+          Derived& x_tight(double tight)
+          { // Set autoscale to include permit data points slightly outside both end ticks.
+            // default 0.
+            // Must preceed x_autoscale(data) call.
+            derived().x_tight_ = tight;
+            return derived();
+          }
+
+          double x_tight()
+          { //
+           return derived().x_tight_;
+          }
+
+          // Get results of autoscaling.
+          double x_auto_min_value()
+          {
+           return derived().x_auto_min_value_;
+          }
+
+          double x_auto_max_value()
+          {
+           return derived().x_auto_max_value_;
+          }
+
+          double x_auto_tick_interval()
+          {
+           return derived().x_auto_tick_interval_;
+          }
+
+           int x_auto_ticks()
+          {
+           return derived().x_auto_ticks_;
+          }
+
           //// Stylesheet.
           // Removed for now to avoid compile warning in spirit.
 
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/numeric_limits_handling.hpp	2008-05-24 12:21:09 EDT (Sat, 24 May 2008)
@@ -41,17 +41,24 @@
   // Provide checks on data values to be plotted.
   // Test if at max or +infinity, or min or - infinity, or NaN.
 
+  // Not clear why min or denorm min are not just ignored as almost zero (which is an OK value).
+
 inline bool limit_max(double a)
-{
+{ // At max value or _infinity.
     return (a ==(std::numeric_limits<int>::max)() // Avoid macro max trap!
          || a == std::numeric_limits<double>::infinity());
 }
 
 inline bool limit_min(double a)
-{
-    return (a == (std::numeric_limits<int>::min)() // Avoid macro min trap!
-        || a == -std::numeric_limits<double>::infinity()
-        || a == std::numeric_limits<double>::denorm_min());
+{// At min value, denorm_min or -infinity.  
+
+  return (
+    (a == -(std::numeric_limits<int>::max)()) // Avoid macro min trap!
+    || (a == -std::numeric_limits<double>::infinity())
+    );
+    //return (a == (std::numeric_limits<int>::min)() // Avoid macro min trap!
+    //    || a == -std::numeric_limits<double>::infinity()
+    //    || a == std::numeric_limits<double>::denorm_min()); // Too small to be useful.
 }
 
 inline bool limit_NaN(double a)
@@ -70,9 +77,9 @@
 }
 
 inline bool pair_is_limit(std::pair<double, double> a)
-{ // Check on both x and y data points.
-        return limit_max(a.first) || limit_min(a.first) || limit_NaN(a.first)
-        || limit_max(a.second) || limit_min(a.second) || limit_NaN(a.second);
+{ // Check on both x and y data points. Return false if either or both are at limit.
+  return limit_max(a.first) || limit_min(a.first) || limit_NaN(a.first)
+    || limit_max(a.second) || limit_min(a.second) || limit_NaN(a.second);
 }
 
 } // namespace detail
@@ -82,9 +89,9 @@
 
 // Defines :
 bool boost::svg::detail::limit_max(double); // true if max or +infinity.
-bool boost::svg::detail::limit_min(double); // true if min or -infinity.
+bool boost::svg::detail::limit_min(double); // true if min, denorm_min or -infinity.
 bool boost::svg::detail::limit_NaN(double); // true if NaN.
-bool boost::svg::detail::is_limit(double); // max, min, infinity or NaN - not a proper data value.
+bool boost::svg::detail::is_limit(double); // max, min, infinity or NaN - not a 'proper' data value.
 bool boost::svg::detail::pair_is_limit(std::pair<double, double>); // x and/or y  not a proper data value.
 
 #endif // BOOST_SVG_NUMERIC_LIMITS_HANDLING_DETAIL_HPP
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_boxplot_detail.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_boxplot_detail.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_boxplot_detail.hpp	2008-05-24 12:21:09 EDT (Sat, 24 May 2008)
@@ -1,6 +1,7 @@
 // svg_boxplot_detail.hpp
 
 // Copyright Jacob Voytko 2007
+// Copyright Paul A. Bristow 2008
 
 // Use, modification and distribution are subject to the
 // Boost Software License, Version 1.0.
@@ -10,18 +11,50 @@
 #ifndef BOOST_SVG_BOXPLOT_DETAIL_HPP
 #define BOOST_SVG_BOXPLOT_DETAIL_HPP
 
+// See also svg_style_detail.hpp for enum plot_doc_structure.
+// Caution: these two enum and ids must match because
+// the enum value is used to index the array of id strings.
+// void set_ids() copies all strings to matching image.get_g_element(i).id()
+// Add any new id items to both!
+
 namespace boost{
 namespace svg{
-namespace boxplot{
-
-enum boxplot_doc_structure
+namespace boxplot
 {
-  BACKGROUND, PLOT_BACKGROUND, 
+  enum boxplot_doc_structure
+  {
+    PLOT_BACKGROUND, // the whole svg image.
+    PLOT_WINDOW_BACKGROUND, // the smaller plot window (if used).
+    X_AXIS, Y_AXIS,
+    X_TICKS, 
     Y_MAJOR_TICKS, Y_MINOR_TICKS,
-    X_TICKS, PLOT_LABELS, Y_LABEL, X_LABEL,
-    BOX_AXIS, BOX, MEDIAN, WHISKER, MILD_OUTLIERS, EXTREME_OUTLIERS,
-    TITLE, BOXPLOT_DOC_CHILDREN
-};
+    Y_MAJOR_GRID, Y_MINOR_GRID,
+    VALUE_LABELS,
+    Y_LABEL, X_LABEL,
+    BOX_AXIS, BOX,
+    MEDIAN, WHISKER, MILD_OUTLIERS, EXTREME_OUTLIERS,
+    PLOT_TITLE,
+    PLOT_NOTES, // Free text and shapes to annotate diagram.
+    BOXPLOT_DOC_CHILDREN
+  };
+
+  std::string document_ids[] = // TODO change to document_ids_ because private member data.
+  { // 
+      "imageBackground", // the whole svg image.
+      "plotBackground", // the smaller plot window (if used).
+      "X-axis", "Y-axis",
+      "xMajorTicks", // Probably not used for Boxplots.
+      "yMajorTicks", "yMinorTicks",
+      "YGrid", "yMinorGrid",
+      "valueLabels", // tick Value Labels
+      "yLabel", "xLabel",  // axis text labels "length (cm)"
+      "boxAxis", "Box", // vertical Box axis line and box.
+      "media", "whisker", "mild_outliers", "extreme_outliers",
+      "title",  // of the whole plot.
+      "plotNotes", // Free text and shapes to annotate diagram.
+      "boxplotDocChildren" // This last string is not used.
+  }; //  std::string document_ids
+
 
 } // namespace boxplot
 } // namespace svg
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style_detail.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style_detail.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style_detail.hpp	2008-05-24 12:21:09 EDT (Sat, 24 May 2008)
@@ -1,6 +1,7 @@
 // svg_style.hpp
 
 // Copyright Jacob Voytko 2007
+// Copyright Paul A. Bristow 2008
 
 // Use, modification and distribution are subject to the
 // Boost Software License, Version 1.0.
@@ -48,6 +49,9 @@
     PLOT_LEGEND_POINTS, // data series point markers, circle, cross...
     PLOT_LEGEND_TEXT, // text describing each data series.
     PLOT_TITLE, // of the whole plot.
+    PLOT_X_POINT_VALUES,  PLOT_Y_POINT_VALUES, // Data point value labels.
+    PLOT_FUNCTIONS, // Lines and curves, often to show a fit to the data.
+    PLOT_NOTES, // Free text and shapes to annotate diagram.
     SVG_PLOT_DOC_CHILDREN // Last enum value used as count of children (22).
 };
 
@@ -69,6 +73,9 @@
     "legendPoints", // data series point markers, circle, cross...
     "legendText", // text describing each data series.
     "title",  // of the whole plot.
+    "plotXValues","plotYValues", // Data point value labels.
+    "plotFunctions", // Lines and curves, often to show a fit to the data.
+    "plotNotes", // Free text and shapes to annotate diagram.
     "plotDocChildren" // This last string is not used.
 }; //  std::string document_ids
     
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp	(original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp	2008-05-24 12:21:09 EDT (Sat, 24 May 2008)
@@ -83,9 +83,9 @@
   // --------------------------------------------------------------------------
 
   class svg_element
-  { // Base class 
+  { // Base class.
   protected:
-    svg_style style_info_; // fill, stroke, width, get by function style.
+    svg_style style_info_; // Colors fill, stroke, width, get by function style.
     std::string id_name_; // set & get by function id.
     std::string class_name_; // set & get by class id.
     std::string clip_name_; // set & get by function clip_id.
@@ -116,7 +116,8 @@
                 const std::string& id_name = "",
                 const std::string& class_name = "",
                 const std::string& clip_name = "")
-                :style_info_(style_info),
+                :
+                style_info_(style_info),
                 id_name_(id_name),
                 class_name_(class_name),
                 clip_name_(clip_name)
@@ -139,7 +140,7 @@
 
     // Set and get member functions.
     svg_style& style()
-    {
+    { // Indirect access to colors & width via style().stroke_color(), fill_color(), width()
       return style_info_;
     }
 
@@ -239,6 +240,7 @@
 
   // --------------------------------------------------
   // class rect_element: Represents a single rectangle.
+  // http://www.w3.org/TR/SVG/shapes.html#RectElement
   // --------------------------------------------------
 
   class rect_element : public svg_element
@@ -247,10 +249,12 @@
     friend bool operator!=(const rect_element&, const rect_element&);
 
   private:
-    double x_;
-    double y_;
-    double height_;
-    double width_;
+    double x_; // x-axis coordinate of the side of the rectangle which has the smaller x-axis coordinate value.
+    double y_; // y-axis coordinate of the side of the rectangle which has the smaller y-axis coordinate value.
+    // So is top left corner of rectangle.
+    double width_; // x + width is top right.
+    double height_; // y + height is bottom left
+    // x + width and y + height is bottom right.
   public:
 
     rect_element(double x, double y, double w, double h)
@@ -456,12 +460,11 @@
 class tspan_element : public text_parent, public svg_element
 { // See 10.5 tspan element http://www.w3.org/TR/SVG/text.html#TSpanElement 
 private:
-  
   double x_;  // Absolute positions.
   double y_;
   double dx_;  // Relative positions.
   double dy_;
-  int rotate_; // of text.
+  int rotate_; // of a 1st single character of text.
   // A list of shifts or rotations for several characters is not yet implemented.
   
   double text_length_;  // Allows the author to provide exact alignment.
@@ -474,6 +477,7 @@
   bool use_text_length_;
 
   text_style style_; // font variants.
+  bool use_style_;
 
 public:
   tspan_element(const std::string& text, const text_style& style = no_style)
@@ -484,16 +488,29 @@
   {
   }
 
-  tspan_element(const tspan_element& rhs)
-    :
-    x_(rhs.x_), y_(rhs.y_), dx_(rhs.dx_), dy_(rhs.dy_), rotate_(rhs.rotate_),
-    text_length_(rhs.text_length_), use_x_(rhs.use_x_), use_y_(rhs.use_y_),
-    use_text_length_(rhs.use_text_length_), style_(rhs.style_),
-    text_parent(rhs)
-  {
-  }
+  tspan_element(const tspan_element& rhs);
+    // TODO all may need refactoring to separate declaration from definition - as example below.
+  
+  //tspan_element(const tspan_element& rhs)
+  //  :
+  //  x_(rhs.x_), y_(rhs.y_), dx_(rhs.dx_), dy_(rhs.dy_), rotate_(rhs.rotate_),
+  //  text_length_(rhs.text_length_), use_x_(rhs.use_x_), use_y_(rhs.use_y_),
+  //  use_text_length_(rhs.use_text_length_), style_(rhs.style_),
+  //  text_parent(rhs)
+  //{
+  //}
+
+  // All setters (all chainable).
+  //tspan_element(const std::string& text, const text_style& style);
+  //tspan_element(const tspan_element&);
+  //tspan_element& text(const std::string& text);
+  //tspan_element& dx(double dx);
+  //tspan_element& dy(double dy); 
+  //tspan_element& rotation(int rotation); 
+  //tspan_element& x(double x);
+  //tspan_element& y(double y);
+  //tspan_element& text_length(double text_length);
 
-  // All setters (chainable).
   tspan_element& text(const std::string& text) 
   { 
     text_=text; 
@@ -513,7 +530,8 @@
   }
 
   tspan_element& rotation(int rotation) 
-  { 
+  { // Note implementation so far only rotates the 1st character in string.
+    // text_element rotation rotates the whole text string, so it *much* more useful.
     rotate_ = rotation; 
     return *this;
   }
@@ -539,7 +557,59 @@
     return *this;
   }
 
+  tspan_element& font_size(unsigned int size)
+  {
+    style_.font_size(size);
+    use_style_ = true;
+    return *this;
+  }
+
+  tspan_element& font_family(const std::string& family)
+  {
+    style_.font_family(family);
+    use_style_ = true;
+    return *this;
+  }
+
+  tspan_element& font_style(const std::string& style)
+  { // font-style: normal | bold | italic | oblique
+    // Examples: "italic"
+    // http://www.croczilla.com/~alex/conformance_suite/svg/text-fonts-02-t.svg
+    style_.font_style(style);
+    use_style_ = true;
+    return *this;
+  }
+
+  tspan_element& font_weight(const std::string& w)
+  { // svg font-weight: normal | bold | bolder | lighter | 100 | 200 .. 900
+    // Examples: "bold", "normal" 
+    // http://www.croczilla.com/~alex/conformance_suite/svg/text-fonts-02-t.svg
+    // tests conformance.  Only two weights are supported by Firefox, Opera, Inkscape
+    style_.font_weight(w);
+    return *this;
+  }
+
+  tspan_element& fill_color(const svg_color& color)
+  {
+    style_info_.fill_color(color);
+    style_info_.fill_on(true);
+    use_style_ = true;
+    return *this;
+  }
+
+
   // All getters.
+
+  //tspan_element::std::string text();
+  //double x();
+  //double y();
+  //double dx();
+  //double dy();
+  //int rotation();
+  //double text_length();
+  //text_style& font_style();
+  //const text_style& font_style() const;
+
   std::string text(){ return text_; }
   double x() { return x_; }
   double y() { return y_; }
@@ -548,18 +618,43 @@
   int rotation() { return rotate_; }
   double text_length() { return text_length_; }
 
+  unsigned int font_size()
+  { 
+    return style_.font_size();
+  }
+
+  const std::string& font_family()
+  {
+    return style_.font_family();
+  }
+
+  const std::string& font_weight() const
+  {
+    return style_.font_weight();
+  }
+
   text_style& font_style()
   { // Access to font family, size ...
     return style_;
   }
 
   const text_style& font_style() const
-  {
+  { // Access to font family, size ... const version.
     return style_;
   }
 
-  void write(std::ostream& os)
+  svg_color fill_color()
   {
+    return style_info_.fill_color();
+  }
+
+  bool fill_on()
+  {
+    return style_info_.fill_on();
+  }
+
+  void write(std::ostream& os)
+  { // tspan_element
     os << "<tspan";
 
     write_attributes(os); // id & clip_path
@@ -572,12 +667,10 @@
     {
       os << " rotate=\"" << rotate_ << "\"";
     }
-
     if(dx_!= 0)
     {
       os << " dx=\"" << dx_ << "\"";
     }
-
     if(dy_!= 0)
     {
       os << " dy=\"" << dy_ << "\"";
@@ -586,19 +679,16 @@
     // Now, add all elements that can be tested with the flags.
     if(use_x_ == true)
     {
-      os << "x=\"" << x_ << "\"";
+      os << " x=\"" << x_ << "\"";
     }
-
     if(use_y_  == true)
     {
-      os << "y=\"" << y_ << "\"";
+      os << " y=\"" << y_ << "\"";
     }
-
     if(use_text_length_ == true)
     {
-      os << "textLength=\"" << text_length_ << "\"";
+      os << " textLength=\"" << text_length_ << "\"";
     }
-
     if (style_.font_size() != 0)
     {
       os << " font-size=\"" << style_.font_size() << "\"";
@@ -627,6 +717,15 @@
   } //   void write(std::ostream& os)
 }; // class tspan_element
 
+tspan_element::tspan_element(const tspan_element& rhs)
+    :
+    x_(rhs.x_), y_(rhs.y_), dx_(rhs.dx_), dy_(rhs.dy_), rotate_(rhs.rotate_),
+    text_length_(rhs.text_length_), use_x_(rhs.use_x_), use_y_(rhs.use_y_),
+    use_text_length_(rhs.use_text_length_), style_(rhs.style_),
+    text_parent(rhs)
+  { // Separately defined constructor.
+  } // tspan_element::tspan_element
+
 class text_element : public svg_element
 { // Holds text with position, size, font, (& styles) & orientation.
   // Not necessarily shown correctly by all browsers, alas.
@@ -644,7 +743,7 @@
   void _generate_text(std::ostream& os)
   {
     for(ptr_vector<text_parent>::iterator i = data_.begin(); 
-        i!=data_.end(); 
+        i != data_.end(); 
         ++i)
     {
       (*i).write(os);
@@ -666,6 +765,24 @@
   // <text x="250" y="219.5" text-anchor="middle"  font-family="verdana" font-size="12">0 </text>
 
 public:
+  // Set
+  //void alignment(align_style a);
+  //void rotation(rotate_style rot);
+  //void x(double x);
+  //void y(double y);
+  //void text(const std::string& t);
+  //tspan_element& tspan(const std::string& t);
+  //text_element(double x, double y, const std::string text,text_style ts,align_style align, rotate_style rotate);
+  //text_element(const text_element& rhs);
+
+  // Get
+  //text_style& style();
+  //const text_style& style() const;
+  //align_style alignment();
+  //rotate_style rotation() const;
+  //double x() const;
+  //double y() const;
+
 
   text_style& style()
   { // Access to font family, size ...
@@ -677,9 +794,16 @@
     return style_;
   }
 
-  void alignment(align_style a)
+  text_element& style(text_style& ts)
+  {
+    style_ = ts;
+    return *this;
+  }
+
+  text_element&  alignment(align_style a) // TODO Change name to align????
   { // left_align, right_align, center_align
     align_ = a;
+    return *this;
   }
 
   align_style alignment()
@@ -687,9 +811,11 @@
     return align_;
   }
 
-  void rotation(rotate_style rot)
+  text_element&  rotation(rotate_style rot)// TODO Change name to rotate???
   { // Degrees: horizontal  = 0, upward = -90, downward, upsidedown
+    // Generates: transform = "rotate(-45 100 100 )" 
     rotate_ = rot;
+    return *this;
   }
 
   rotate_style rotation() const
@@ -697,9 +823,13 @@
     return rotate_;
   }
 
-  void x(double x)
+  // set functions now return *this to be chainable, for example:
+  // my_text_element.style(no_style).x(999).y(555).alignment(right_align).rotation(vertical);
+
+  text_element& x(double x)
   { // x coordinate of text to write.
     x_ = x;
+    return *this;
   }
 
   double x() const
@@ -707,9 +837,10 @@
     return x_;
   }
 
-  void y(double y)
+  text_element& y(double y)
   { // y coordinate of text to write.
     y_ = y;
+    return *this;
   }
 
   double y() const
@@ -745,14 +876,14 @@
     style_(ts),
     align_(align),
     rotate_(rotate)
-  { // text_element default constructor, defines defaults for all private members.
-    data_.push_back(new text_element_text(text));
+  { // text_element Default Constructor, defines defaults for all private members.
+    data_.push_back(new text_element_text(text)); // Adds new text string.
   }
 
-  text_element(const text_element& rhs) :
-    x_(rhs.x_), y_(rhs.y_), style_(rhs.style_),
-    align_(rhs.align_), rotate_(rhs.rotate_)
-  {
+  text_element(const text_element& rhs)
+  :
+    x_(rhs.x_), y_(rhs.y_), style_(rhs.style_), align_(rhs.align_), rotate_(rhs.rotate_)
+  { // Copy constructor.
      data_ = (const_cast<text_element&>(rhs)).data_.release();  
   }
 
@@ -760,20 +891,19 @@
   {
     x_ = rhs.x_;
     y_ = rhs.y_;
-    data_.clear();
+    data_.clear(); // Copy data_
           data_.insert(data_.end(), rhs.data_.begin(), rhs.data_.end());
     style_ = rhs.style_;
     align_ = rhs.align_; 
     rotate_ = rhs.rotate_;
+    return *this; // ADDed PAB.
   }
 
   std::string text()
   {
-   std::stringstream os;
-
+    std::stringstream os;
     _generate_text(os);
-
-   return os.str();
+    return os.str();
   }
 
   void write(std::ostream& os)
@@ -1159,7 +1289,7 @@
     ptr_vector<path_point> path; // All the (x, y) coordinate pairs,
     // filled by calls of m, M, l , L... that push_back.
   public:
-    bool fill;
+    // bool fill; now inherited from parent svg class.
 
     path_element(const path_element& rhs)
     {
@@ -1167,17 +1297,29 @@
     }
 
     path_element(const svg_style& style_info, 
-        const std::string& id_name="", 
-        const std::string& class_name="",
-        const std::string& clip_name="")
-        : svg_element(style_info, id_name, class_name, clip_name)
+      const std::string& id_name="", 
+      const std::string& class_name="",
+      const std::string& clip_name="")
+      :
+      svg_element(style_info, id_name, class_name, clip_name)
     {
     }
 
-    path_element() : fill(true)
-    { // TODO why is the default fill(true)?
+    path_element() 
+    {
+      // fill now got from the parent svg fill color.
+    }
+
+    path_element& fill_on(bool on_)
+    { // Set area fill, on or off.
+      style_info_.fill_on(on_);
+      return *this;
     }
 
+    bool fill_on()
+    { // Get area fill, on or off.
+      return style_info_.fill_on();
+    }
     // Note 1: return of path_element& permits chaining calls like
     // my_path.M(3, 3).l(150, 150).l(200, 200)...;
 
@@ -1198,7 +1340,14 @@
     }
 
     path_element& z()
-    {
+    { // Note lower case z, see path_element& Z() below.
+      path.push_back(new z_path());
+      return *this;
+    }
+
+    path_element& Z()
+    { // Upper case Z also provided for compatibility with
+      // http://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand 8.3.3 which allows either case.
       path.push_back(new z_path());
       return *this;
     }
@@ -1302,7 +1451,10 @@
         write_attributes(o_str); // id & clip_path
         style_info_.write(o_str); // fill, stroke, width...
 
-        if(!fill)
+        // line above should write fill = "none" that
+        // seems to be needed for reasons unclear.
+        // Even when g_element does not specify a fill, it seems to be interpreted as black fill.
+        if(!fill_on())
         {
           o_str << " fill=\"none\"";
         }
@@ -1643,18 +1795,20 @@
 
     void write(std::ostream& os)
     {
-      // Would be nice to avoid useless <g id="yMinorGrid"></g>
-      // TODO but would this mean that useful style is lost?
-
-      os << "<g"; // Do NOT need space if convention is to start following item with space.
-      write_attributes(os); // id="background" (or clip_path)
-      style_info_.write(os); // stroke="rgb(0,0,0)"
-      os << ">" ;
-      for(unsigned int i = 0; i < children.size(); ++i)
-      {
-        children[i].write(os); 
+      if (children.size() > 0)
+      { // Avoid useless output like: <g id="legendBackground"></g>
+        // TODO check this doesn't mean that useful style is lost?
+
+        os << "<g"; // Do NOT need space if convention is to start following item with space.
+        write_attributes(os); // id="background" (or clip_path)
+        style_info_.write(os); // stroke="rgb(0,0,0)" fill= "rgb(255,0,0)" ...
+        os << ">" ;
+        for(unsigned int i = 0; i < children.size(); ++i)
+        {
+          children[i].write(os); 
+        }
+        os << "</g>" << std::endl;
       }
-      os << "</g>" << std::endl;
       // Example:
       // <g fill="rgb(255,255,255)" id="background"><rect x="0" y="0" width="500" height="350"/></g>
     } // void write(std::ostream& rhs)
@@ -1666,7 +1820,7 @@
 
     // Returns a reference to the new child node just created.
     g_element& g()
-    {
+    { // was add_g_element
       children.push_back(new g_element());
       return *(static_cast<g_element*>(&children[children.size()-1]));
     }
@@ -1738,13 +1892,13 @@
       children.push_back(g);
     }
 
-    polygon_element& triangle(double x1, double y1, double x2, double y2, double x3, double y3, bool f)
+    polygon_element& triangle(double x1, double y1, double x2, double y2, double x3, double y3, bool f = true)
     {
       children.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, f));
       return *(static_cast<polygon_element*>(&(children[(unsigned int)(children.size()-1)])));
     }
 
-    polygon_element& rhombus(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, bool f)
+    polygon_element& rhombus(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, bool f = true)
     {
       children.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, x4, y4, f = true));
       return *(static_cast<polygon_element*>(&(children[(unsigned int)(children.size()-1)])));