|
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 Ω
+ // 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 Ω = 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' Ω
+ in_esc = true;
+ while ((*i != ';')
+ && (i != s.end())) // In case mistakenly not terminated.
+ {
+ i++; // Only count Ω 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 ΩΦ")
.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>-α </sup> Ω Φ √ ∞ ζ ±", "./demo_2d_plot_XYPM.svg", "X-axis ±Ω", -10., +10., "Y-axis ∞√", -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