Boost logo

Boost-Commit :

From: pbristow_at_[hidden]
Date: 2007-12-03 14:21:19


Author: pbristow
Date: 2007-12-03 14:21:18 EST (Mon, 03 Dec 2007)
New Revision: 41654
URL: http://svn.boost.org/trac/boost/changeset/41654

Log:
More updates but still much TODO. 1-D and boxplot fully broken by these changes.
Text files modified:
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp | 213 ++++++++++++++++++++++++--------------
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp | 6
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp | 218 ++++++++++++++++++++++++++++-----------
   sandbox/SOC/2007/visualization/libs/svg_plot/doc/svg_plot.qbk | 50 ++++++++
   sandbox/SOC/2007/visualization/libs/svg_plot/test/2d_color_consistency.cpp | 30 +++--
   5 files changed, 366 insertions(+), 151 deletions(-)

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp 2007-12-03 14:21:18 EST (Mon, 03 Dec 2007)
@@ -232,32 +232,64 @@
       tick_path.M(x1, y1).L(x1, y2);
       // Leaving current position at the bottom end of the tick.
 
- if(derived().use_x_major_labels )
- { // Show value by the tick.
+ if(derived().use_x_major_labels)
+ { // Show value by the tick as "1.2" or "3.4e+000"...
         std::stringstream label;
- label << value; // TODO precision problems here?
-
+ label.precision(derived().x_value_precision_);
+ label.flags(derived().x_value_ioflags_);
+ label << value; // "1.2" or "3.4e+000"...
+ double y = y2; // bottom end of the tick.
+ align_style alignment = center_align;
         if(derived().use_down_ticks)
         { // No need to shift if derived().use_up_ticks as labels are below the X-axis.
- y2 += derived().x_label_info.font_size(); // Move down just below bottom end of tick.
+ y += derived().x_label_info.font_size();
+ // Move down a font height below bottom end of tick.
+ }
+ if (derived().x_label_rotation_ == upward)
+ { //
+ alignment = right_align;
+ //y += label.str().size() * derived().x_label_info.font_size();
+ // so the last digit will be by the tick.
+ }
+ else if((derived().x_label_rotation_ == downward)
+ || (derived().x_label_rotation_ == downhill))
+ { // start from tick and write down.
+ alignment = left_align;
+ }
+ else if(derived().x_label_rotation_ == horizontal)
+ {
+ alignment = center_align; // center on the tick.
         }
- if(derived().use_x_ticks_on_plot_window_)
- { // Always want all values including "0" if labelling on the external plot window.
- y2,
- derived().image.get_g_element(detail::PLOT_VALUE_LABELS).text(x1, y2,
- label.str(), derived().x_label_info.font_size(), derived().x_label_info.font_family(),
- "", "", "", "", center_align, // center label on the tick.
- horizontal);
+ else if(derived().x_label_rotation_ == uphill)
+ { // 45 slope up,
+ alignment = left_align; // Uphill to end at tick.
+ y += label.str().size() * derived().x_label_info.font_size() * 0.7;
+ // sloping so need about sin(45) = 0.707 less space,
+ // so the last digit is by the tick.
         }
         else
- { // Internal - value labels just below horizontal X-axis.
- if ((value != 0) && derived().use_x_axis_lines_)
- { // Avoid a "0" below the X-axis if it would be cut through by the vertical Y-axis line.
- y2,
- derived().image.get_g_element(detail::PLOT_VALUE_LABELS).text(x1, y2,
+ { // 45 slope down
+ alignment = left_align; // Assume downhill from tick,
+ // so no need to y adjustment.
+ }
+
+ //if(derived().use_x_ticks_on_plot_window_) // External style.
+ //{ // Always want all values including "0" if labelling on the external plot window.
+ // derived().image.get_g_element(detail::PLOT_VALUE_LABELS).text(
+ // x1, y, // x centered on tick,
+ // label.str(), derived().x_label_info.font_size(), derived().x_label_info.font_family(),
+ // "", "", "", "", alignment, // center label on the tick.
+ // derived().x_label_rotation_);
+ //}
+ //else
+ { // ! use_x_ticks_on_plot_window_ = Internal - value labels just below horizontal X-axis.
+ if (derived().use_x_ticks_on_plot_window_ || ((value != 0) && derived().use_x_axis_lines_))
+ { // Avoid a "0" below the X-axis if it would be cut through by any internal vertical Y-axis line.
+ derived().image.get_g_element(detail::PLOT_VALUE_LABELS).text(
+ x1, y,
               label.str(), derived().x_label_info.font_size(), derived().x_label_info.font_family(),
- "", "", "", "", center_align, // center label on the tick.
- horizontal);
+ "", "", "", "", alignment, // center label on the tick.
+ derived().x_label_rotation_);
           }
         }
       } // use_x_major_labels
@@ -281,10 +313,10 @@
     path_element& major_grid_path = derived().image.get_g_element(PLOT_X_MAJOR_GRID).path();
 
     if(derived().use_x_axis_lines_)
- { // Draw the horizontal X-axis line.
+ { // Draw the horizontal X-axis line the full width of the plot window.
       derived().image.get_g_element(PLOT_X_AXIS).line(
- derived().plot_x1, derived().x_axis,
- derived().plot_x2, derived().x_axis);
+ derived().plot_x1, derived().x_axis, // y = 0
+ derived().plot_x2, derived().x_axis); // y = 0
     }
 
     // x_minor_jump is the interval between minor ticks.
@@ -364,9 +396,8 @@
     // Use whichever is the biggest of point marker and font.
 
     double spacing = (std::max)(font_size, point_size);
- bool is_header = (derived().legend_header_.text() != "");
     // std::cerr << spacing << ' ' << font_size << ' ' << point_size << endl;
- double legend_width(0); //
+ bool is_header = (derived().legend_header_.text() != "");
     size_t longest = 0;
     for(unsigned int i = 0; i < derived().series.size(); ++i)
     { // Find the longest text in all the data series.
@@ -377,7 +408,7 @@
         longest = siz;
       }
     }
- legend_width = (6 + longest /2) * spacing;
+ double legend_width = (6 + longest /2) * spacing;
     // font_size is not exact because width varies.
     // Allow for a leading space, data marker symbol, space,
     // line in color (only if 2-D and line option selected TODO)
@@ -387,14 +418,13 @@
     // the legend title and text_margin_s around it
     // (if any) plus a text_margin_ top and bottom.
     // Add more height depending on the number of lines of text.
- double legend_height = 2. * spacing;
- if (derived().use_title) // plot title
- // && derived().legend_header_.text() != "" leave space even if no string?
+ double legend_height = spacing;
+ if ( (derived().use_title) // plot title
+ && (derived().legend_header_.text() != "")) // & really is a legend title.
     {
- legend_height += spacing;
+ legend_height += 2 * spacing;
     }
     legend_height += num_points * spacing * 2; // Space for the point symbols & text.
- // legend_height += spacing; // At bottom. Not needed?
 
     // x, y position of legend 'box' top left, level with top right of plot window.
     double legend_x_start(derived().plot_x2);
@@ -403,13 +433,13 @@
 
     int x_size = derived().image.x_size();
     if((legend_x_start + legend_width) > x_size)
- { // Use all the image width available.
+ { // Use nearly all the image width available.
       std::cout << "Legend text line was too long by "
        << ((legend_x_start + legend_width) - x_size)
        << " pixels, & so truncated. legend_width == " << legend_width << std::endl;
       // For example:
       // "Legend text line was too long by about 84 pixels & so truncated. legend_width == 252"
- legend_width = x_size - legend_x_start - derived().text_margin_;
+ legend_width = x_size - legend_x_start - spacing; // derived().text_margin_;
       // text_margin_ just allows the border box to show.
     }
 
@@ -417,7 +447,7 @@
     g_element* g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_BACKGROUND));
     g_ptr->push_back(new
       rect_element(legend_x_start, legend_y_start, legend_width, legend_height));
- derived().legend_x1_ = legend_x_start; // Save for acces by legend_to_left
+ derived().legend_x1_ = legend_x_start; // Save for access by legend_to_left.
     derived().legend_x2_ = legend_width;
     derived().legend_y1_ = legend_y_start; // and legend_bottom_right.
     derived().legend_y2_ = legend_height;
@@ -443,32 +473,27 @@
       g_inner_ptr->style()
         .fill_color(derived().series[i].point_style.fill_color)
         .stroke_color(derived().series[i].point_style.stroke_color);
+ if(derived().series[i].point_style.shape != none)
+ {
+ draw_plot_point( // Plot point like circle, square...
+ legend_x_start + spacing, // space before point marker.
+ legend_y_pos,
+ *g_inner_ptr,
+ derived().series[i].point_style);
+ legend_x_pos += 2 * spacing;
+ }
 
- draw_plot_point( // Plot point like circle, square...
- legend_x_start + spacing, // space before point marker.
- legend_y_pos,
- *g_inner_ptr,
- derived().series[i].point_style);
- legend_x_pos += 2 * spacing ;
-
- // TODO line markers properly
- // only really applicable to 2-D sets plot_line_style,
- // but svg_1d_plot does NOT DEFINE line_style.
- // Meanwhile use svg_1d_plot .use_line and point color.
- // SHOULD use both fill & stroke colors from the line's style.
- // bool line_on = derived().series[i].plot_line_style.line_on;
- // svg_color col = derived().series[i].plot_line_style.color;
+ // Line markers - only really applicable to 2-D sets plot_line_style,
       if (derived().use_line)
       { // Need to draw a short line to show color for that data series.
- g_inner_ptr->style() // Use fill & stroke colors from point style. (Should be plot_line_style!)
- .fill_color(derived().series[i].point_style.fill_color)
- .stroke_color(derived().series[i].point_style.stroke_color);
+ g_inner_ptr->style() // Use fill & stroke colors from line style.
+ .stroke_color(derived().series[i].line_style.color);
         g_inner_ptr->push_back(new line_element(
- legend_x_pos,
+ legend_x_pos + spacing /2., // half space leading space
           legend_y_pos,
- legend_x_pos + spacing, // line sample is one char long.
+ legend_x_pos + spacing * 1.5, // line sample is one char long.
           legend_y_pos));
- legend_x_pos += 2 * spacing; // line & space.
+ legend_x_pos += 2. * spacing; // short line & space.
       } // use_line
 
       // Legend text for each Data Series added to the plot.
@@ -477,8 +502,9 @@
         legend_x_pos, // allow space for the marker.
         legend_y_pos,
         derived().series[i].title, // Text for this data series.
- derived().legend_header_.font_size(), // font size
- "", "", "", "", "", // TODO full font info for legend needed here?
+ derived().legend_header_.font_size(), // font size &
+ derived().legend_header_.font_family(), // font family.
+ "", "", "", "",
         left_align));
       legend_y_pos += 2 * spacing;
     } // for
@@ -1049,21 +1075,15 @@
     return derived().image.coord_precision();
   }
 
- Derived& value_precision(int digits)
- { // Precision of tick label values in decimal digits (default 3).
- derived().value_precision_(digits);
+ Derived& x_value_precision(int digits)
+ { // Precision of X tick label values in decimal digits (default 3).
+ derived().x_value_precision_ = digits;
     return derived();
   }
 
- int value_precision()
+ int x_value_precision()
   { //
- return derived().value_precision_;
- }
-
- Derived& title(const std::string title)
- { // Plot title.
- derived().title_info.text(title);
- return derived();
+ return derived().x_value_precision_;
   }
 
   const std::string title()
@@ -1159,6 +1179,17 @@
     return derived().title_info.font_alignment();
   }
 
+ Derived& legend_width(double width)
+ {
+ derived().legend_width_ = width;
+ return derived();
+ }
+
+ double legend_width()
+ {
+ return derived().legend_width_;
+ }
+
   Derived& legend_title(const std::string title)
   {
     derived().legend_header_.text(title);
@@ -1170,6 +1201,17 @@
     return derived().legend_header_.text();
   }
 
+ Derived& legend_font_family(const std::string& family)
+ {
+ derived().legend_header_.font_family(family);
+ return derived();
+ }
+
+ const std::string& legend_font_family()
+ {
+ return derived().legend_header_.font_family();
+ }
+
   Derived& legend_title_font_size(unsigned int size)
   {
     derived().legend_header_.font_size(size);
@@ -1347,7 +1389,6 @@
     return derived().plot_y2;
   }
 
-
   std::pair<double, double> plot_window_y()
   {
     std::pair<double, double> r;
@@ -1423,6 +1464,24 @@
     return derived().x_label_info.font_family();
   }
 
+ Derived& x_value_ioflags(int flags)
+ { // IO flags of X tick label values (default 0X201).
+ derived().x_value_ioflags_ = flags;
+ return derived();
+ }
+
+ int x_value_ioflags()
+ { // ALL stream ioflags for control of format of X value labels.
+ return derived().x_value_ioflags_;
+ }
+
+ Derived& title(const std::string title)
+ { // Plot title.
+ derived().title_info.text(title);
+ return derived();
+ }
+
+
   Derived& x_axis_label_color(const svg_color& col)
   { // Set BOTH stroke and fill to the same color.
     derived().image.get_g_element(detail::PLOT_X_LABEL).style().fill_color(col);
@@ -1480,15 +1539,15 @@
     return derived().use_x_major_labels;
   }
 
- Derived& x_major_label_up(bool cmd)
+ Derived& x_major_label_rotation(int rot)
   {
- derived().use_x_label_up_ = cmd;
+ derived().x_label_rotation_ = rot;
     return derived();
   }
 
- bool x_major_label_up()
+ int x_major_label_rotation()
   {
- return derived().use_x_label_up_;
+ return derived().x_label_rotation_;
   }
 
   Derived& title_on(bool cmd)
@@ -1574,13 +1633,13 @@
     return derived().image.get_g_element(PLOT_TITLE).style().stroke_color();
   }
 
- Derived& title_width(double width)
+ Derived& title_font_width(double width)
   { // width of text is effectively the boldness
     derived().image.get_g_element(PLOT_TITLE).style().stroke_width(width);
     return derived();
   }
 
- double title_width()
+ double title_font_width()
   {
     return derived().image.get_g_element(PLOT_TITLE).style().stroke_width();
   }
@@ -1598,13 +1657,13 @@
     return derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_color();
   }
 
- Derived& legend_width(double width)
- { // width of text is effectively the boldness
- derived().image.get_g_element(PLOT_LEGENDTEXT).style().stroke_width(width);
+ Derived& legend_font_width(double width)
+ { // width of text is effectively the boldness.
+ derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width(width);
     return derived();
   }
 
- double legend_width()
+ double legend_font_width()
   {
     return derived().image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width();
   }

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 2007-12-03 14:21:18 EST (Mon, 03 Dec 2007)
@@ -340,9 +340,13 @@
   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.
+ downhill = 45, // slope down.
     downward = 90, // vertical writing down.
- upsidedown = 180 //
+ backdown = 135, // slope down backwards.
+ upsidedown = 180 // == -180
   };
 
   // text_element::text_element(double x, double y,

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp 2007-12-03 14:21:18 EST (Mon, 03 Dec 2007)
@@ -133,12 +133,17 @@
   text_element title_info; // Plot title.
   text_element legend_header_; // legend box header or title (if any).
   text_element x_label_info; // For example: "length"
+ text_element x_label_value; // For example: "1.2" or "1.2e+001"
   text_element y_label_info; // For example: "volume"
   text_element x_units_info; // For example: "mm"
   text_element y_units_info; // 2-D only.
+ text_element y_label_value; // For example: "1.2" or "1.2e+001"
 
- int value_precision_; // precision for tick value labels, usually 3 will suffice.
+ int x_value_precision_; // precision for tick value labels, usually 3 will suffice.
+ int y_value_precision_; // precision for tick value labels, usually 3 will suffice.
   // Used to decide how much space to allow for tick values.
+ int x_value_ioflags_; // IO formatting flags for X-axis.
+ int y_value_ioflags_; // IO formatting flags for Y-axis.
   double text_margin_; // Marginal space around text items like title,
   // as a fraction of font size, (pixels) (was fixed at 1.5).
   double border_margin_; // Marginal (pixels) space around the plot border.
@@ -166,8 +171,9 @@
   // text width is effectively the boldness of the font.
   // 0 is default, 1 is bolder, 2 very bold...
   // TODO SVG has also a not yet implemented boldness.
- double title_width_;
- double legend_width_;
+ double title_font_width_;
+ double legend_font_width_;
+ double legend_width_; // width of legend box in pixels.
   double legend_x1_; // Left of legend box. (Optionally set by legend_position).
   double legend_y1_; // Top of legend box.
   // Size of legend box is controlled by its contents,
@@ -215,8 +221,8 @@
   bool use_y_major_labels;
   bool use_x_label_units;
   bool use_y_label_units;
- bool use_x_label_up_; // X_axis value labels written vertically up.
- bool use_y_label_up_; // Y_axis value labels written vertically up.
+ int x_label_rotation_; // X_axis value labels written vertically up.
+ int y_label_rotation_; // Y_axis value labels written vertically up.
   bool use_x_major_grid_;
   bool use_x_minor_grid_;
   bool use_y_major_grid_;
@@ -256,22 +262,31 @@
     // See documentation for default settings rationale.
 
     title_info(0, 0, "Plot of data", 16, "Verdana", "", "", "", "", center_align, horizontal),
- title_width_(1), // text width is effectively the boldness of the font.
- legend_width_(0.5),
+ title_font_width_(1), // text width is effectively the boldness of the font.
+ legend_width_(200), // width of legend box (pixels)
+ legend_header_(0, 0, "", 14, "Verdana", "", "", "", "", center_align, horizontal),
+ legend_font_width_(0.5),
     x_label_info(0, 0, "X Axis", 14, "Verdana", "", "", "", "", center_align, horizontal),
+ x_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, horizontal),
+ // TODO use this and provide way to set'n'get separately.
     x_label_width_(0.5),
     y_label_info(0, 0, "Y Axis", 14, "Verdana", "", "", "", "", center_align, upward),
+ y_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, upward),
     y_label_width_(0.5),
+ x_label_rotation_(horizontal),
+ y_label_rotation_(horizontal),
     x_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, horizontal),
     y_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, upward),
     // Plot may look odd if font and size of label & units are different!
     // y_units_info(0, 0, "(units)", 11, "Times New Roman", "italic", "bold", "wider", "underline", right_align, upsidedown),
     // shows some values that might be useful if svg browsers are fully implemented
     // to support font modification to text characters.
- value_precision_(3), // precision for tick value labels, usually 3 will suffice.
- // TODO provide a way of controlling scientific format.
- text_margin_(2.), // for text was 1.5
- // as a multiplier of the font size.
+ x_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
+ x_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
+ y_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
+ y_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
+ // Note that ALL the flags are set, overwriting the defaults.
+ text_margin_(2.), // for text, as a multiplier of the font size.
     border_margin_(5), // Prevent plot window box begin right on edge?
     // plot_x1, x2, y1, 2 are set in calculate_plot_window
     border_width_(2), // width of border to plot window and legend box.
@@ -316,8 +331,6 @@
     use_y_label_units(false),
     use_x_major_labels(true), // tick value labels.
     use_y_major_labels(true),
- use_x_label_up_(false),
- use_y_label_up_(false),
     use_x_label(true), // "X-axis"
     use_y_label(true), // "Y-axis" - true for 2-D, false for 1-D.
     use_title(true),
@@ -361,10 +374,10 @@
     image.get_g_element(PLOT_Y_LABEL).style().stroke_color(black).stroke_width(y_label_width_);
     image.get_g_element(PLOT_VALUE_LABELS).style().stroke_color(black).stroke_width(x_label_width_); // text
     // TODO?? Y label width?
- image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width(legend_width_);
- image.get_g_element(PLOT_TITLE).style().stroke_width(title_width_); //
+ image.get_g_element(PLOT_LEGEND_TEXT).style().stroke_width(legend_font_width_);
+ image.get_g_element(PLOT_TITLE).style().stroke_width(title_font_width_); //
     image.get_g_element(PLOT_TITLE).style().stroke_color(black);
- // If color is not set, then get a very 'thin' font and width has not effect!
+ // If color is not set, then get a very 'thin' font and width has no effect!
 
     // Note that widths are stored in member data *and* copied here.
     // Not sure if this is wise but ...
@@ -384,7 +397,7 @@
     // Grids.
     // TODO these may not be needed here - they MUST be set at call time in case use_x_major_grid_ has changed.
     if(use_x_major_grid_)
- {
+ { // pale blue.
       image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width(x_major_grid_width_).stroke_color(svg_color(200, 220, 255));
     }
     if(use_x_minor_grid_)
@@ -466,31 +479,70 @@
       plot_x2 -= plot_border_width();
       plot_y1 += plot_border_width();
       plot_y2 -= plot_border_width();
-
+ // Even after reading http://www.w3.org/TR/SVG/fonts.html, unclear how to
+ // determine the width of digits, so an arbitrary width height ratio is used:
+ const double wh = 0.7; // width compared to font height (assume size is this).
+ static const double sin45 = 0.707;
       if(use_legend)
       { // Space for legend at right.
         // TODO what if want legend elsewhere?
- plot_x2 -= 150; // This width 150 is an arbitrary legend box width.
+ plot_x2 -= legend_width_; // legend box width.
         // TODO size could depend on font_size & length of text??? Sounds tricky.
       }
       if (use_y_major_labels && use_y_ticks_on_plot_window_)
- { // Move edge right to give space for value_precision_ digits.
- // (perhaps allow + 1 for negative sign? What about exponent?).
- plot_x1 += y_label_info.font_size() * (value_precision_ * 0.7);
- // 0.7 because not as wide as high.
+ { // Move plot window right to make space for value labels.
+ // We would really like to know the length of the longest value label here!
+ // Might convert the max and then use its .length()?
+ int l = (y_value_precision_ + 2);
+ if(y_value_ioflags_ & std::ios::scientific)
+ { // ALso need space for e, sign & 3 exponent digits = 5)
+ l += 5;
+ }
+ else if(y_value_ioflags_ & std::ios::fixed)
+ { // Need space for decimal point & sign & at least 1 more digit)
+ l += 3;
+ }
+ if (y_label_rotation_ == horizontal)
+ { // Move edge right to give space for y_value_precision_ digits.
+ plot_x1 += y_label_info.font_size() * (l * wh);
+ }
+ else if((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
+ { // Only need one char width.
+ plot_x1 += y_label_info.font_size() * 1.5;
+ }
+ else
+ { // assume some slope 45? So diagonally down from tick,
+ // and takes a bit less room.
+ plot_x1 += y_label_info.font_size() * l * wh * sin45;
+ }
       }
       if (use_x_major_labels && use_x_ticks_on_plot_window_)
- { // Move bottom up to give space for value_precision_ digits.
+ { // Move bottom up to give space for x value labels
+ // x_value_precision_ digits.
         // (perhaps + 1 for negative sign?).
- if (use_x_label_up_)
- {
- plot_y2 -= x_label_info.font_size() * (value_precision_ * 0.7);
- // 0.7 because not as wide as high.
+ double l = x_value_precision_ + 1 + 1; // sign & decimal point.
+ if (x_value_ioflags_ == std::ios::scientific)
+ { // space for e+000
+ l += 5;
+ }
+ else if(y_value_ioflags_ & std::ios::fixed)
+ { // Need space for decimal point & sign & at least 1 more digit)
+ l += 3;
+ }
+
+ if ((x_label_rotation_ == upward) || (x_label_rotation_ == downward))
+ { // need
+ l += 2; // space at top and bottom?
+ }
+ else if(x_label_rotation_ != horizontal)
+ { // Only 1 char height needed if horizontal.
+ l = 2;
         }
         else
- { // Only 1 char height needed.
- plot_y2 -= x_label_info.font_size();
+ { // assume some slope, say 45 sin(45) = 0.707?
+ l *= 0.707;
         }
+ plot_y2 -= x_label_info.font_size() * (l * wh);
       }
       if(use_left_ticks)
       { // Reduce plot to give space for biggest of any external left ticks.
@@ -573,14 +625,13 @@
   } // void draw_y_minor_ticks
 
   void draw_y_major_ticks(double value, path_element& tick_path, path_element& grid_path)
- { // Draw Y axis major ticks, grids & tick value labels.
+ { // Draw Y axis major ticks, tick value labels & grids.
     double y1(value);
     transform_y(y1); // cartesian to SVG coordinates.
     double x1(0.); // left end of tick.
     double x2(image.y_size()); // right end of tick.
     if(use_y_major_grid_)
     { // Draw horizontal major grid line.
-
       if(!use_plot_window)
       { // TODO is this right?
         //if (use_title())
@@ -591,13 +642,14 @@
         { // Start further right to give space for y axis value label.
           y1 -= y_label_info.font_size() * text_margin_ ;
         }
+
         if(use_left_ticks)
         { // And similarly for left ticks.
           y1 -= y_major_tick_length_;
         }
       }
       else
- { // use_plot_window
+ { // Do use_plot_window.
         x1 = plot_x1 + 1;
         x2 = plot_x2 - 1;
       }
@@ -630,42 +682,60 @@
     }
 
     if(use_y_major_labels)
- { // Label the tick with value, for example "1.3"
+ { // Label the tick with value, for example "1.2"
       std::stringstream label;
- // TODO precision(?) - may be ugly because precision(6) if we do nothing.
- label << value; // Example: label.str() == "20" or "0.25"
+ label.precision(y_value_precision_);
+ label.flags(y_value_ioflags_); // set ALL IOflags.
+ label << value; // Example: label.str() == "20" or "0.25" or "1.2e+015"
       if(use_left_ticks)
       {
         if (y_minor_tick_length_ > y_minor_tick_length_)
- { // In case some joker has made the minor ticks are long than the major,
+ { // In case some joker has made the minor ticks longer than the major,
           // we might need to move left more for the longer tick.
           x1 -= (y_minor_tick_length_ - y_minor_tick_length_);
         }
- x1 -= y_label_info.font_size() / text_margin_; // font height.
+ x1 -= y_label_info.font_size(); // move left by a font width.
       }
       else
       { // No need to move if right tick, or none.
       }
-
+ // Need to work out how much space value labels will need.
+ double y = y1;
+ align_style alignment = center_align;
       if(use_y_ticks_on_plot_window_)
- { // Always want all values including "0" if labelling on the external plot window.
+ { // External to plot window style.
+ if(y_label_rotation_ == horizontal)
+ { // Just shift down half a digit to center value digits on tick.
+ alignment = right_align;
+ y += y_label_info.font_size() / 2;
+ }
+ else if ((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
+ {// Tick value label straight up or down vertically on y axis.
+ // No shift y down to center.
+ alignment = center_align;
+ }
+ else
+ { // Assume some 45 slope, so need about sqrt(2) less space?
+ x1 += y_label_info.font_size() * 0.5; // move left by half a font width.
+ // no y shift needed.
+ alignment = right_align;
+ }
+ // Always want all values including "0", if labeling external to plot window.
         image.get_g_element(detail::PLOT_VALUE_LABELS).text(
           x1,
- y1 + y_label_info.font_size() / 2, // shift down to center value digits on tick.
- label.str(), y_label_info.font_size(), "", "", "", "", "", right_align, horizontal);
- // Might want to label tick values vertically on y axis?
- // then use center_align and no shift down to center.
+ y,
+ label.str(), y_label_info.font_size(), "", "", "", "", "", alignment, y_label_rotation_);
       }
       else
- { // Internal - value labels close to left of vertical Y-axis.
+ { // ! use_y_ticks_on_plot_window_Internal - value labels close to left of vertical Y-axis.
         if ((value != 0) && use_x_axis_lines_)
- { // Avoid a zero ON the Y-axis if it would be cut through by the horizontal X-axis line.
+ { // Avoid a zero ON the Y-axis as it would be cut through by the horizontal X-axis line.
+ y += y_label_info.font_size() / 2;
           image.get_g_element(detail::PLOT_VALUE_LABELS).text(x1,
- y1,
- label.str(), y_label_info.font_size(), y_label_info.font_family(),
- "", "", "", "", center_align, // on the tick
- upward); // -90 degree rotation.
- // If want to write horizontal ??
+ y, // Just shift down half a digit to center value digits on tick.
+ label.str(), y_label_info.font_size(), y_label_info.font_family(), "", "", "", "",
+ center_align, // on the tick ???
+ y_label_rotation_);
         }
       }
     } // if(use_y_major_labels)
@@ -739,14 +809,15 @@
     }
 
     image.get_g_element(detail::PLOT_Y_LABEL).push_back(new
- text_element(y_label_info.font_size() * text_margin_,
+ text_element(y_label_info.font_size() * 1.5,
       // shift over one char height to right from left edge of image.
       (plot_y2 + plot_y1) / 2., // center on the plot window.
       label, // "Y-Axis" for example.
        y_label_info.font_size(),
        y_label_info.font_family(),
- "", "", "", "", center_align,
- upward)); // Y label must be drawn vertically.
+ "", "", "", "",
+ center_align, // One might want it to left or right_align?
+ upward)); // Y label must be drawn vertically.
   } // draw_y_label
 
   void draw_straight_lines(const svg_2d_plot_series& series)
@@ -1039,7 +1110,6 @@
     return use_x_label;
   }
 
-
   svg_2d_plot& y_major_labels_on(bool cmd)
   {
     use_y_major_labels = cmd;
@@ -1051,15 +1121,15 @@
     return use_y_major_labels;
   }
 
- svg_2d_plot& y_major_label_up(bool cmd)
+ svg_2d_plot& y_major_label_rotation(int rot)
   {
- use_y_label_up_ = cmd;
+ y_label_rotation_ = rot;
     return *this;
   }
 
- bool y_major_label_up()
+ int y_major_label_rotation()
   {
- return use_y_label_up_;
+ return y_label_rotation_;
   }
 
   svg_2d_plot& y_axis_width(double width)
@@ -1073,6 +1143,34 @@
     return image.get_g_element(detail::PLOT_Y_AXIS).style().stroke_width();
   }
 
+ svg_2d_plot& y_value_precision(int digits)
+ { // Precision of Y tick label values in decimal digits (default 3).
+ y_value_precision_ = digits;
+ return *this;
+ }
+
+ int y_value_precision()
+ { // Precision of Y tick label values in decimal digits (default 3).
+ return y_value_precision_;
+ }
+
+ svg_2d_plot& y_value_ioflags(int flags)
+ { // IO flags of Y tick label values (default 0X201).
+ y_value_ioflags_ = flags;
+ return *this;
+ }
+
+ int y_value_ioflags()
+ { // ALL stream ioflags for control of format of Y value labels.
+ return y_value_ioflags_;
+ }
+
+ //Derived& title(const std::string title)
+ //{ // Plot title.
+ // derived().title_info.text(title);
+ // return derived();
+ //}
+
   svg_2d_plot& y_axis_color(const svg_color& col)
   { // Set BOTH stroke and fill to the same color.
     image.get_g_element(detail::PLOT_Y_AXIS).style().fill_color(col);
@@ -1377,7 +1475,7 @@
   }
 
   svg_2d_plot& y_label_font_size(unsigned int i)
- { // TODO May be best to tie these two font sizes together?
+ { // May be best to tie label & unit font sizes together?
     y_label_info.font_size(i);
     // y_units_info.font_size(i);
     return *this;

Modified: sandbox/SOC/2007/visualization/libs/svg_plot/doc/svg_plot.qbk
==============================================================================
--- sandbox/SOC/2007/visualization/libs/svg_plot/doc/svg_plot.qbk (original)
+++ sandbox/SOC/2007/visualization/libs/svg_plot/doc/svg_plot.qbk 2007-12-03 14:21:18 EST (Mon, 03 Dec 2007)
@@ -1388,8 +1388,56 @@
 [endsect] [/section:svg_2d_plot_interface]
 [endsect] [/section:interface]
 
+
+
+
 [section:implementation Implementation & Rationale]
 
+[h4 Controlling the format of Label values]
+
+Both the X and Y axis tick can be labelled with their values.
+
+The precision (number of decimal digits used) for both x and y
+can be controlled using the function
+`.x_value_precision(int);` and `.y_value_precision(int);`
+
+for example, `my_plot..y_value_precision(1) would suffice
+for values in a limited range, like from 0.0 to 0.5.
+
+The default is chosen to be 3
+(otherwise the C++ Standard default precision of 6 would be chosen,
+a rather larger precision than is typically required).
+
+If a lower precision is acceptable for the values used to label the axis,
+this will reduce the length and space required for the label.
+
+It may also be necessary to use exponent format to avoid either
+extremely long labels, or labels that are all the same.
+To control formatting, two functions
+`.x_value_ioflags(int);` and `.y_value_ioflags(int);`
+
+are provided and these provide control in the normal C++ Standard library
+iostream function `flags(int)`.
+
+Note that this function sets *all* the flags, so to obtain 'default' behaviour
+it is probably necessary to at least set the decimal bit with `ios::dec`.
+
+You may wish to prevent exponent format by including `ios::fixed`.
+
+Other settings can be added with other format flags, most usefully `ios::scientific`.
+
+[note It is, of course, possible to produce combinations that are probably not desired,
+like `ios::hex` | `ios::scientific` or whose effect is undefined behaviour.]
+
+If you need or want to use scientific (exponential format) it is unfortunate that
+the standard library specification always requires 3 exponent digits to be used:
+this is ugly, takes up valuable space and is rarely necessary,
+and indeed impossible with floats.
+
+However, with some experimentation, it is possible to label ticks values reasonably well.
+
+
+
 [h4 Number of Minor ticks]
 
 `x_num_minor_ticks()` and `x_num_minor_ticks()`
@@ -1422,7 +1470,7 @@
 
 
 This section provide more information about this implementation
-and some of the rationale for desing decisions.
+and some of the rationale for design decisions.
 
 [h4 SVG Specification]
 

Modified: sandbox/SOC/2007/visualization/libs/svg_plot/test/2d_color_consistency.cpp
==============================================================================
--- sandbox/SOC/2007/visualization/libs/svg_plot/test/2d_color_consistency.cpp (original)
+++ sandbox/SOC/2007/visualization/libs/svg_plot/test/2d_color_consistency.cpp 2007-12-03 14:21:18 EST (Mon, 03 Dec 2007)
@@ -13,12 +13,17 @@
 # pragma warning(disable : 4180) // warning C4180: qualifier applied to function type has no meaning; ignored
 # pragma warning(disable : 4172) // warning C4180: qualifier applied to function type has no meaning; ignored
 
-# pragma warning(disable : 4310) // cast truncates constant value
-# pragma warning(disable : 4512) // assignment operator could not be generated
-# pragma warning(disable : 4702) // unreachable code
+// added to boost.test/detail supress_warnings
+//# pragma warning(disable : 4310) // cast truncates constant value
+//# pragma warning(disable : 4512) // assignment operator could not be generated
+//# pragma warning(disable : 4702) // unreachable code
 #endif
 
-#include <boost/test/included/test_exec_monitor.hpp>
+#define BOOST_TEST_MAIN
+// Must come BEFORE this include.
+#include <boost/test/included/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
 #include <boost/svg_plot/svg_2d_plot.hpp>
 using namespace boost::svg;
 
@@ -26,7 +31,7 @@
 using std::cout;
 using std::endl;
 
-int test_main(int, char*[])
+BOOST_AUTO_TEST_CASE( test1 )
 {
         svg_2d_plot my_plot;
 
@@ -45,7 +50,7 @@
   my_plot.y_label("Y"); //
          BOOST_CHECK_EQUAL(my_plot.y_label(), "Y"); // & check.
 
- BOOST_CHECK_EQUAL(my_plot.x_ticks_up_on(), true); // Check default.
+ BOOST_CHECK_EQUAL(my_plot.x_ticks_up_on(), false); // Check default.
   my_plot.x_ticks_up_on(false); // Set
          BOOST_CHECK_EQUAL(my_plot.x_ticks_up_on(), false); // & check.
          BOOST_CHECK_EQUAL(my_plot.x_ticks_up_on(), false); // & check.
@@ -55,10 +60,10 @@
          BOOST_CHECK_EQUAL(my_plot.x_ticks_down_on(), false); // & check.
          BOOST_CHECK_EQUAL(my_plot.x_ticks_down_on(), false); // & check.
 
- BOOST_CHECK_EQUAL(my_plot.y_ticks_right_on(), true); // Check default.
- my_plot.y_ticks_right_on(false); // Set
- BOOST_CHECK_EQUAL(my_plot.y_ticks_right_on(), false); // & check.
- BOOST_CHECK_EQUAL(my_plot.y_ticks_right_on(), false); // & check.
+ BOOST_CHECK_EQUAL(my_plot.y_ticks_right_on(), false); // Check default.
+ my_plot.y_ticks_right_on(true); // Set
+ BOOST_CHECK_EQUAL(my_plot.y_ticks_right_on(), true); // & check.
+ BOOST_CHECK_EQUAL(my_plot.y_ticks_right_on(), true); // & check.
 
   BOOST_CHECK_EQUAL(my_plot.y_ticks_left_on(), true); // Check default.
   my_plot.y_ticks_left_on(false); // Set
@@ -148,8 +153,9 @@
         BOOST_CHECK(my_plot.legend_background_color() == svg_color(0, 0, 3));
         BOOST_CHECK(my_plot.background_color() == svg_color(0, 0, 2));
         BOOST_CHECK(my_plot.background_border_color() == svg_color(0, 0, 1));
- return 0;
-}
+
+} // BOOST_AUTO_TEST_CASE( test1 )
+
 
 /*
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk