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