Boost logo

Boost-Commit :

From: pbristow_at_[hidden]
Date: 2008-01-23 06:57:21


Author: pbristow
Date: 2008-01-23 06:57:20 EST (Wed, 23 Jan 2008)
New Revision: 42924
URL: http://svn.boost.org/trac/boost/changeset/42924

Log:
Changes to check actual length of strings including unicode greek etc avoiding legend box containing greek etc width being wildly overestimated.
Text files modified:
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp | 74 +++++++++++++++++----------
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp | 63 ++++++++++++-----------
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp | 85 +++++++++++++++++++------------
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_boxplot.hpp | 26 ++++----
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_style.hpp | 105 ++++++++++++++++++++++++++++++---------
   sandbox/SOC/2007/visualization/libs/svg_plot/example/demo_2d_plot.cpp | 14 ++++
   6 files changed, 237 insertions(+), 130 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-01-23 06:57:20 EST (Wed, 23 Jan 2008)
@@ -28,11 +28,6 @@
     //JV: G++ can't resolve names in these enums in axis_plot_frame
     // when they are in svg_2d_plot.hpp
 
- static const double wh = 0.7; // font text width/height ratio.
- // Even after reading http://www.w3.org/TR/SVG/fonts.html, unclear how to
- // determine the exact width of digits, so an
- // arbitrary average width height ratio wh = 0.7 is used as a good approximation.
-
     static const double sin45 = 0.707; // Use if axis value labels are sloping.
 
     // x_axis_position_ and y_axis_position_ use these.
@@ -275,7 +270,7 @@
               }
             }
             else
- { // Internal_style, draw tick from the central X axis line.
+ { // Draw tick from the central X axis line (Internal_style).
               y_up = derived().x_axis_.axis_; // X-axis line.
               y_down = derived().x_axis_.axis_;
               if(derived().x_ticks_.up_ticks_on_)
@@ -301,7 +296,7 @@
                 std::string v = strip_e0s(label.str());
                 label.str(v);
               }
- double y = y_down; // bottom end of the tick.
+ double y = (derived().x_ticks_.major_value_labels_on_ < 0) ? y_down : y_up; // bottom or top end of the tick.
               align_style alignment = center_align;
               if(derived().x_ticks_.down_ticks_on_)
               { // No need to shift if derived().up_ticks_on_ as labels are below the X-axis.
@@ -310,7 +305,7 @@
               if (derived().x_ticks_.label_rotation_ == upward)
               { //
                 alignment = right_align;
- x -= derived().x_label_info_.style().font_size() * 0.3; // To centre digit and - on tick.
+ x -= derived().x_label_info_.style().font_size() * 0.3; // To centre digit and minus (or plus) sign - on tick.
                 //y += label.str().size() * derived().x_label_info_.font_size() * 0.5; // Part digit space.
                 // so the last digit will be by the tick.
               }
@@ -466,6 +461,9 @@
           // Update title_info_ with position.
           derived().title_info_.x(derived().image.x_size() / 2.); // Center of image.
           // Assumes align = center_align.
+ // And center_align will ensure that will center correctly
+ // even if original string is long because contains Unicode like &#x3A9;
+ // because the render engine does the centering.
           double y;
           y = derived().title_info_.style().font_size() * derived().text_margin_; // Leave a linespace above.
           derived().title_info_.y(y);
@@ -488,7 +486,7 @@
           else
           { // legend_on_ == true
             // Work out the size the legend box needs to be to hold the
- // header, markers & text.
+ // header, markers, lines & text.
             size_t num_series = derived().series.size(); // How many data series.
             int font_size = derived().legend_header_.style().font_size();
             int point_size = derived().series[0].point_style_.size();
@@ -497,22 +495,25 @@
             // std::cout << spacing << ' ' << font_size << ' ' << point_size << std::endl;
             bool is_header = (derived().legend_header_.text() != "");
 
- size_t longest = derived().legend_header_.text().size();
+ double longest = string_svg_length(derived().legend_header_.text(), derived().legend_style_);
+ std::cout << "\nLegend header " << longest << " svg units." << std::endl;
+
+ //text_element legend_header_; // legend box header or title (if any).
+ //text_style legend_style_;
+ // was size_t longest = derived().legend_header_.text().size();
             // 0 if no header.
- for(unsigned int i = 0; i < num_series; ++i)
- { // Find the longest text in all the data series.
+ for(size_t i = 0; i < num_series; ++i)
+ { // Find the longest text (if longer than header) in all the data series.
               std::string s = derived().series[i].title_;
- size_t siz = s.size();
+ double siz = string_svg_length(s, derived().legend_style_);
               if (siz > longest)
               {
                 longest = siz;
               }
             } // for
- std::cout.flags(std::ios_base::dec);
- // std::cout << "\nLongest legend header or data descriptor " << longest << " chars" << std::endl;
- derived().legend_width_ = (1 + longest)
- * ::boost::svg::wh
- * font_size;
+ // std::cout.flags(std::ios_base::dec); should not be needed TODO
+ std::cout << "\nLongest legend header or data descriptor " << longest << " svg units." << std::endl;
+ derived().legend_width_ = (1 + longest);
                                     
             // Allow for a leading space, longest text
             // & trailing space before box margin.
@@ -573,15 +574,15 @@
               }
               break;
                 // If outside then reserve space for legend by reducing plot window.
- case outside_right: // Default.
+ case outside_right: // Default legend position is outside_right,
               // so that it isn't too close to the image edge or the plot window.
               derived().plot_right_ -= derived().legend_width_ + spacing; // Narrow plot window from right.
- derived().legend_left_ = derived().plot_right_; // plot + border.
+ derived().legend_left_ = derived().plot_right_ + spacing; // plot + border.
               derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
               derived().legend_top_ = derived().plot_top_; // Level with top of plot window.
- //derived().legend_top_ += spacing; // down a bit? Or could center vertically?
               derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
               break;
+ // TODO other positions untested.
             case outside_left:
               derived().legend_left_ = derived().plot_left_ + spacing; // left edge + space.
               derived().plot_left_ += derived().legend_width_ + spacing; // Push plot window right to make room,
@@ -1420,7 +1421,7 @@
 
           Derived& title_font_alignment(align_style alignment)
           {
- derived().title_info_.font_alignment(alignment);
+ derived().title_info_.alignment(alignment);
             return derived();
           }
 
@@ -1485,7 +1486,7 @@
             return derived();
           }
 
- std::pair<double, double> legend_top_left()
+ const std::pair<double, double> legend_top_left()
           {// Top left of legend box.
             std::pair<double, double> r;
             r.first = derived().legend_left_;
@@ -1493,8 +1494,8 @@
             return r;
           }
 
- std::pair<double, double> legend_bottom_right()
- {// BOttom right of legend box.
+ const std::pair<double, double> legend_bottom_right()
+ {// Bottom right of legend box.
             std::pair<double, double> r;
             r.first = derived().legend_right_;
             r.second = derived().legend_bottom_;
@@ -1502,7 +1503,7 @@
           }
 
           Derived& legend_lines(bool is)
- {
+ { // If legend should include samples of the lines joining data points.
             derived().legend_lines_ = is;
             return derived();
           }
@@ -1544,6 +1545,19 @@
           {
             return derived().outside_legend_on_;
           }
+
+
+ Derived& legend_header_font_size(int size)
+ {
+ derived().legend_header_.style().font_size(size);
+ return *this;
+ }
+
+ int legend_header_font_size()
+ {
+ return derived().legend_header_.style().font_size();
+ }
+
           Derived& plot_window_on(bool cmd)
           {
             derived().plot_window_on_ = cmd;
@@ -1556,7 +1570,7 @@
             }
             //derived().legend_place_ = outside_right;
             return derived();
- }
+ }
 
           bool plot_window_on()
           {
@@ -1861,7 +1875,7 @@
           Derived& axes_on(bool is)
           { // Draw *both* x and y axes (note plural).
             derived().x_axis_.axis_line_on_ = is;
- derived().y_axis_.axis_line_on_ = is;
+ derived().y_axis_.axis_line_on_ = is; // Unsuitable for 1D?
             return derived();
           }
 
@@ -2286,6 +2300,10 @@
             }
             derived().x_axis_.min_ = min_x;
             derived().x_axis_.max_ = max_x;
+ //derived().x_ticks_.max_ = min_x;
+ //derived().y_ticks_.max_ = max_x;
+ // done in calculate_plot_window.
+ // TODO May be best to combine these?
             return derived();
           }
 

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp 2008-01-23 06:57:20 EST (Wed, 23 Jan 2008)
@@ -38,23 +38,26 @@
 {
   // Forward declarations.
   const std::string strip_e0s(std::string s); // Strip unncessary zeros and e and sign.
+ double string_svg_length(const std::string& s, const text_style& style);
+
   class svg_1d_plot; // Plot.
   class svg_1d_plot_series; // plot data series.
+ // see axis_plot_frame.hpp
 
- static const double wh = 0.7; // font text width/height ratio.
+// static const double wh = 0.7; // font text width/height ratio.
   // Even after reading http://www.w3.org/TR/SVG/fonts.html, unclear how to
   // determine the exact width of digits, so an
   // arbitrary average width height ratio wh = 0.7 is used as a good approximation.
 
- static const double sin45 = 0.707; // Use if axis value labels are sloping.
+// static const double sin45 = 0.707; // Use if axis value labels are sloping.
 
   // x_axis_position_ and y_axis_position_ use these.
- enum x_axis_intersect {bottom = -1, x_intersects_y = 0, top = +1};
+// enum x_axis_intersect {bottom = -1, x_intersects_y = 0, top = +1};
   // bottom = X-axis free below bottom of end of Y-axis (case of all Y definitely < 0).
   // top = X-axis free above top of X-axis (case of all Y definitely > 0).
   // x_intersects_y when Y values include zero, so X intersects the Y axis.
 
- enum y_axis_intersect {left = -1, y_intersects_x = 0, right = +1};
+// enum y_axis_intersect {left = -1, y_intersects_x = 0, right = +1};
   // left = Y-axis free to left of end of X-axis (case of all X definitely < 0).
   // right = Y-axis free to left of end of X-axis (case of all X definitely > 0).
   // y_intersects_x when X values include zero, so intersects the X axis.
@@ -271,6 +274,8 @@
     x_units_info_(0, 0, " (units)", x_value_label_style_, center_align, horizontal),
     x_label_value_(0, 0, "", x_value_label_style_, center_align, horizontal),
     x_axis_(X, -10., +10., black, 1, 0, true, false, true),
+ y_axis_(Y, 0., +1., black, 1, 0, false, false, false),
+
     // Might fill in all values, but there are rather many for ticks_labels_style,
     x_ticks_(X),// so for defaults see ticks_labels_style.
     image_border_(yellow, white, 2, 10, true, true), // margin should be about axis label font size.
@@ -304,21 +309,21 @@
     // Build the document tree & add all the children of the root node.
     for(int i = 0; i < detail::SVG_PLOT_DOC_CHILDREN; ++i)
     {
- image.add_g_element();
+ image.g();
     }
 
     // Set other SVG color, stroke & width defaults for various child PLOT nodes.
- image.get_g_element(PLOT_BACKGROUND).style().fill_color(image_border_.fill_);
- image.get_g_element(PLOT_BACKGROUND).style().stroke_color(image_border_.stroke_);
- image.get_g_element(PLOT_BACKGROUND).style().stroke_width(image_border_.width_); //
- image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color(plot_window_border_.fill_);
- image.get_g_element(PLOT_WINDOW_BACKGROUND).style().stroke_width(plot_window_border_.width_).stroke_color(plot_window_border_.stroke_);
- image.get_g_element(PLOT_LIMIT_POINTS).style().stroke_color(lightslategray).fill_color(antiquewhite);
- image.get_g_element(PLOT_X_AXIS).style().stroke_color(black).stroke_width(x_axis_.width());
- image.get_g_element(PLOT_X_LABEL).style().fill_color(black);
- image.get_g_element(PLOT_VALUE_LABELS).style().fill_color(black);
- image.get_g_element(PLOT_LEGEND_TEXT).style().fill_color(black);
- image.get_g_element(PLOT_TITLE).style().fill_color(black).stroke_on(false);
+ image.g(PLOT_BACKGROUND).style().fill_color(image_border_.fill_);
+ image.g(PLOT_BACKGROUND).style().stroke_color(image_border_.stroke_);
+ image.g(PLOT_BACKGROUND).style().stroke_width(image_border_.width_); //
+ image.g(PLOT_WINDOW_BACKGROUND).style().fill_color(plot_window_border_.fill_);
+ image.g(PLOT_WINDOW_BACKGROUND).style().stroke_width(plot_window_border_.width_).stroke_color(plot_window_border_.stroke_);
+ image.g(PLOT_LIMIT_POINTS).style().stroke_color(lightslategray).fill_color(antiquewhite);
+ image.g(PLOT_X_AXIS).style().stroke_color(black).stroke_width(x_axis_.width());
+ image.g(PLOT_X_LABEL).style().fill_color(black);
+ image.g(PLOT_VALUE_LABELS).style().fill_color(black);
+ image.g(PLOT_LEGEND_TEXT).style().fill_color(black);
+ image.g(PLOT_TITLE).style().fill_color(black).stroke_on(false);
 
     // Note that widths are stored in member data *and* copied here.
     // Not sure if this is wise but ...
@@ -326,15 +331,15 @@
     // Ticks
     if(x_ticks_.use_up_ticks() || x_ticks_.use_down_ticks())
     {
- image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width(x_ticks_.major_tick_width_).stroke_color(black);
- image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width(x_ticks_.minor_tick_width_).stroke_color(black);
+ image.g(PLOT_X_MAJOR_TICKS).style().stroke_width(x_ticks_.major_tick_width_).stroke_color(black);
+ image.g(PLOT_X_MINOR_TICKS).style().stroke_width(x_ticks_.minor_tick_width_).stroke_color(black);
     }
     // Grids.
     // Default color & width for grid, used or not.
- image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_width(x_ticks_.major_grid_width_).stroke_color(svg_color(200, 220, 255));
- BOOST_ASSERT(image.get_g_element(PLOT_X_MAJOR_GRID).style().stroke_color() == svg_color(200, 220, 255));
- image.get_g_element(PLOT_X_MINOR_GRID).style().stroke_width(x_ticks_.minor_grid_width_).stroke_color(svg_color(200, 220, 255));
- //image.get_g_element(PLOT_DATA_LINES).style().stroke_width(2); // default width.
+ image.g(PLOT_X_MAJOR_GRID).style().stroke_width(x_ticks_.major_grid_width_).stroke_color(svg_color(200, 220, 255));
+ BOOST_ASSERT(image.g(PLOT_X_MAJOR_GRID).style().stroke_color() == svg_color(200, 220, 255));
+ image.g(PLOT_X_MINOR_GRID).style().stroke_width(x_ticks_.minor_grid_width_).stroke_color(svg_color(200, 220, 255));
+ //image.g(PLOT_DATA_LINES).style().stroke_width(2); // default width.
     // Alter with plot.data_lines_width(4);
 
     legend_place_ = (plot_window_on_) ? outside_right : inside; // Defaults.
@@ -394,11 +399,11 @@
       }
       else if ((x_ticks_.label_rotation_ == upward) || (x_ticks_.label_rotation_ == downward))
       { // ! horizontal so will need more than 2 chars worth.
- x_label_length_+= x_ticks_.label_max_chars_ * x_value_label_style_.font_size() * wh; // SVG chars.
+ x_label_length_+= x_ticks_.label_max_width_ * x_value_label_style_.font_size() * wh; // SVG chars.
       }
       else
       { // Assume label is sloping, say 45, so * sin(45) = 0.707.
- x_label_length_+= x_ticks_.label_max_chars_ * x_value_label_style_.font_size() * wh * sin45; // SVG 'chars'.
+ x_label_length_+= x_ticks_.label_max_width_ * x_value_label_style_.font_size() * wh * sin45; // SVG 'chars'.
       }
 
       if (x_ticks_.major_value_labels_on_ != 0)
@@ -450,7 +455,7 @@
     if(plot_window_on_)
     {
       // Draw plot window rect.
- image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).push_back(
+ image.g(detail::PLOT_WINDOW_BACKGROUND).push_back(
         new rect_element(plot_left_, plot_top_, (plot_right_ - plot_left_), plot_bottom_ - plot_top_));
     } // plot_window_on_
   } // void calculate_plot_window()
@@ -490,7 +495,7 @@
         y1 = plot_top_;
         y2 = plot_bottom_;
       }
- image.get_g_element(detail::PLOT_X_AXIS).line(x, y1, x, y2);
+ image.g(detail::PLOT_X_AXIS).line(x, y1, x, y2);
     }
     draw_x_axis();
   } // draw_axes()
@@ -501,7 +506,7 @@
     clear_all();
 
     // Draw plot background.
- image.get_g_element(detail::PLOT_BACKGROUND).push_back(
+ image.g(detail::PLOT_BACKGROUND).push_back(
       new rect_element(0, 0, image.x_size(), image.y_size()));
 
     calculate_plot_window();
@@ -523,7 +528,7 @@
     transform_y(y);
     for(unsigned int i = 0; i < series.size(); ++i)
     { // For each of the data series.
- g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_POINTS).add_g_element();
+ g_element& g_ptr = image.g(detail::PLOT_DATA_POINTS).g();
 
       g_ptr.style().stroke_color(series[i].point_style_.stroke_color_);
       g_ptr.style().fill_color(series[i].point_style_.fill_color_);
@@ -548,7 +553,7 @@
   { // document ids for use in <g id = "PLOT_TITLE".../>
     for(int i = 0; i < detail::SVG_PLOT_DOC_CHILDREN; ++i)
     {
- image.get_g_element(i).id(detail::document_ids[i]);
+ image.g(i).id(detail::document_ids[i]);
     }
   } // void set_ids()
 

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 2008-01-23 06:57:20 EST (Wed, 23 Jan 2008)
@@ -215,7 +215,7 @@
       double legend_bottom_; // bottom of legend box.
       size_t legend_longest_; // longest (both header & data) string in legend box,
 
- axis_line_style x_axis_;
+ axis_line_style x_axis_;
       axis_line_style y_axis_;
 
       ticks_labels_style x_ticks_;
@@ -266,8 +266,8 @@
         x_axis_(X, -10., +10., black, 1, 0, true, false, true),
         y_axis_(Y, -10., +10., black, 1, 0, true, false, true),
         // Might fill in all values, but there are rather many for ticks_labels_style,
- x_ticks_(X),// so for defaults see ticks_labels_style.
- y_ticks_(Y),
+ x_ticks_(X, x_value_label_style_),// so for other defaults see ticks_labels_style.
+ y_ticks_(Y, y_value_label_style_),
         y_label_info_(0, 0, "Y Axis", y_axis_label_style_, center_align, upward),
         y_units_info_(0, 0, " (units)", y_axis_label_style_, center_align, upward),
         y_label_value_(0, 0, "", y_value_label_style_, center_align, upward),
@@ -389,8 +389,6 @@
           plot_top_ += title_font_size() * (text_margin_ + 0.5);
         }
 
- size_legend_box(); // Size depends on its contents.
- place_legend_box(); // according to options chosen.
        // Assume that axis labels are always at bottom and left.
        if(x_axis_.label_on_)
        { // Leave space at bottom for X axis label.
@@ -410,7 +408,10 @@
           plot_top_ += image_border_.margin_;
           plot_bottom_ -= image_border_.margin_;
         }
- // Check if the axes will intersect.
+ size_legend_box(); // Size depends on its contents.
+ place_legend_box(); // according to options chosen.
+
+ // Check if the axes will intersect.
         // X axis position is determined by the range of Y min and max label values.
         x_axis_position_ = x_intersects_y; // Assume X-axis will intersect Y-axis (range of Y values includes zero).
         if (y_axis_.min_ > std::numeric_limits<double>::min()) // all Y values definitely > zero.
@@ -437,8 +438,14 @@
           y_ticks_.ticks_on_plot_window_on_ = +1; // right = true;
         }
 
+ // Ensure both axis and ticks have the same range.
+ x_ticks_.max_ = x_axis_.max_;
+ x_ticks_.min_ = x_axis_.min_;
+ y_ticks_.max_ = y_axis_.max_;
+ y_ticks_.min_ = y_axis_.min_;
+
         // Calculate the number of chars of the longest value labels.
- x_ticks_.longest_label();
+ x_ticks_.longest_label(); // Updates label_max_width_
         y_ticks_.longest_label();
 
         // Check that labels won't collide and advise if they will.
@@ -447,16 +454,16 @@
         double y_label_length_ = 0.; // Width of y labels, depending on orientation.
         if (y_ticks_.label_rotation_ == horizontal)
         { // Move plot left edge right to give space for y_value_precision_ digits.
- y_label_length_ += y_ticks_.label_max_chars_ * y_axis_label_style_.font_size() * wh; // SVG units
+ y_label_length_ += y_ticks_.label_max_width_; // SVG units.
         }
         else if((y_ticks_.label_rotation_ == upward) || (y_ticks_.label_rotation_ == downward))
         { // Only need one char & 1 space width from Y-axis label.
- y_label_length_ += y_value_label_style_.font_size() * 2 * wh;
+ y_label_length_ += 2 * y_value_label_style_.font_size() * wh;
         }
         else
         { // Assume some slope 45, so diagonally down from tick,
           // and takes a bit less room.
- y_label_length_ = y_ticks_.label_max_chars_ * y_value_label_style_.font_size() * wh * sin45;
+ y_label_length_ = y_ticks_.label_max_width_ * sin45;
         }
 
         if (y_ticks_.major_value_labels_on_ != 0)
@@ -471,30 +478,30 @@
           { // Contract plot window right to left to make space for value labels on right.
            plot_right_ -= y_label_length_;
           }
- // else y_ticks_.ticks_on_plot_window_on_ == 0 // On vertical Y-axis line.
- // Ignore the unusual case of Y-axis line too close to the axis label?
- // In this case the value labels may overflow the plot window
- // and collide with the axis label!
- // User must change to put value label downward, or on other side of the axis line.
- // using major_value_labels_on(int d)
- // to set tick value labels to left (<0), none (==0) or right (>0).
           else
- { // no labels on plot window (may be on mid-plot Y-axis).
+ { // y_ticks_.ticks_on_plot_window_on_ == 0
+ // no labels on plot window (may be on mid-plot Y-axis line).
+ // Ignore the unusual case of Y-axis line too close to the axis label.
+ // In this case the value labels may overflow the plot window
+ // and collide with the axis label!
+ // User must change to put value label downward, or on other side of the axis line.
+ // using major_value_labels_on(int d)
+ // to set tick value labels to left (<0), none (==0) or right (>0).
           }
         } // y_ticks_. major_value_labels_on
 
         double x_label_length_ = 0; // Work out the longest value label for X-Axis.
         if (x_ticks_.label_rotation_ == horizontal)
         { // Only 1 char height & 1 space needed if labels are horizontal.
- x_label_length_ = 2 * x_value_label_style_.font_size() * wh; // SVG chars
+ x_label_length_ = 2 * x_value_label_style_.font_size() * wh; // 2 SVG chars
         }
         else if ((x_ticks_.label_rotation_ == upward) || (x_ticks_.label_rotation_ == downward))
         { // ! horizontal so will need more than 2 chars worth.
- x_label_length_+= x_ticks_.label_max_chars_ * x_value_label_style_.font_size() * wh; // SVG chars.
+ x_label_length_+= x_ticks_.label_max_width_ ; // SVG chars.
         }
         else
         { // Assume label is sloping, say 45, so * sin(45) = 0.707.
- x_label_length_+= x_ticks_.label_max_chars_ * x_value_label_style_.font_size() * wh * sin45; // SVG 'chars'.
+ x_label_length_+= x_ticks_.label_max_width_ * sin45; // SVG 'chars'.
         }
 
         if (x_ticks_.major_value_labels_on_ != 0)
@@ -511,6 +518,7 @@
           }
           else
           { // no labels on plot window (may be on mid-plot X-axis).
+ // See also notes above on case where labels can overwrite axis.
           }
         } // x_ticks_. major_value_labels_on
 
@@ -525,16 +533,16 @@
         }
 
         if (x_axis_.axis_line_on_)
- { // Want a X-axis line, so check if range includes zero, so axes intersect,
+ { // Want an X-axis line, so check if range includes zero, so axes intersect,
           // and x_axis_ is svg coordinate of Y-axis (usually y = 0).
- // If not fix axis to bottom of the plot window.
- if ((x_axis_position_ == bottom) // All definitely > zero.
+ // If not fix axis to bottom (or top) of the plot window.
+ if ((x_axis_position_ == bottom) // All Y values definitely > zero.
             && !(x_ticks_.ticks_on_plot_window_on_ < 0) ) // & not already at bottom.
           { // y_min_ > 0 so X-axis will not intersect Y-axis, so use plot window.
             plot_bottom_ -= x_label_length_; // Move up for the value labels.
             x_axis_.axis_ = plot_bottom_; // Put X-axis on bottom.
           }
- else if ((x_axis_position_ == top) // definitely < zero.
+ else if ((x_axis_position_ == top) // All Y values definitely < zero.
             && !(x_ticks_.ticks_on_plot_window_on_ > 0) ) // & not already at top.
           { // // y_max_ < 0 so X-axis will not intersect Y-axis, so use plot window.
              plot_top_ += x_label_length_; // Move down for labels.
@@ -549,14 +557,14 @@
         if (y_axis_.axis_line_on_)
         { // Want a Y-axis line, so check if range includes zero, so axes intersect,
           // and y_axis_ is svg coordinate of X-axis (usually x = 0).
- // If not fix axis to left of the plot window
- // and perhaps leave space (and quiggle between) to show this?
- if (y_axis_position_ == left) // all definitely > zero.
- { // Y-axis will not intersect X -axis, so put Y-axis line to left of plot window.
+ // If not fix axis to left (or right) of the plot window.
+// TODO more logic here as X???
+ if (y_axis_position_ == left) // All X values definitely > zero.
+ { // Y-axis will not intersect X -axis, so put Y-axis line on plot window.
             y_axis_.axis_ = plot_left_; // Y-axis to left,
             //plot_left_ += 2 * y_label_info_.font_size(); // with a space.
           }
- else if(y_axis_position_ == right)
+ else if(y_axis_position_ == right) // All X values definitely < zero.
           {
             y_axis_.axis_ = plot_right_; // Y-axis to right of plot window,
             //plot_right_ -= 2 * y_label_info_.font_size(); // with a space.
@@ -567,12 +575,23 @@
           }
         } // if (use_y_axis_line_)
 
- // TODO this can move up to after last change to plot_left ...???
+ if (plot_right_ <= plot_left_)
+ {
+ std::cout << "plot window left " << plot_left_ << ", right " << plot_right_ << std::endl;
+ throw std::runtime_error("Plot window right <= left!");
+ }
+
+ if (plot_top_ >= plot_bottom_)
+ {
+ std::cout << "plot window top " << plot_top_ << ", bottom " << plot_bottom_ << std::endl;
+ throw std::runtime_error("Plot window top >= bottom!");
+ }
+
         // Calculate scale and shift factors for transform from Cartesian to plot.
         // SVG image is 0, 0 at top left,y increase *downwards*
         // Cartesian 0, 0 at bottom left, y increasing upwards.
         x_scale_ = (plot_right_ - plot_left_) / (x_axis_.max_ - x_axis_.min_);
- x_shift_ = plot_left_ - x_axis_.min_ *(plot_right_ - plot_left_) / (x_axis_.max_ - x_axis_.min_);
+ x_shift_ = plot_left_ - x_axis_.min_ * (plot_right_ - plot_left_) / (x_axis_.max_ - x_axis_.min_);
         y_scale_ = -(plot_bottom_-plot_top_) / (y_axis_.max_-y_axis_.min_);
         y_shift_ = plot_top_ - (y_axis_.max_ * (plot_top_ - plot_bottom_) / (y_axis_.max_ - y_axis_.min_));
 
@@ -1270,7 +1289,7 @@
         return y_ticks_.value_precision_;
       }
 
- svg_2d_plot& y_value_ioflags(std::_Ios_Fmtflags flags)
+ svg_2d_plot& y_value_ioflags( std::ios_base::fmtflags flags)
       { // IO flags of Y tick label values (default 0X201).
         y_ticks_.value_ioflags_ = flags;
         return *this;

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_boxplot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_boxplot.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_boxplot.hpp 2008-01-23 06:57:20 EST (Wed, 23 Jan 2008)
@@ -46,19 +46,19 @@
 namespace svg
 {
 
-BOOST_PARAMETER_NAME((box_style, keyword) box);
-BOOST_PARAMETER_NAME((median_style, keyword) median);
-BOOST_PARAMETER_NAME((axis_style, keyword) axis);
-BOOST_PARAMETER_NAME((min_whisker_style, keyword) min_whisker);
-BOOST_PARAMETER_NAME((max_whisker_style, keyword) max_whisker);
-BOOST_PARAMETER_NAME((mild_outlier_style, keyword) mild_outlier);
-BOOST_PARAMETER_NAME((ext_outlier_style, keyword) ext_outlier);
-BOOST_PARAMETER_NAME((whisker_length, keyword) whisker);
-BOOST_PARAMETER_NAME((box_width, keyword) width);
-BOOST_PARAMETER_NAME((functor, keyword) fnctr);
-BOOST_PARAMETER_NAME((ctr, keyword) container);
-BOOST_PARAMETER_NAME((name, keyword) title);
-
+//BOOST_PARAMETER_NAME((box_style, keyword) box);
+//BOOST_PARAMETER_NAME((median_style, keyword) median);
+//BOOST_PARAMETER_NAME((axis_style, keyword) axis);
+//BOOST_PARAMETER_NAME((min_whisker_style, keyword) min_whisker);
+//BOOST_PARAMETER_NAME((max_whisker_style, keyword) max_whisker);
+//BOOST_PARAMETER_NAME((mild_outlier_style, keyword) mild_outlier);
+//BOOST_PARAMETER_NAME((ext_outlier_style, keyword) ext_outlier);
+//BOOST_PARAMETER_NAME((whisker_length, keyword) whisker);
+//BOOST_PARAMETER_NAME((box_width, keyword) width);
+//BOOST_PARAMETER_NAME((functor, keyword) fnctr);
+//BOOST_PARAMETER_NAME((ctr, keyword) container);
+//BOOST_PARAMETER_NAME((name, keyword) title);
+//
 struct svg_boxplot_series
 {
     double whisker_min;

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_style.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_style.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_style.hpp 2008-01-23 06:57:20 EST (Wed, 23 Jan 2008)
@@ -19,7 +19,7 @@
 #include "svg_color.hpp"
 #include "detail/svg_style_detail.hpp"
 
-#include <ostream>
+#include <iostream>
 // using std::ostream;
 #include <sstream>
 // using std::stringstream;
@@ -53,6 +53,8 @@
 
 const std::string strip_e0s(std::string s);
 // Ugly hack to remove unwanted sign and leading zero(s) in exponent.
+double string_svg_length(const std::string& s, const text_style& style);
+// Estimate length of string when appears as svg units.
 
 // -----------------------------------------------------------------
 // This is the style information for any <g> tag.
@@ -250,12 +252,12 @@
   { // text_style default constructor, defines defaults for all private members.
   }
 
- int font_size()
+ int font_size() const
   {
     return font_size_;
   }
 
- text_style& font_size(unsigned int i)
+ const text_style& font_size(unsigned int i)
   { // pixels, default 10.
     font_size_ = i;
     return *this;
@@ -266,7 +268,7 @@
     return font_family_;
   }
 
- text_style& font_family(const std::string& s)
+ const text_style& font_family(const std::string& s)
   { // Examples: "Arial", "Times New Roman", "Verdana", "Lucida Sans Unicode"
     font_family_ = s;
     return *this;
@@ -277,7 +279,7 @@
     return style_; // example "normal"
   }
 
- text_style& font_style(const std::string& s)
+ const text_style& font_style(const std::string& s)
   { // Examples: "italic"
     style_ = s;
     return *this;
@@ -288,7 +290,7 @@
     return weight_;
   }
 
- text_style& font_weight(const std::string& s)
+ const text_style& font_weight(const std::string& s)
   { // svg font-weight: normal | bold | bolder | lighter | 100 | 200 .. 900
     // Examples: "bold", "normal"
     weight_ = s;
@@ -300,7 +302,7 @@
     return stretch_;
   }
 
- text_style& font_stretch(const std::string& s)
+ const text_style& font_stretch(const std::string& s)
   { // Examples: "wider" but implementation?
     // font-stretch: normal | wider | narrower ...
     stretch_ = s;
@@ -312,7 +314,7 @@
     return decoration_;
   }
 
- text_style& font_decoration(const std::string& s)
+ const text_style& font_decoration(const std::string& s)
   { // Examples: "underline" | "overline" | "line-through"
     decoration_ = s; // But implementation doubtful.
     return *this;
@@ -376,6 +378,7 @@
 
 text_style no_style; // Uses all constructor defaults.
 
+
 enum point_shape
 { // Marking a data point.
   // Used in draw_plot_point in axis_plot_frame.hpp
@@ -738,20 +741,23 @@
     bool major_grid_on_; // Draw X grid at major ticks.
     bool minor_grid_on_;// Draw X grid at minor ticks.
     int value_precision_; // precision for tick value labels, usually 3 will suffice.
- std::_Ios_Fmtflags value_ioflags_; // IO formatting flags for the axis default std::ios::dec.
+ std::ios_base::fmtflags value_ioflags_; // IO formatting flags for the axis default std::ios::dec.
     bool strip_e0s_; // If redundant zero, + and e are to be stripped.
- size_t label_max_chars_; // width (in SVG units) of longest label on axis.
+ double label_max_width_; // width (in SVG units) of longest label on axis.
     int ticks_on_plot_window_on_; // Value labels & ticks on the plot window border
     // (rather than on X or Y-axis).
- // For X-axis -1 = left, 0 = false, +1 = right. Default left of plot window.
- // For Y-axis -1 = bottom, 0 = false, +1 = top. Default bottom of plot window.
+ // For X-axis -1 = left, 0 = false, +1 = right. Default -1 left of plot window.
+ // For Y-axis -1 = bottom, 0 = false, +1 = top. Default -1 bottom of plot window.
+ const text_style& value_label_style_;
 
     ticks_labels_style(dim d = X,
+ const text_style& style = no_style,
       double max = 10., double min = -10.,
       double major_interval = 2.,
       unsigned int num_minor_ticks = 4)
       : // Constructor.
       dim_(d),
+ value_label_style_(style),
       max_(max), min_(min),
       major_interval_(major_interval),
       num_minor_ticks_(num_minor_ticks),
@@ -787,7 +793,7 @@
     value_ioflags_(std::ios::dec), // IO formatting flags for the axis.
     // Note that ALL the flags are set, overwriting any defaults, so std::dec is wise.
     strip_e0s_(true), // strip superflous zeros and signs.
- label_max_chars_(0), // width (in SVG units) of longest label on axis.
+ label_max_width_(0.), // width (estimated in SVG units) of longest label on axis.
     ticks_on_plot_window_on_(-1) // Value labels & ticks on the plot window rather than on X or Y-axis.
     // Default -1 means left or bottom.
   {
@@ -800,8 +806,9 @@
         throw std::runtime_error("Axis ticks & labels range too small!" );
       }
   }
+
 
- size_t label_length(double value)
+ double label_length(double value)
   { // Find the length of label for a value.
     // Needs to know the IO precision & flags for the axis,
     // and if zeros are to be stripped, so can't be a free function.
@@ -809,20 +816,24 @@
     label.precision(value_precision_);
     label.flags(value_ioflags_);
     label << value; // "1.2" or "3.4e+000"...
+ double r;
     if (strip_e0s_)
     { // Do want to strip unecessary e, +, & leading exponent zeros.
       std::string stripped = strip_e0s(label.str());
- return stripped.size();
- }
- return label.str().size();
- } // int x_label_length
+ r = string_svg_length(stripped, value_label_style_);
+ // want x_or y_value_label_style_ here!
+ return r;
+ }
+ r = string_svg_length(label.str(), value_label_style_);
+ return r;
+ } // double label_length
 
- size_t longest_label()
- { // Update label_max_chars_ with the longest value label as pixels,
+ double longest_label()
+ { // Update label_max_width_ with the longest value label as pixels,
     // return the count of digits etc.
     if(major_value_labels_on_ != 0) // ! none
     { // Show values by the tick as "1.2" or "3.4e+000"...
- size_t longest = 0;
+ double longest = 0;
       
       //axis_line_style& axis = (dim_ = X) ? y_axis() : x_axis(); // The intersecting *other* axis.
       // || !axis.axis_line_on_ ignore these tests to avoid the above that doesn't work.
@@ -838,7 +849,7 @@
           // or avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
           // (won't be a Y-axis line for 1-D,
           // where both the zero tick & value label is always wanted).
- size_t l = label_length(v);
+ double l = label_length(v);
           if (l > longest)
           {
             longest = l;
@@ -852,19 +863,19 @@
         { // 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.
- size_t l = label_length(v);
+ double l = label_length(v);
           if (l > longest)
           {
             longest = l;
           }
         }
       } // for v
- label_max_chars_ = longest;
+ label_max_width_ = longest;
       return longest;
     }
     else
     {
- label_max_chars_ = 0;
+ label_max_width_ = 0;
       return 0;
     }
   } // longest_label()
@@ -931,6 +942,8 @@
     }
 }; // class box_style
 
+const std::string strip_e0s(std::string s);
+
 const std::string strip_e0s(std::string s)
 { // Ugly hack to remove unwanted sign and leading zero(s) in exponent.
   // Use to work out the longest value label before calculate_plot_window.
@@ -977,6 +990,48 @@
   return s; // Perhaps unchanged.
 } // const std::string strip(double d)
 
+ static const double wh = 0.7; // font text width/height ratio.
+ // Even after reading http://www.w3.org/TR/SVG/fonts.html, unclear how to
+ // determine the exact width of digits, so an
+ // arbitrary average width height ratio wh = 0.7 is used as a good approximation.
+
+double string_svg_length(const std::string& s, const text_style& style)
+{ // Return length of string in SVG units depending on font size etc.
+ // If possible use an actual length, else use average char width,
+ // and deal with Unicode, for example &#x3A9; = greek omega,
+ // counting each symbol(s) embedded between & amd ; as one character,
+ // and ignore embedded xml like <sub> (not implemented by browsers yet).
+
+ double d = 0.; // Estimated or actual width of resulting svg string.
+ bool in_esc = false;
+ for (std::string::const_iterator i = s.begin(); i != s.end(); i++)
+ {
+ if (*i == '&')
+ { // Start of Unicode 'escape sequence' &#x3A9;
+ in_esc = true;
+ while ((*i != ';')
+ && (i != s.end())) // In case mistakenly not terminated.
+ {
+ i++; // Only count &#x3A9; as 1 character wide.
+ }
+ in_esc = false;
+ }
+ if (*i == '<')
+ {
+ in_esc = true;
+ while ((*i != '>')
+ && (i != s.end())) // In case mistakenly not terminated.
+ {
+ i++; // Only count <...>; as NO character wide.
+ }
+ d--;
+ in_esc = false;
+ }
+ d++;
+ }
+ std::cout << "string " << s << " has " << d << " characters." << std::endl;
+ return d * style.font_size() * wh;
+} // double string_svg_length(
 
 
 }//svg

Modified: sandbox/SOC/2007/visualization/libs/svg_plot/example/demo_2d_plot.cpp
==============================================================================
--- sandbox/SOC/2007/visualization/libs/svg_plot/example/demo_2d_plot.cpp (original)
+++ sandbox/SOC/2007/visualization/libs/svg_plot/example/demo_2d_plot.cpp 2008-01-23 06:57:20 EST (Wed, 23 Jan 2008)
@@ -112,7 +112,8 @@
           .y_label_on(true)
           .y_major_labels_on(-1)
           .x_major_labels_on(-1)
- .legend_title("Function")
+ //.legend_title("Function")
+ .legend_title("Unicode &#x3A9;&#x3A6;")
           .legend_title_font_size(16);
 
   // Color settings chosen for visibility rather than taste!
@@ -195,6 +196,8 @@
 
 int main()
 {
+ try
+ {
   // boost::array or anything in boost such that pair_type has
   // std and boost as associated namespaces.
   typedef ::std::pair< ::boost::array<int, 1>, int> pair_type;
@@ -216,12 +219,19 @@
    // Demonstrate/test plots with various range of x and y, some *not* including zero.
 
    plot("Plot of Mathematical Functions", "./demo_2d_plot_XYPM.svg", "X-axis", -10., +10., "Y-axis", -10., +10.); // Both X & Y include zero.
- plot("Plot of Mathematical Functions", "./demo_2d_plot_XP.svg", "X-axis", +1., +10., "Y-axis", -10., 10.); // X all > 0
+ plot("Plot of Mathematical Functions", "./demo_2d_plot_XP.svg", "X-axis", +1., +10., "Y-axis", -10., 10.); // X all > 0
    plot("Plot of Mathematical Functions", "./demo_2d_plot_XN.svg", "X-axis", -10., -1., "Y-axis", -10., 10.); // x all < 0
    plot("Plot of Mathematical Functions", "./demo_2d_plot_YP.svg", "X-axis", -1., +10., "Y-axis", +1., +10.); // Y all > 0
    plot("Plot of Mathematical Functions", "./demo_2d_plot_YN.svg", "X-axis", -1., +10., "Y-axis", -10., -1.); // y all < 0
    plot("Plot of Mathematical Functions", "./demo_2d_plot_XYP.svg", "X-axis", +1., +10., "Y-axis", +1., +10.); // x & y all > 0
    plot("Plot of Mathematical Functions", "./demo_2d_plot_XYN.svg", "X-axis", -10., -1., "Y-axis", -10., -1.); // x & y all < 0
+ plot("Title with Unicode <sup>-&#945; </sup> &#x3A9; &#x3A6; &#x221A; &#x221E; &#x3B6; &#x00B1;", "./demo_2d_plot_XYPM.svg", "X-axis &#x00B1;&#x3A9;", -10., +10., "Y-axis &#x221E;&#x221A;", -10., +10.); // Both X & Y include zero.
+
+ }
+ catch (char* message)
+ {
+ cout << message << endl;
+ }
   return 0;
 } // int main()
 


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