|
Boost-Commit : |
From: pbristow_at_[hidden]
Date: 2008-01-13 10:12:11
Author: pbristow
Date: 2008-01-13 10:12:10 EST (Sun, 13 Jan 2008)
New Revision: 42719
URL: http://svn.boost.org/trac/boost/changeset/42719
Log:
Major update to nearly all modules to use new text_style and other classes, and remove Boost.Parameter.
Major renaming and accessor functions added.
Show-2d settings
2D ONLY Working somewhat but still major faults to fix.
and 1-D and boxplot to do.
Text files modified:
sandbox/SOC/2007/visualization/boost/svg_plot/detail/axis_plot_frame.hpp | 835 ++++++++++++------------
sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp | 394 +++++------
sandbox/SOC/2007/visualization/boost/svg_plot/stylesheet.hpp | 2
sandbox/SOC/2007/visualization/boost/svg_plot/svg.hpp | 104 +-
sandbox/SOC/2007/visualization/boost/svg_plot/svg_1d_plot.hpp | 173 ++--
sandbox/SOC/2007/visualization/boost/svg_plot/svg_2d_plot.hpp | 1329 ++++++++++++++++++---------------------
sandbox/SOC/2007/visualization/boost/svg_plot/svg_boxplot.hpp | 158 ++--
sandbox/SOC/2007/visualization/boost/svg_plot/svg_style.hpp | 933 ++++++++++++++++++++++-----
8 files changed, 2162 insertions(+), 1766 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-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -28,17 +28,17 @@
enum legend_places
{ // Placing of legend box, if requested by legend_on(true).
- inside = 0, // Default place for inside is top left of plot window,
+ 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_right = +1, // Default for outside.
- outside_top = +2,
- outside_bottom = -2
+ outside_left = 1, // Outside
+ outside_right = +2, // Default for outside.
+ outside_top = +3,
+ outside_bottom = +4
};
namespace detail
{
-
template <class Derived>
class axis_plot_frame
{
@@ -75,60 +75,10 @@
// void clear_points();
// void clear_plot_background();
// void clear_grids();
-
- const std::string strip(std::string s)
- { // Ugly hack to remove unwanted sign and leading zero in exponent.
- // TODO It alters the layout because space
- // is still allowed for the longest string.
- // Would need to work out the longest value label before calculate_plot_window.
- // But should be useful for values that spill over into exponent format
- // 'by accident' - when leading zeros are likely.
- using std::string;
- size_t j = s.find("e+000");
- if (j != string::npos)
- {
- s.erase(j, 5); // remove "e+000"
- goto ret;
- }
- j = s.find("e-000");
- if (j != string::npos)
- {
- s.erase(j, 5); // remove "e-000"
- goto ret;
- }
- j = s.find("e+00");
- if (j != string::npos)
- {
- s.erase(j + 1, 3); // remove "+00"
- goto ret;
- }
-
- j = s.find("e-00");
- if (j != string::npos)
- {
- s.erase(j+2, 2); // remove "00", leave "-"
- goto ret;
- }
- j = s.find("e+0");
- if (j != string::npos)
- {
- s.erase(j + 1, 2); // remove "+0"
- goto ret;
- }
- j = s.find("e-0");
- if (j != string::npos)
- {
- s.erase(j+2, 1); // remove "0", leave "-"
- goto ret;
- }
-ret:
- return s;
- } // const std::string strip(double d)
-
void transform_point(double& x, double& y)
{ // Scale & shift both x & y to graph coordinate.
- x = derived().x_scale * x + derived().x_shift;
- y = derived().y_scale * y + derived().y_shift;
+ x = derived().x_scale_ * x + derived().x_shift_;
+ y = derived().y_scale_ * y + derived().y_shift_;
adjust_limits(x, y); // In case either hits max, min, infinity or NaN.
}
// TODO do we need to adjust_limit(x); // In case hits max, min, infinity or NaN?
@@ -137,12 +87,12 @@
void transform_x(double & x)
{ // Scale and shift x only.
- x = derived().x_scale * x + derived().x_shift;
+ x = derived().x_scale_ * x + derived().x_shift_;
}
void transform_y(double & y)
{ // Scale and shift y only.
- y = derived().y_scale * y + derived().y_shift;
+ y = derived().y_scale_ * y + derived().y_shift_;
}
void draw_x_minor_ticks(double value, path_element& tick_path, path_element& grid_path)
@@ -154,72 +104,70 @@
double y2(derived().image.y_size());
// Draw the minor grid, if wanted.
- if(derived().use_x_minor_grid_)
+ if(derived().x_ticks_.minor_grid_on_)
{
- if(!derived().use_plot_window_)
- { // Use whole image.
+ if(!derived().plot_window_on_)
+ { // Use whole image.
// Make space for title and X-axis labels.
- if(derived().use_title)
+ if(derived().title_on_)
{ // Allow text_margin_ * font_size around text (pixels).
- y1 += derived().title_info.font_size() * derived().text_margin_;
+ y1 += derived().title_info_.style().font_size() * derived().text_margin_;
}
- if(derived().use_x_label)
+ if(derived().x_axis_.label_on_)
{
- y2 -= derived().x_label_info.font_size() * derived().text_margin_;
+ y2 -= derived().x_label_info_.style().font_size() * derived().text_margin_;
}
}
else
- { // use_plot_window_ == true.
- y1 = derived().plot_y1 + 1; // Top. Why +1 and -1?
- y2 = derived().plot_y2 - 1; // Bottom. Ensure *inside* window?
+ { // plot_window_on_ == true.
+ y1 = derived().plot_top_ + 1; // Top. Why +1 and -1?
+ y2 = derived().plot_bottom_ - 1; // Bottom. Ensure *inside* window?
}
// Make sure that we are drawing inside the allowed window.
- if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // allow = too?
+ if((x1 >= derived().plot_left_) && (x1 <= derived().plot_right_)) // allow = too?
{
//std::cerr << "Writing draw_x_minor_ticks grid inside plot window: x1 = "
- // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+ // << x1 << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
grid_path.M(x1, y1).L(x1, y2);
}
else
{ // This will happen but is designed to be ignored!
// TODO check this is best. See comment in draw_x_axis
//std::cerr << "Writing draw_x_minor_ticks grid OUTside plot window: x1 = "
- // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+ // << x1 << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
}
} // use_x_minor_grid
- double x_tick_length = derived().x_minor_tick_length_;
- if(derived().use_x_ticks_on_plot_window_)
+ double x_tick_length = derived().x_ticks_.minor_tick_length_;
+ if(derived().x_ticks_.ticks_on_plot_window_on_)
{ // Put minor ticks on the plot window border.
- y1 = derived().plot_y2; // on the window line.
- y2 = derived().plot_y2; // y1 = upper, y2 = lower end of tick.
- if(derived().use_up_ticks)
+ y1 = derived().plot_bottom_; // on the window line.
+ y2 = derived().plot_bottom_; // y1 = upper, y2 = lower end of tick.
+ if(derived().x_ticks_.up_ticks_on_)
{ //
y1 -= x_tick_length; // up.
}
- if (derived().use_down_ticks)
+ if (derived().x_ticks_.down_ticks_on_)
{
y2 += x_tick_length; // down.
}
}
else
{ // Internal style, draw tick up and/or down from the X-axis line.
- y1 = derived().x_axis; // X-axis horizontal line.
- y2 = derived().x_axis;
- if(derived().use_up_ticks)
+ y1 = derived().x_axis_.axis_; // X-axis horizontal line.
+ y2 = derived().x_axis_.axis_;
+ if(derived().x_ticks_.up_ticks_on_)
{
y1 -= x_tick_length; // up
}
- if (derived().use_down_ticks)
+ if (derived().x_ticks_.down_ticks_on_)
{
y2 += x_tick_length; // down.
}
}
// Make sure that we are drawing inside the allowed window.
- if((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // TODO allow < or <=
+ if((x1 >= derived().plot_left_) && (x1 <= derived().plot_right_)) // TODO allow < or <=
{
- //std::cerr << "Writing draw_x_minor_ticks inside plot window: x1 = "
- // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
tick_path.M(x1, y1).L(x1, y2);
// No value labels on minor ticks, at present.
}
@@ -227,110 +175,113 @@
{ // This will happen but is designed to be ignored!
// TODO check this is best. See comment in draw_x_axis
//std::cerr << "Writing draw_x_minor_ticks OUTside plot window: x1 = "
- // << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+ // << x1 << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
}
} // void draw_x_minor_ticks
void draw_x_major_ticks(double value, path_element& tick_path, path_element& grid_path)
{ // draw ticks - and grid too if wanted.
- // If use_x_major_labels then value may be shown beside the major tick.
- double x1(value); //
- transform_x(x1);
- double y1(0.); // // y1 = upper,
- double y2(derived().image.x_size()); // y2 = lower end of tick.
- if(derived().use_x_major_grid_)
+ // If major_value_labels_on then value shown beside the major tick.
+ double x(value); //
+ transform_x(x); // x value in svg.
+ double y_up(0.); // upper end of tick.
+ double y_down(derived().image.x_size()); // y_down = lower end of tick.
+ if(derived().x_ticks_.major_grid_on_)
{ // Draw major grid vertical line.
- if(!derived().use_plot_window_)
+ if(!derived().plot_window_on_)
{ // Allow a modest margin around text of title and X-axis labels, if in use.
- if(derived().use_title)
+ if(derived().title_on_)
{
- y1 += derived().title_info.font_size() * derived().text_margin_;
+ y_up += derived().title_info_.style().font_size() * derived().text_margin_;
}
- if(derived().use_x_label)
+ if(derived().x_ticks_.major_value_labels_on)
{ // If use_x_major_labels then value may be shown beside the major tick.
- y2 -= derived().x_label_info.font_size() * derived().text_margin_;
+ y_down -= derived().x_label_info_.style().font_size() * derived().text_margin_;
}
}
else
- { // use_plot_window_ == true
- y1 = derived().plot_y1; // Bottom of plot window.
- y2 = derived().plot_y2; // Top of plot window.
+ { // plot_window_on_ == true
+ y_up = derived().plot_top_; // Bottom of plot window.
+ y_down = derived().plot_bottom_; // Top of plot window.
+ }
+ if((y_down <= derived().plot_bottom_) && (y_up >= derived().plot_top_) && (x >= derived().plot_left_) && (x <= derived().plot_right_))
+ { // Make sure that we are drawing inside the allowed window.
+ grid_path.M(x, y_up).L(x, y_down); // Vertical grid line.
}
- grid_path.M(x1, y1).L(x1, y2); // Vertical grid line.
} // use_x_major_grid
// 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((x1 >= derived().plot_x1) && (x1 <= derived().plot_x2)) // now <=
+ if((x >= derived().plot_left_) && (x <= derived().plot_right_)) // now <=
{
- double x_tick_length = derived().x_major_tick_length_;
- if(derived().use_x_ticks_on_plot_window_)
+ double x_tick_length = derived().x_ticks_.major_tick_length_;
+ if(derived().x_ticks_.ticks_on_plot_window_on_)
{ // Put the ticks on the plot window border (was external).
- y1 = derived().plot_y2; // on the window line.
- y2 = derived().plot_y2; // y1 = upper, y2 = lower.
- if(derived().use_up_ticks)
+ y_up = derived().plot_bottom_; // on the window line.
+ y_down = derived().plot_bottom_; // y_up = upper, y_down = lower.
+ if(derived().x_ticks_.up_ticks_on_)
{
- y1 -= x_tick_length; // up
+ y_up -= x_tick_length; // up
}
- if (derived().use_down_ticks)
+ if (derived().x_ticks_.down_ticks_on_)
{
- y2 += x_tick_length; // down.
+ y_down += x_tick_length; // down.
}
}
else
{ // Internal_style, draw tick from the central X axis line.
- y1 = derived().x_axis; // X-axis line.
- y2 = derived().x_axis;
- if(derived().use_up_ticks)
+ y_up = derived().x_axis_.axis_; // X-axis line.
+ y_down = derived().x_axis_.axis_;
+ if(derived().x_ticks_.up_ticks_on_)
{
- y1 -= x_tick_length; // up
+ y_up -= x_tick_length; // up
}
- if (derived().use_down_ticks)
+ if (derived().x_ticks_.down_ticks_on_)
{
- y2 += x_tick_length; // down.
+ y_down += x_tick_length; // down.
}
}
- tick_path.M(x1, y1).L(x1, y2);
+ tick_path.M(x, y_up).L(x, y_down);
// Leaving current position at the bottom end of the tick.
- if(derived().use_x_major_labels)
+ if(derived().x_ticks_.major_value_labels_on)
{ // Show value by the tick as "1.2" or "3.4e+000"...
std::stringstream label;
- label.precision(derived().x_value_precision_);
- label.flags(derived().x_value_ioflags_);
+ label.precision(derived().x_ticks_.value_precision_);
+ label.flags(derived().x_ticks_.value_ioflags_);
label << value; // "1.2" or "3.4e+000"...
- if (derived().strip_e0s_)
+ if (derived().x_ticks_.strip_e0s_)
{ // remove unecessary e, +, leadings 0s
- std::string v = strip(label.str());
+ std::string v = strip_e0s(label.str());
label.str(v);
}
- double y = y2; // bottom end of the tick.
+ double y = y_down; // bottom end of the tick.
align_style alignment = center_align;
- if(derived().use_down_ticks)
- { // No need to shift if derived().use_up_ticks as labels are below the X-axis.
- // y += derived().x_label_value.font_size();
+ if(derived().x_ticks_.down_ticks_on_)
+ { // No need to shift if derived().up_ticks_on_ as labels are below the X-axis.
+ // y += derived().x_label_value_.font_size();
}
- if (derived().x_label_rotation_ == upward)
+ if (derived().x_ticks_.label_rotation_ == upward)
{ //
alignment = right_align;
- //y += label.str().size() * derived().x_label_info.font_size();
+ //y += label.str().size() * derived().x_label_info_.font_size();
// so the last digit will be by the tick.
}
- else if((derived().x_label_rotation_ == downward)
- || (derived().x_label_rotation_ == downhill))
+ else if((derived().x_ticks_.label_rotation_ == downward)
+ || (derived().x_ticks_.label_rotation_ == downhill))
{ // start from tick and write down.
- y += derived().x_label_value.font_size() * 0.5;
+ y += derived().x_label_value_.style().font_size() * 0.5;
alignment = left_align;
}
- else if(derived().x_label_rotation_ == horizontal)
+ else if(derived().x_ticks_.label_rotation_ == horizontal)
{
- y += derived().x_label_value.font_size() * 1.5;
+ y += derived().x_label_value_.style().font_size() * 1.5;
alignment = center_align; // center on the tick.
}
- else if(derived().x_label_rotation_ == uphill)
+ else if(derived().x_ticks_.label_rotation_ == uphill)
{ // 45 slope up,
alignment = left_align; // Uphill to end at tick.
- y += label.str().size() * derived().x_label_info.font_size() * 0.7;
+ y += label.str().size() * derived().x_label_info_.style().font_size() * 0.7;
// sloping up so need about sin(45) = 0.707 less space,
// so the last digit is by the tick.
}
@@ -341,14 +292,14 @@
}
{ // ! use_x_ticks_on_plot_window_ = Internal - value labels just below horizontal X-axis.
- if (derived().use_x_ticks_on_plot_window_ || ((value != 0) && derived().use_x_axis_lines_))
+ if (derived().x_ticks_.ticks_on_plot_window_on_ || ((value != 0) && derived().x_axis_.axis_line_on_))
{ // Avoid a "0" below the X-axis if it would be cut through by any internal vertical Y-axis line.
derived().image.get_g_element(detail::PLOT_VALUE_LABELS).text(
- x1, y,
+ x, y,
label.str(),
- derived().x_label_value.font_size(), derived().x_label_value.font_family(),
- "", "", "", "", alignment, // center label on the tick.
- derived().x_label_rotation_);
+ derived().x_label_value_.style(),
+ alignment, // center label on the tick.
+ derived().x_ticks_.label_rotation_);
}
}
} // use_x_major_labels
@@ -356,23 +307,23 @@
else
{ // Outside plot window - so do nothing? Warning?
//std::cerr << "Writing draw_x_major_ticks OUTside plot window: "
- // "x1 = " << x1 << ", plot_x1 = " << derived().plot_x1 << ", plot_x2 = " << derived().plot_x2 << std::endl;
+ // "x = " << x << ", plot_left_ = " << derived().plot_left_ << ", plot_right_ = " << derived().plot_right_ << std::endl;
}
} // draw_x_major_ticks
void draw_x_axis()
- {
- if(derived().use_x_axis_lines_)
+ { // Draw horizontal X-axis line &.
+ if(derived().x_axis_.axis_line_on_)
{ // Draw the horizontal X-axis line the full width of the plot window,
// perhaps including an addition in lieu of a major tick.
- double xleft = derived().plot_x1;
- double xright = derived().plot_x2;
- if (derived().use_left_ticks && derived().use_x_ticks_on_plot_window_
+ double xleft = derived().plot_left_;
+ double xright = derived().plot_right_;
+ if (derived().y_ticks_.left_ticks_on_ && derived().x_ticks_.ticks_on_plot_window_on_
&& (derived().y_axis_position_ == y_intersect))
{ // Extend the horizontal line left in lieu of longest tick.
- xleft -= (std::max)(derived().y_minor_tick_length_, derived().y_major_tick_length_);
+ xleft -= (std::max)(derived().y_ticks_.minor_tick_length_, derived().y_ticks_.major_tick_length_);
}
- double y = derived().x_axis; // y = 0, (provided y range includes zero).
+ double y = derived().x_axis_.axis_; // y = 0, (provided y range includes zero).
derived().image.get_g_element(PLOT_X_AXIS).line(
xleft, y,
xright, y);
@@ -385,14 +336,14 @@
path_element& major_grid_path = derived().image.get_g_element(PLOT_X_MAJOR_GRID).path();
// x_minor_jump is the interval between minor ticks.
- double x_minor_jump = derived().x_major_interval_ /
- (derived().x_num_minor_ticks_ + 1.);
+ double x_minor_jump = derived().x_ticks_.major_interval_ /
+ (derived().x_ticks_.num_minor_ticks_ + 1.);
// Draw the ticks on the positive side (right of zero).
- for(double x = 0.; x <= derived().x_max; x += derived().x_major_interval_)
+ for(double x = 0.; x <= derived().x_axis_.max_; x += derived().x_ticks_.major_interval_)
{
for(double j = x + x_minor_jump;
- j < (x + derived().x_major_interval_) * (1. - 2 * std::numeric_limits<double>::epsilon());
+ 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
// that intermittently puts minor ticks *at same value as* major ticks.
@@ -404,7 +355,7 @@
// TODO this seems ugly - as does the negative ones below.
draw_x_minor_ticks(j, minor_tick_path, minor_grid_path);
} // for j
- if ((x != 0. || !derived().use_y_axis_lines_) || derived().use_x_ticks_on_plot_window_)
+ if ((x != 0. || !derived().y_axis_.axis_line_on_) || derived().x_ticks_.ticks_on_plot_window_on_)
{ // 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);
@@ -412,24 +363,24 @@
}
// Draw the ticks on the negative side (left of zero).
- for(double x = 0.; x >= derived().x_min; x -= derived().x_major_interval_)
+ for(double x = 0.; x >= derived().x_axis_.min_; x -= derived().x_ticks_.major_interval_)
{
// Draw minor ticks.
for(double j = x - x_minor_jump;
- j > (x - derived().x_major_interval_ + x_minor_jump) * (1. + 2 * std::numeric_limits<double>::epsilon());
+ 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
// that intermittently puts minor ticks *at same value as* major ticks.
j -= x_minor_jump)
{
- if ((j != 0. || !derived().use_y_axis_lines_) || derived().use_x_ticks_on_plot_window_)
+ if ((j != 0. || !derived().y_axis_.axis_line_on_) || derived().x_ticks_.ticks_on_plot_window_on_)
{ // 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);
}
}
- if ((x != 0. || !derived().use_y_axis_lines_) || derived().use_x_ticks_on_plot_window_)
+ if ((x != 0. || !derived().y_axis_.axis_line_on_) || derived().x_ticks_.ticks_on_plot_window_on_)
{ // 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.
@@ -444,28 +395,19 @@
void draw_title()
{
- // Update title_info with position.
- derived().title_info.x(derived().image.x_size() / 2.); // Center of image.
+ // Update title_info_ with position.
+ derived().title_info_.x(derived().image.x_size() / 2.); // Center of image.
// Assumes align = center_align.
double y;
- if (derived().use_plot_window_)
- {
- y = derived().plot_y1; // plot_y1 IS now assigned in calculate_plot_window
- // y is distance from top of image to top of plot window.
- y /= derived().text_margin_; // Center the title in the space between.
- }
- else
- { // Using all image.
- y = derived().title_info.font_size() * derived().text_margin_; // Leave a linespace above.
- }
- derived().title_info.y(y);
- derived().image.get_g_element(PLOT_TITLE).push_back(new text_element(derived().title_info));
+ y = derived().title_info_.style().font_size() * derived().text_margin_; // Leave a linespace above.
+ derived().title_info_.y(y);
+ derived().image.get_g_element(PLOT_TITLE).push_back(new text_element(derived().title_info_));
} // void draw_title()
void size_legend_box()
{ // Calculate how big the legend box needs to be.
// Store in legend_width_ and legend_height_
- if(derived().use_legend == false)
+ if(derived().legend_on_ == false)
{ // No legend, so set values to show legend position invalid.
derived().legend_left_ = -1;
derived().legend_right_ = -1;
@@ -476,12 +418,12 @@
return;
}
else
- { // use_legend == true
+ { // legend_on_ == true
// Work out the size the legend box needs to be to hold the
// header, markers & text.
size_t num_series = derived().series.size(); // How many data series.
- int font_size = derived().legend_header_.font_size();
- int point_size = derived().series[0].point_style.size();
+ int font_size = derived().legend_header_.style().font_size();
+ int point_size = derived().series[0].point_style_.size();
// Use height of whichever is the biggest of point marker and font.
double spacing = (std::max)(font_size, point_size);
// std::cout << spacing << ' ' << font_size << ' ' << point_size << std::endl;
@@ -491,7 +433,7 @@
// 0 if no header.
for(unsigned int i = 0; i < num_series; ++i)
{ // Find the longest text in all the data series.
- std::string s = derived().series[i].title;
+ std::string s = derived().series[i].title_;
size_t siz = s.size();
if (siz > longest)
{
@@ -499,20 +441,17 @@
}
} // for
std::cout.flags(std::ios_base::dec);
- std::cout << "\nLongest legend header or data descriptor " << longest << " chars" << std::endl; // TODO remove.
-
- const double wh = 0.7; // TODO share a common value?
- // font_size is not exact because width varies but use 0.7.
- derived().legend_width_ = (0 + longest) * wh * font_size;
- // Allow for a leading space, longest
+ // std::cout << "\nLongest legend header or data descriptor " << longest << " chars" << std::endl;
+ derived().legend_width_ = (1 + longest) * wh * font_size;
+ // Allow for a leading space, longest text
// & trailing space before box margin.
- if (derived().use_line)
- { // colored line marker.
+ if (derived().legend_lines_)
+ { // colored line marker in legend.
derived().legend_width_ += spacing * 2.;
}
- if(derived().series[0].point_style.shape() != none)
+ if(derived().series[0].point_style_.shape() != none)
{ // colored data point marker, cross, round... & space
- derived().legend_width_ += 2 * derived().series[0].point_style.size();
+ derived().legend_width_ += 2 * derived().series[0].point_style_.size();
}
// else no point marker.
@@ -526,29 +465,31 @@
derived().legend_height_ += 2 * font_size; // text & space after.
}
derived().legend_height_ += num_series * spacing * 2; // Space for the data point symbols & text.
- } // use_legend == true
+ } // legend_on_ == true
- std::cout << "Legend width " << derived().legend_width_
- << ", height " << derived().legend_height_ << std::endl;
+ std::cout << "Legend width " << derived().legend_width_ << ", height " << derived().legend_height_ << std::endl;
} // void size_legend_box()
void place_legend_box()
{
- if(derived().use_legend) // Legend box required.
+ if(derived().legend_on_) // Legend box required.
{
- derived().use_outside_legend_ = true; // Unless proves to be inside.
+ derived().outside_legend_on_ = true; // Unless proves to be inside.
+ double spacing = derived().y_label_font_size() * 1.; // Around any legend box - beyond any border.
switch (derived().legend_place_)
{
+ case nowhere:
+ return;
case inside:
- derived().use_outside_legend_ = false;
+ derived().outside_legend_on_ = false;
if (derived().legend_left_ == -1)
{ // Legend box position NOT been set by legend_top_left.
// Default inside position is top left of plot window.
- derived().legend_left_ = derived().plot_x1;
- derived().legend_right_ = derived().plot_x1 + derived().legend_width_;
- derived().plot_x1 = derived().legend_right_;
- derived().legend_top_ = derived().plot_y1; // Level with top of plot window.
- if (derived().use_title)
+ derived().legend_left_ = derived().plot_left_;
+ derived().legend_right_ = derived().plot_left_ + derived().legend_width_;
+ derived().plot_left_ = derived().legend_right_;
+ derived().legend_top_ = derived().plot_top_; // Level with top of plot window.
+ if (derived().title_on_)
{
derived().legend_top_ += derived().title_font_size() * 2.; // below title.
}
@@ -561,21 +502,43 @@
break;
// If outside then reserve space for legend by reducing plot window.
case outside_right:
- derived().legend_right_ = derived().plot_x2; // right image edge less border.
- derived().legend_right_ -= derived().y_label_font_size() * 2.; // space from right edge.
+ // so that it isn't too close to the image edge or the plot window.
+ derived().legend_right_ = derived().plot_right_; // right image edge less border.
+ derived().legend_right_ -= spacing; // space from right edge.
derived().legend_left_ = derived().legend_right_ - derived().legend_width_;
- derived().plot_x2 = derived().legend_left_; // Narrow plot window from left.
- derived().plot_x2 -= derived().y_label_font_size() * 2.; // space.
- derived().legend_top_ = derived().plot_y1; // Level with top of plot window.
- derived().legend_top_ += derived().y_label_font_size() * 2.; // TODO ???
+ derived().plot_right_ = derived().legend_left_; // Narrow plot window from left.
+ derived().plot_right_ -= spacing;
+ derived().legend_top_ = derived().plot_top_; // Level with top of plot window.
+ derived().legend_top_ += spacing;
derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
break;
case outside_left:
- // TODO implement.
+ derived().legend_left_ = derived().plot_left_;
+ derived().legend_left_ += derived().y_label_font_size() * spacing;
+ derived().plot_left_ += derived().legend_width_; // Contract plot window right to make room,
+ derived().plot_left_ += spacing;
+ 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;
+ derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
break;
case outside_top:
- break;
- case outside_bottom:
+ // centered.
+ derived().legend_left_ = derived().image.x_size() / 2. - derived().legend_width_ / 2;
+ derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+ derived().plot_top_ += derived().legend_height_ + spacing ;
+ derived().legend_top_ = derived().title_info_.y() + derived().title_font_size() * derived().text_margin_;
+ derived().legend_top_ += spacing;
+ derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
+ break;
+ case outside_bottom:
+ // centered.
+ derived().legend_left_ = derived().image.x_size()/ 2. - derived().legend_width_ / 2;
+ derived().legend_right_ = derived().legend_left_ + derived().legend_width_;
+ derived().plot_bottom_ -= derived().legend_height_;
+ derived().plot_bottom_ -= spacing;
+ derived().legend_top_ = derived().plot_bottom_;
+ derived().legend_bottom_ = derived().legend_top_ + derived().legend_height_;
break;
} // switch
@@ -612,32 +575,21 @@
g_element* g_ptr = &(derived().image.get_g_element(PLOT_LEGEND_BACKGROUND));
g_ptr->push_back(new
rect_element(derived().legend_left_, derived().legend_top_, derived().legend_width_, derived().legend_height_));
- } // if use_legend
+ } // if legend_on_
} // void calculate_legend_box()
void draw_legend()
{
// size_t num_points = derived().series.size();
- int font_size = derived().legend_header_.font_size();
- int point_size = derived().series[0].point_style.size();
+ int font_size = derived().legend_header_.style().font_size();
+ int point_size = derived().series[0].point_style_.size();
// Use whichever is the biggest of point marker and font.
double spacing = (std::max)(font_size, point_size);
// std::cerr << spacing << ' ' << font_size << ' ' << point_size << endl;
bool is_header = (derived().legend_header_.text() != "");
- // TODO use saved version.
- size_t longest = 0;
- for(unsigned int i = 0; i < derived().series.size(); ++i)
- { // Find the longest text in all the data series.
- std::string s = derived().series[i].title;
- size_t siz = s.size();
- if (siz > longest)
- {
- longest = siz;
- }
- }
- // Assume legend box position has already been sized by calculate_legend_box.
+ // 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_;
@@ -665,44 +617,42 @@
for(unsigned int i = 0; i < derived().series.size(); ++i)
{ // Show point marker, text info and perhaps line for all the data series.
double legend_x_pos = legend_x_start;
+ legend_x_pos += spacing; // space before point marker.
g_inner_ptr = &(g_ptr->add_g_element());
// Use both stroke colors from the point's style.
- g_inner_ptr->style()
- .stroke_color(derived().series[i].point_style.stroke_color_);
- g_inner_ptr->style().stroke_width(2); // TODO create a global for this
+ g_inner_ptr->style().stroke_color(derived().series[i].point_style_.stroke_color_);
+ g_inner_ptr->style().stroke_width(2);
- if(derived().series[i].point_style.shape() != none)
+ if(derived().series[i].point_style_.shape() != none)
{
draw_plot_point( // Plot point like circle, square...
- legend_x_start + spacing / 2, // space before point marker.
+ legend_x_pos,
legend_y_pos,
*g_inner_ptr,
- derived().series[i].point_style);
+ derived().series[i].point_style_);
legend_x_pos += 1.0 * spacing;
}
// Line markers - only really applicable to 2-D sets plot_line_style,
- if (derived().use_line)
+ if (derived().legend_lines_)
{ // Need to draw a short line to show color for that data series.
g_inner_ptr->style() // Use fill & stroke colors from line style.
- .stroke_color(derived().series[i].line_style.color);
+ .stroke_color(derived().series[i].line_style_.color_);
g_inner_ptr->push_back(new line_element(
legend_x_pos + spacing /2., // half space leading space
legend_y_pos,
legend_x_pos + spacing * 2., // line sample is two char long.
legend_y_pos));
legend_x_pos += 2.5 * spacing; // short line & half space.
- } // use_line
+ } // legend_lines_
// Legend text for each Data Series added to the plot.
g_inner_ptr = &(derived().image.get_g_element(PLOT_LEGEND_TEXT));
g_inner_ptr->push_back(new text_element(
legend_x_pos, // allow space for the marker.
legend_y_pos,
- derived().series[i].title, // Text for this data series.
- derived().legend_header_.font_size(), // font size &
- derived().legend_header_.font_family(), // font family.
- "", "", "", "",
+ derived().series[i].title_, // Text for this data series.
+ derived().legend_header_.style(),
left_align));
legend_y_pos += 2 * spacing;
} // for
@@ -712,25 +662,30 @@
{
// color is set in constructor.
//image.get_g_element(detail::PLOT_X_LABEL).style().stroke_color(black);
- // and using y_label_color(color)
+ // and using x_label_color(color)
- std::string label = derived().x_label_info.text(); // x_axis label, and optional units.
- if (derived().use_x_label_units && (derived().x_units_info.text() != ""))
- { // Append the units, if any, providing brackets ().
- label += " (" + derived().x_units_info.text() + ")";
+ 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.
+ label += derived().x_units_info_.text();
}
// Simplest to start from the bottom of the image.
// and move up to give enough space for the X-axis label.
double y = derived().image.y_size(); // bottom edge of image.
- y -= derived().x_label_font_size(); // Up enough for a space underneath label.
+ if (derived().image_border_.border_on_)
+ {
+ y -= derived().image_border_.width_; // Allow space for border.
+ y -= derived().image_border_.margin_; // Allow a margin.
+ y -= derived().x_axis_label_style_.font_size() / 2; // Allow a half font too.
+ }
derived().image.get_g_element(PLOT_X_LABEL).push_back(new text_element(
( // x position relative to the x-axis which is middle of plot window.
- derived().plot_x2 + derived().plot_x1) / 2, // x coordinate - middle.
+ derived().plot_right_ + derived().plot_left_) / 2, // x coordinate - middle.
y, // Up from image bottom edge.
label,
- derived().x_label_font_size(),
- derived().x_label_font_family(), "", "", "", "", center_align, horizontal)
+ derived().x_label_info_.style(),
+ center_align, horizontal)
);
} // void draw_x_label()
@@ -741,37 +696,37 @@
// use the appropriate plot min or max.
if(detail::limit_max(x))
{
- x = derived().plot_x2;
+ x = derived().plot_right_;
}
if(detail::limit_max(y))
{
- y = derived().plot_y1;
+ y = derived().plot_top_;
}
if(detail::limit_min(x))
{
- x = derived().plot_x1;
+ x = derived().plot_left_;
}
if(detail::limit_min(y))
{
- y = derived().plot_y1;
+ y = derived().plot_top_;
}
// If value is NaN, use zero instead.
// TODO Do we want/get a different color or shape for NaNs??
if(detail::limit_NaN(x))
{
- x = 0;
+ x = 0.;
transform_x(x);
}
if(detail::limit_NaN(y))
{
- y = 0;
+ y = 0.;
transform_y(y);
}
} // void adjust_limits
void draw_plot_point(double x, double y,
g_element& g_ptr,
- const plot_point_style& sty)
+ plot_point_style& sty)
{
int size = sty.size_;
double half_size = size / 2.;
@@ -822,7 +777,7 @@
break;
case symbol:
- g_ptr.text(x, y + half_size, sty.symbols_, size, "Lucida Sans Unicode"); // symbol(s), size and centre.
+ g_ptr.text(x, y + half_size, sty.symbols(), sty.style(), center_align, horizontal); // symbol(s), size and centre.
// TODO Need to provide way to set style.symbols when Boost.Parameter is unravelled.
// Unicode symbols that work on most browsers are listed at
@@ -835,32 +790,32 @@
break;
case diamond:
- g_ptr.text(x, y, "♦", size, "Lucida Sans Unicode");
+ g_ptr.text(x, y, "♦", sty.symbols_style_, center_align, horizontal);
// size / 4. puts bottom tip on the X-axis,
// size / 2. put center above the X-axis
// x, y, put on the X-axis - probably what is needed for 2-D plots.
// diamond, spades, clubs & hearts fill with expected fill_color.
break;
case asterisk:
- g_ptr.text(x, y - size / 3., "∗", size, "Lucida Sans Unicode");
+ g_ptr.text(x, y - size / 3., "∗", sty.symbols_style_, center_align, horizontal);
// asterisk is black filled.
// size /3 puts the bottom tip on the X-axis.
break;
case lozenge:
- g_ptr.text(x, y - size / 3., "◊", size, "Lucida Sans Unicode");
+ g_ptr.text(x, y - size / 3., "◊", sty.symbols_style_, center_align, horizontal);
// size / 3 to get tip of lozenge just on the X-axis.
// lozenge seems not to fill?
break;
case club:
- g_ptr.text(x, y, "♣", size, "Lucida Sans Unicode");
+ g_ptr.text(x, y, "♣", sty.symbols_style_, center_align, horizontal);
// x, y, puts club just on the X-axis
break;
case spade:
- g_ptr.text(x, y, "♠", size, "Lucida Sans Unicode");
+ g_ptr.text(x, y, "♠", sty.symbols_style_, center_align, horizontal);
//
break;
case heart:
- g_ptr.text(x, y , "♥", size, "Lucida Sans Unicode");
+ g_ptr.text(x, y , "♥", sty.symbols_style_, center_align, horizontal);
//
break;
case cone: // Pointing down triangle.
@@ -951,8 +906,8 @@
private:
Derived& derived()
{
- return static_cast<Derived&>(*this); // Why is cast required?
- // error C2440: 'return' : cannot convert from 'boost::svg::detail::axis_plot_frame<Derived>' to 'boost::svg::svg_1d_plot &'
+ return static_cast<Derived&>(*this);
+ //http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
}
const Derived& derived()const
{
@@ -1213,7 +1168,7 @@
return derived();
}
- const bool license_on()
+ bool license_on()
{
return derived().image.is_license();
}
@@ -1251,117 +1206,117 @@
Derived& x_value_precision(int digits)
{ // Precision of X tick label values in decimal digits (default 3).
- derived().x_value_precision_ = digits;
+ derived().x_ticks_.value_precision_ = digits;
return derived();
}
int x_value_precision()
{ //
- return derived().x_value_precision_;
+ return derived().x_ticks_.value_precision_;
}
const std::string title()
{
- return derived().title_info.text();
+ return derived().title_info_.text();
}
Derived& title_font_size(unsigned int i)
{
- derived().title_info.font_size(i);
+ derived().title_info_.style().font_size(i);
return derived();
}
unsigned int title_font_size()
{
- return derived().title_info.font_size();
+ return derived().title_info_.style().font_size();
}
Derived& title_font_family(const std::string& family)
{
- derived().title_info.font_family(family);
+ derived().title_info_.style().font_family(family);
return derived();
}
const std::string& title_font_family()
{
- return derived().title_info.font_family();
+ return derived().title_info_.style().font_family();
}
Derived& title_font_style(const std::string& style)
{
- derived().title_info.font_style(style);
+ derived().title_info_.style().font_style(style);
return derived();
}
const std::string& title_font_style()
{
- return derived().title_info.font_style();
+ return derived().title_info_.style().font_style();
}
Derived& title_font_weight(const std::string& weight)
{
- derived().title_info.font_weight(weight);
+ derived().title_info_.style().font_weight(weight);
return derived();
}
const std::string& title_font_weight()
{
- return derived().title_info.font_weight();
+ return derived().title_info_.style().font_weight();
}
Derived& legend_font_weight(const std::string& weight)
{
- derived().legend_header_.font_weight(weight);
+ derived().legend_header_.style().font_weight(weight);
return derived();
}
const std::string& legend_font_weight()
{
- return derived().legend_header_.font_weight();
+ return derived().legend_header_.style().font_weight();
}
Derived& title_font_stretch(const std::string& stretch)
{
- derived().title_info.font_stretch(stretch);
+ derived().title_info_.style().font_stretch(stretch);
return derived();
}
const std::string& title_font_stretch()
{
- return derived().title_info.font_stretch();
+ return derived().title_info_.style().font_stretch();
}
Derived& title_font_decoration(const std::string& decoration)
{
- derived().title_info.font_decoration(decoration);
+ derived().title_info_.style().font_decoration(decoration);
return derived();
}
const std::string& title_font_decoration()
{
- return derived().title_info.font_decoration();
+ return derived().title_info_.style().font_decoration();
}
- Derived& title_font_rotation(int rotate)
+ Derived& title_font_rotation(rotate_style rotate)
{ // Degrees (0 to 360).
- derived().title_info.font_rotation(rotate);
+ derived().title_info_.rotation(rotate);
return derived();
}
int title_font_rotation()
{
- return derived().title_info.font_rotation();
+ return derived().title_info_.rotation();
}
Derived& title_font_alignment(align_style alignment)
{
- derived().title_info.font_alignment(alignment);
+ derived().title_info_.font_alignment(alignment);
return derived();
}
align_style title_font_alignment()
{
- return derived().title_info.font_alignment();
+ return derived().title_info_.alignment();
}
Derived& legend_width(double width)
@@ -1388,24 +1343,24 @@
Derived& legend_font_family(const std::string& family)
{
- derived().legend_header_.font_family(family);
+ derived().legend_header_.style().font_family(family);
return derived();
}
const std::string& legend_font_family()
{
- return derived().legend_header_.font_family();
+ return derived().legend_header_.style().font_family();
}
Derived& legend_title_font_size(unsigned int size)
{
- derived().legend_header_.font_size(size);
+ derived().legend_header_.style().font_size(size);
return derived();
}
unsigned int legend_title_font_size()
{
- return derived().legend_header_.font_size();
+ return derived().legend_header_.style().font_size();
}
Derived& legend_top_left(double x, double y)
@@ -1436,20 +1391,20 @@
return r;
}
- Derived& line_on(bool is)
+ Derived& legend_lines(bool is)
{
- derived().use_line = is;
+ derived().legend_lines_ = is;
return derived();
}
- bool line_on()
+ bool legend_lines()
{
- return derived().use_line;
+ return derived().legend_lines_;
}
Derived& legend_on(bool cmd)
{
- derived().use_legend = cmd;
+ derived().legend_on_ = cmd;
if(cmd)
{
derived().image.get_g_element(detail::PLOT_LEGEND_BACKGROUND)
@@ -1461,7 +1416,7 @@
bool legend_on()
{
- return derived().use_legend;
+ return derived().legend_on_;
}
Derived& legend_place(legend_places l)
@@ -1477,30 +1432,30 @@
bool legend_outside()
{
- return derived().use_outside_legend_;
+ return derived().outside_legend_on_;
}
Derived& plot_window_on(bool cmd)
{
- derived().use_plot_window_ = cmd;
+ derived().plot_window_on_ = cmd;
if(cmd)
- { // set plot window color and border color.
- // TODO - allow user to change these.
- derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND)
- .style().fill_color(white)
- .stroke_color(black);
+ { // Set plot window
+ derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style()
+ .fill_color(derived().plot_window_border_.fill_) // background color and
+ .stroke_color(derived().plot_window_border_.stroke_); // border color.
}
- derived().legend_place_ = outside_right;
+ //derived().legend_place_ = outside_right;
return derived();
}
bool plot_window_on()
{
- return derived().use_plot_window_;
+ return derived().plot_window_on_;
}
Derived& plot_border_color(const svg_color& col)
{
+ derived().plot_window_border_.stroke_ = col;
derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_color(col);
return derived();
}
@@ -1517,178 +1472,188 @@
Derived& plot_border_width(double w)
{
+ derived().plot_window_border_.width_ = w;
derived().image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).style().stroke_width(w);
return derived();
}
- Derived& border_margin(double w)
+ Derived& image_border_margin(double w)
{
- derived().border_margin_ = w;
+ derived().image_border_.margin_ = w;
return derived();
}
- double border_margin()
+ double image_border_margin()
{
- return derived().border_margin_;
+ return derived().image_border_.margin_;
}
- Derived& border_width(double w)
+ Derived& image_border_width(double w)
{
- derived().border_width_ = w;
+ derived().image_border_.width_ = w;
return derived();
}
- double border_width()
+ double image_border_width()
{
- return derived().border_width_;
+ return derived().image_border_.width_;
}
Derived& plot_window_x(double min_x, double max_x)
{ // This is normally calculated from other plot values.
if(max_x <= min_x)
{
- throw std::runtime_error("plot_window_x: X range: x_max < x_min");
+ throw std::runtime_error("plot_window X: x_max_ <= x_min_");
}
- derived().plot_x1 = min_x;
- derived().plot_x2 = max_x;
+ if((max_x - min_x) < std::numeric_limits<double>::epsilon() * 1000)
+ { // Range too small to display.
+ throw std::runtime_error("plot_window X range too small!" );
+ }
+ derived().plot_left_ = min_x;
+ derived().plot_right_ = max_x;
return derived();
}
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_");
+ }
if(max_y <= min_y)
{
- throw std::runtime_error("plot_window_y : Y range: y_max < y_min");
+ throw std::runtime_error("plot_window Y range too small!");
}
- derived().plot_y1 = min_y;
- derived().plot_y2 = max_y;
+ derived().plot_top_ = min_y;
+ derived().plot_bottom_ = max_y;
return derived();
}
std::pair<double, double> plot_window_x()
{
std::pair<double, double> r;
- r.first = derived().plot_x1;
- r.second = derived().plot_x2;
+ r.first = derived().plot_left_;
+ r.second = derived().plot_right_;
return r;
}
double plot_window_x_left()
{
- return derived().plot_x1;
+ return derived().plot_left_;
}
double plot_window_x_right()
{
- return derived().plot_x2;
+ return derived().plot_right_;
}
double plot_window_y_top()
{
- return derived().plot_y1;
+ return derived().plot_top_;
}
double plot_window_y_bottom()
{
- return derived().plot_y2;
+ return derived().plot_bottom_;
}
std::pair<double, double> plot_window_y()
{
std::pair<double, double> r;
- r.first = derived().plot_y1;
- r.second = derived().plot_y2;
+ r.first = derived().plot_top_;
+ r.second = derived().plot_bottom_;
return r;
}
double x_minor_interval()
{
- return derived().x_minor_interval_; // interval
+ return derived().x_ticks_.minor_interval_; // interval
}
double y_minor_interval()
{
- return derived().y_minor_interval_; // interval
+ return derived().y_ticks_.minor_interval_; // interval
}
Derived& x_ticks_up_on(bool cmd)
{
- derived().use_up_ticks = cmd;
+ derived().x_ticks_.up_ticks_on_ = cmd;
return derived();
}
bool x_ticks_up_on()
{
- return derived().use_up_ticks;
+ return derived().x_ticks_.up_ticks_on_;
}
Derived& x_ticks_down_on(bool cmd)
{
- derived().use_down_ticks = cmd;
+ derived().x_ticks_.down_ticks_on_ = cmd;
return derived();
}
bool x_ticks_down_on()
{
- return derived().use_down_ticks;
+ return derived().x_ticks_.down_ticks_on_;
}
// Only need y_ticks_left_on & y_ticks_right_on in 2D
Derived& x_label_on(bool cmd)
{ // Show X-axis label text, or not.
- derived().use_x_label = cmd;
+ derived().x_axis_.label_on_ = cmd;
return derived();
}
bool x_label_on()
{
- return derived().use_x_label;
+ return derived().x_axis_.label_on_;
}
Derived& x_label_font_size(unsigned int i)
{
- derived().x_label_info.font_size(i);
+ derived().x_label_info_.style().font_size(i);
return derived();
}
unsigned int x_label_font_size()
{
- return derived().x_label_info.font_size();
+ return derived().x_label_info_.style().font_size();
}
Derived& x_value_font_size(unsigned int i)
{
- derived().x_value_value.font_size(i);
+ derived().x_value_value.style().font_size(i);
return derived();
}
unsigned int x_value_font_size()
{
- return derived().x_value_value.font_size();
+ return derived().x_value_value.style().font_size();
}
Derived& x_label_font_family(const std::string& family)
{
- derived().x_label_info.font_family(family);
+ derived().x_label_info_.style().font_family(family);
return derived();
}
const std::string& x_label_font_family()
{
- return derived().x_label_info.font_family();
+ return derived().x_label_info_.style().font_family();
}
Derived& x_value_ioflags(int flags)
{ // IO flags of X tick label values (default 0X201).
- derived().x_value_ioflags_ = flags;
+ derived().x_ticks_.value_ioflags_ = flags;
return derived();
}
int x_value_ioflags()
{ // ALL stream ioflags for control of format of X value labels.
- return derived().x_value_ioflags_;
+ return derived().x_ticks_.value_ioflags_;
}
Derived& title(const std::string title)
{ // Plot title.
- derived().title_info.text(title);
+ derived().title_info_.text(title);
return derived();
}
@@ -1718,113 +1683,113 @@
Derived& x_ticks_on_plot_window_on(bool cmd)
{ // External style.
- derived().use_x_ticks_on_plot_window_ = cmd;
+ derived().x_ticks_.ticks_on_plot_window_on_ = cmd;
return derived();
}
bool x_ticks_on_plot_window_on()
{ // External style = true.
- return derived().use_x_ticks_on_plot_window_;
+ return derived().x_ticks_.ticks_on_plot_window_on_;
}
Derived& x_label_units_on(bool cmd)
{
- derived().use_x_label_units = cmd;
+ derived().x_axis_.label_units_on = cmd;
return derived();
}
bool x_label_units_on()
{
- return derived().use_x_label_units;
+ return derived().x_axis_.label_units_on_;
}
Derived& x_major_labels_on(bool cmd)
{
- derived().use_x_major_labels = cmd;
+ derived().x_ticks_.major_value_labels_on = cmd;
return derived();
}
bool x_major_labels_on()
{
- return derived().use_x_major_labels;
+ return derived().x_ticks_.major_value_labels_on;
}
- Derived& x_major_label_rotation(int rot)
+ Derived& x_major_label_rotation(rotate_style rot)
{
- derived().x_label_rotation_ = rot;
+ derived().x_ticks_.label_rotation_ = rot;
return derived();
}
- int x_major_label_rotation()
+ rotate_style x_major_label_rotation()
{
- return derived().x_label_rotation_;
+ return derived().x_ticks_.label_rotation_;
}
Derived& title_on(bool cmd)
{
- derived().use_title = cmd;
+ derived().title_on_ = cmd;
return derived();
}
bool title_on()
{
- return derived().use_title;
+ return derived().title_on_;
}
Derived& x_major_grid_on(bool is)
{
- derived().use_x_major_grid_ = is;
+ derived().x_ticks_.major_grid_on_ = is;
return derived();
}
bool x_major_grid_on()
{
- return derived().use_x_major_grid_;
+ return derived().x_ticks_.major_grid_on_;
}
Derived& x_minor_grid_on(bool is)
{
- derived().use_x_minor_grid_ = is;
+ derived().x_ticks_.minor_grid_on_ = is;
return derived();
}
bool x_minor_grid_on()
{
- return derived().use_x_minor_grid_;
+ return derived().x_ticks_.minor_grid_on_;
}
Derived& axes_on(bool is)
{ // Draw *both* x and y axes (note plural).
- derived().use_x_axis_lines_ = is;
- derived().use_y_axis_lines_ = is;
+ derived().x_axis_.axis_line_on_ = is;
+ derived().y_axis_.axis_line_on_ = is;
return derived();
}
bool axes_on()
{ // Used X in preference to Y for 1D, but now require *both* x and y axis on.
- return derived().use_x_axis_lines_ && derived().use_y_axis_lines_;
+ return derived().x_axis_.axis_line_on_ && derived().y_axis_.axis_line_on_;
}
Derived& x_axis_on(bool is)
- { // Draw a horizontal x_axis line.
- derived().use_x_axis_lines_ = is;
+ { // Draw a horizontal x_axis_ line.
+ derived().x_axis_.axis_line_on_ = is;
return derived();
}
bool x_axis_on()
{ // Use X in preference to Y for 1D
- return derived().use_x_axis_lines_;
+ return derived().x_axis_.axis_line_on_;
}
Derived& y_axis_on(bool is)
- {// Draw a vertical y_axis line.
- derived().use_y_axis_lines_ = is;
+ {// Draw a vertical y_axis_ line.
+ derived().y_axis_.axis_line_on_ = is;
return derived();
}
bool y_axis_on()
{ // Should be always false for 1D.
- return derived().use_y_axis_lines_;
+ return derived().y_axis_.axis_line_on_;
}
// enums like PLOT_TITLE provide a std:string like "title"
@@ -1917,6 +1882,21 @@
return derived().image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color();
}
+ const std::string x_axis_position()
+ {
+ switch(derived().x_axis_position_)
+ {
+ case top:
+ return "y_axis_position top (all values < 0)"; break;
+ case x_intersect:
+ return "y_axis_position intersects X axis (range includes zero)"; break;
+ case bottom:
+ return "y_axis_position right (all values > 0)"; break;
+ default:
+ return "?"; break;
+ }
+ }
+
Derived& x_axis_color(const svg_color& col)
{ // Note only stroke color is set.
derived().image.get_g_element(PLOT_X_AXIS).style().stroke_color(col);
@@ -2066,74 +2046,74 @@
Derived& x_label(const std::string& str)
{
- derived().x_label_info.text(str);
+ derived().x_label_info_.text(str);
return derived();
}
std::string x_label()
{
- return derived().x_label_info.text();
+ return derived().x_label_info_.text();
}
Derived& x_label_units(const std::string& str)
{
- derived().x_units_info.text(str);
+ derived().x_units_info_.text(str);
return derived();
}
std::string x_label_units()
{
- return derived().x_units_info.text();
+ return derived().x_units_info_.text();
}
// y_label not needed in 1D.
Derived& y_label(const std::string& str)
{
- derived().y_label_info.text(str);
+ derived().y_label_info_.text(str);
return derived();
}
std::string y_label()
{
- return derived().y_label_info.text();
+ return derived().y_label_info_.text();
}
Derived& y_label_units(const std::string& str)
{
- derived().y_units_info.text(str);
+ derived().y_units_info_.text(str);
return derived();
}
std::string y_label_units()
{
- return derived().y_units_info.text();
+ return derived().y_units_info_.text();
}
Derived& x_major_interval(double inter)
{
- derived().x_major_interval_ = inter;
+ derived().x_ticks_.major_interval_ = inter;
return derived();
}
double x_major_interval()
{
- return derived().x_major_interval_;
+ return derived().x_ticks_.major_interval_;
}
Derived& x_major_tick_length(double length)
{
- derived().x_major_tick_length_ = length;
+ derived().x_ticks_.major_tick_length_ = length;
return derived();
}
double x_major_tick_length()
{
- return derived().x_major_tick_length_;
+ return derived().x_ticks_.major_tick_length_;
}
Derived& x_major_tick_width(double width)
{
- derived().x_major_tick_width_ = width; // Redundant?
+ derived().x_ticks_.major_tick_width_ = width; // Redundant?
derived().image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width(width);
return derived();
}
@@ -2145,18 +2125,18 @@
Derived& x_minor_tick_length(double length)
{
- derived().x_minor_tick_length_ = length;
+ derived().x_ticks_.minor_tick_length_ = length;
return derived();
}
double x_minor_tick_length()
{
- return derived().x_minor_tick_length_;
+ return derived().x_ticks_.minor_tick_length_;
}
Derived& x_minor_tick_width(double width)
{
- derived().x_minor_tick_width_ = width;
+ derived().x_ticks_.minor_tick_width_ = width;
derived().image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width(width);
return derived();
}
@@ -2169,99 +2149,100 @@
Derived& x_major_tick(double d)
{ // Interval (Cartesian units) between major ticks.
- derived().x_major_interval_ = d;
+ derived().x_ticks_.major_interval_ = d;
}
double x_major_tick()
{ // Interval (Cartesian units) between major ticks.
- return derived().x_major_interval_;
+ return derived().x_ticks_.major_interval_;
}
Derived& x_minor_interval(double interval)
{ // aka x_minor_tick
- derived().x_minor_interval_ = interval;
+ derived().x_ticks_.minor_interval_ = interval;
return derived();
}
Derived& x_num_minor_ticks(unsigned int num)
{
- derived().x_num_minor_ticks_ = num;
+ derived().x_ticks_.num_minor_ticks_ = num;
return derived();
}
unsigned int x_num_minor_ticks()
{ // NB NOT float or double!
- return derived().x_num_minor_ticks_;
+ return derived().x_ticks_.num_minor_ticks_;
}
Derived& x_range(double min_x, double max_x)
{
if(max_x <= min_x)
- {
- throw std::runtime_error("Illegal Argument: X range: x_max < x_min");
+ { // max_x <= min_x.
+ throw std::runtime_error("X range: max <= min!");
+ }
+ if((max_x - min_x) < std::numeric_limits<double>::epsilon() * 1000)
+ { // Range too small to display.
+ throw std::runtime_error("X range too small!" );
}
- derived().x_min = min_x;
- derived().x_max = max_x;
+ derived().x_axis_.min_ = min_x;
+ derived().x_axis_.max_ = max_x;
return derived();
}
std::pair<double, double> x_range()
{
std::pair<double, double> r;
- r.first = derived().x_min;
- r.second = derived().x_max;
+ r.first = derived().x_axis_.min_;
+ r.second = derived().x_axis_.max_;
return r;
}
- // Avoid clashes with class svg_1d_plot variable x_min & x_max,
- // so use longer x_minimum, x_maximum ...
- Derived& x_minimum(double min_x)
+ Derived& x_min(double min_x)
{
- // Can't check here that x_max > x_min because may not have set x_max yet.
- // TODO ensure that there is another check somewhere.
- derived().x_min = min_x;
+ // Not useful to check here that x_max_ > x_min_ because may not have set x_min_ yet.
+ derived().x_axis_.min_ = min_x;
return derived();
}
- double x_minimum()
+ double x_min()
{
- return derived().x_min;
+ return derived().x_axis_.min_;
}
- Derived& x_maximum(double x)
+ Derived& x_max(double x)
{
- // Can't check here that x_max > x_min because may not have set x_min yet.
- // TODO check that there is another check somewhere.
- derived().x_max = x;
+ // Not useful to check here that x_max_ > x_min_ because may not have set x_min_ yet.
+ derived().x_axis_.max_ = x;
return derived();
}
- double x_maximum()
+ double x_max()
{
- return derived().x_max;
+ return derived().x_axis_.max_;
}
- // Stylesheet.
-
- Derived& load_stylesheet(const std::string& file)
- {
- derived().image.load_stylesheet(file);
- return derived();
- }
+ //// Stylesheet.
+ // Removed for now to avoid compile warning in spirit.
- // Image info (& identical const version).
-
- svg& get_svg()
- {
- derived()._update_image();
- return derived().image;
- }
-
- const svg& get_svg() const
- {
- derived()._update_image();
- return derived().image;
- }
+ //Derived& load_stylesheet(const std::string& file)
+ //{
+ // derived().image.load_stylesheet(file);
+ // return derived();
+ //}
+
+ //// Image info (& identical const version).
+
+ //svg& get_svg()
+ //{
+ // derived()._update_image();
+ // return derived().image;
+ //}
+
+ //const svg& get_svg() const
+ //{
+ // derived()._update_image();
+ // return derived().image;
+ //}
}; // template <class Derived> class axis_plot_frame
} // detail
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-01-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -16,13 +16,6 @@
// This file svg_tag.hpp defines all classes that can occur in the SVG parse tree.
// -------------------------------------------------------------------------------
-#if defined (BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable: 4127) // "conditional expression is constant."
-# pragma warning(disable: 4512) // "assignment operator could not be generated."
-# pragma warning(disable: 4100) // "'boost_parameter_enabler_argument' : unreferenced formal parameter"
-#endif
-
#include <boost/ptr_container/ptr_container.hpp>
// using boost::vec_ptr;
#include <boost/array.hpp>
@@ -37,10 +30,6 @@
#include <vector>
// using std::vector;
-#if defined (BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
namespace boost
{
namespace svg
@@ -90,7 +79,7 @@
class svg_element
{ // Base class
protected:
- svg_style style_info; // fill, stroke, width, get by function style.
+ svg_style style_info; // fill, stroke, width, get by function style().
std::string id_name; // set & get by function id.
std::string clip_name; // set & get by function clip_id.
@@ -156,7 +145,7 @@
}
void clip_id(const std::string& id)
- { // Named clip, for example: g_ptr.clip_id(plot_window_clip);
+ { // Named clip, for example: g_ptr.clip_id(plot_window_clip_);
clip_name = id;
}
@@ -194,8 +183,10 @@
// Example: <line x1="5" y1="185" x2="340" y2="185"/>
}
}; // class line_element
+
+
// --------------------------------------------------
- // class rect_element; Represents a single rectangle.
+ // class rect_element: Represents a single rectangle.
// --------------------------------------------------
class rect_element : public svg_element
@@ -327,8 +318,6 @@
}
}; // class ellipse_element
-
-
// ----------------------------------------------------------------------
// text_element Represents a single block of text, with font & alignment.
// ----------------------------------------------------------------------
@@ -337,202 +326,144 @@
left_align, right_align, center_align
};
- enum rotate_style
- { // Rotation in degrees from horizontal.
- horizontal = 0, // normal left to right.
- uphill = -45, // slope up.
- upward = -90, // vertical writing up.
- backup = -135, // slope up backwards.
- downhill = 45, // slope down.
- downward = 90, // vertical writing down.
- backdown = 135, // slope down backwards.
- upsidedown = 180 // == -180
- };
-
- // text_element::text_element(double x, double y,
- // const std::string&,
- // int,
- // const std::string& font,
- // const std::string& style, const std::string& weight,
- // const std::string& stretch, const std::string& decoration,
- // int align, int rotate);
+ //enum rotate_style defined in svg_style.
+ //{ // Rotation in degrees from horizontal.
+ // horizontal = 0, // normal left to right.
+ // uphill = -45, // slope up.
+ // upward = -90, // vertical writing up.
+ // backup = -135, // slope up backwards.
+ // downhill = 45, // slope down.
+ // downward = 90, // vertical writing down.
+ // backdown = 135, // slope down backwards.
+ // upsidedown = 180 // == -180
+ //};
class text_element: public svg_element
{ // Holds text with position, size, font, (& styles) & orientation.
// Not necessarily shown correctly by all browsers, alas.
private: // Access only via member functions below.
- double x_coord; // Cartesian units.
- double y_coord;
- // http://www.w3.org/TR/SVG/text.html#FontFamilyProperty
- // 10.10 Font selection properties
- std::string txt; // Actual text to display
- // (may contain embedded xml characters for Greek, math etc, for example Ω).
- int size; // " font-size = 12"
- // http://www.w3.org/TR/SVG/text.html#CharactersAndGlyphs
- std::string font; // font-family: "Arial" | "Times New Roman" | "Verdana" | "Lucida Sans Unicode"
- // "sans", "serif", "times"
- std::string style_; // font-style: normal | bold | italic | oblique
- std::string weight; // font-weight: normal | bold | bolder | lighter | 100 | 200 .. 900
- std::string stretch; // font-stretch: normal | wider | narrower ...
- std::string decoration; // // "underline" | "overline" | "line-through"
- align_style align; // left_align, right_align, center_align
- int rotate; // horizontal, upward, downward, upsidedown
- // Example:
- // <text x="250" y="219.5" text-anchor="middle" font-family="verdana" font-size="12">0 </text>
-
- text_style style_info_; // To replace above elements.
+ // SVG Coordinates of 1st character EM box, see
+ // http://www.w3.org/TR/SVG/text.html#TextElement 10.2
+ // So any text with y coordinate = 0 shows only any roman lower case descenders!
+ double x_; // Left edge.
+ double y_; // Bottom of roman capital character.
+ std::string text_; // Actual text to display.
+ text_style style_; // font variants.
+ align_style align_; // left_align, right_align, center_align
+ rotate_style rotate_; // horizontal, upward, downward, upsidedown
+
+ // (Text may contain embedded xml Unicode characters
+ // for Greek, math etc, for example: Ω).
+ //int size; // " font-size = 12"
+ //// http://www.w3.org/TR/SVG/text.html#CharactersAndGlyphs
+ //std::string font; // font-family: "Arial" | "Times New Roman" | "Verdana" | "Lucida Sans Unicode"
+ //// "sans", "serif", "times"
+ //// http://www.w3.org/TR/SVG/text.html#FontFamilyProperty
+ //// 10.10 Font selection properties
+ //std::string style_; // font-style: normal | bold | italic | oblique
+ //std::string weight; // font-weight: normal | bold | bolder | lighter | 100 | 200 .. 900
+ //std::string stretch; // font-stretch: normal | wider | narrower ...
+ //std::string decoration; // // "underline" | "overline" | "line-through"
+ //// Example:
+ //// <text x="250" y="219.5" text-anchor="middle" font-family="verdana" font-size="12">0 </text>
public:
// Set and get member functions.
text_style& style()
- {
- return style_info_;
+ { // Access to font family, size ...
+ return style_;
}
const text_style& style() const
{
- return style_info_;
+ return style_;
}
- void font_alignment(align_style a)
+ void alignment(align_style a)
{ // left_align, right_align, center_align
- align = a;
+ align_ = a;
}
- align_style font_alignment()
+ align_style alignment()
{ // left_align, right_align, center_align
- return align;
- }
-
- void font_family(const std::string& s)
- { // Examples: "Arial", "Times New Roman", "Verdana", "Lucida Sans Unicode"
- font = s;
- }
-
- const std::string& font_family() const
- {
- return font;
- }
-
- void font_style(const std::string& s)
- {
- style_ = s;
- }
-
- const std::string& font_style() const
- {
- return style_;
- }
-
- void font_weight(const std::string& s)
- { // normal | bold | bolder | lighter | 100 | 200 .. 900
- weight = s;
- }
-
- const std::string& font_weight() const
- {
- return weight;
- }
-
- void font_stretch(const std::string& s)
- { // normal | wider | narrower .
- stretch = s;
- }
-
- const std::string& font_stretch() const
- {
- return stretch;
- }
-
- void font_decoration(const std::string& s)
- { // "underline" | "overline" | "line-through"
- decoration = s;
- }
-
- const std::string& font_decoration() const
- {
- return decoration;
- }
-
- void font_size(unsigned int i)
- { // pixels, default 10.
- size = i;
+ return align_;
}
- int font_size() const
- {
- return size;
- }
-
- void font_rotation(int rot)
+ void rotation(rotate_style rot)
{ // Degrees: horizontal = 0, upward = -90, downward, upsidedown
- rotate = rot;
+ rotate_ = rot;
}
- int font_rotation() const
+ rotate_style rotation() const
{
- return rotate;
+ return rotate_;
}
void x(double x)
{ // x coordinate of text to write.
- x_coord = x;
+ x_ = x;
}
double x() const
{ // x coordinate of text to write.
- return x_coord;
+ return x_;
}
void y(double y)
{ // y coordinate of text to write.
- y_coord = y;
+ y_ = y;
}
double y() const
{ // y coordinate of text to write.
- return y_coord;
+ return y_;
}
void text(const std::string& t)
{ // text to write.
- txt = t;
+ text_ = t;
}
- std::string text()
+ const std::string& text()
{
- return txt;
+ return text_;
}
- text_element(double x = 0., double y = 0.,
- const std::string& text = "",
- int size = 12,
- const std::string& font = "Lucida Sans Unicode",
- const std::string& style = "", const std::string& weight = "",
- const std::string& stretch = "", const std::string& decoration = "",
- align_style align = center_align, int rotate = horizontal,
- text_style ts = no_style) // To replace above elements.
+ text_element(
+ // Coordinates of 1st character EM box, see
+ // http://www.w3.org/TR/SVG/text.html#TextElement 10.2
+ double x = 0., // Left edge.
+ double y = 0., // Bottom of character (roman capital).
+ // So any text with y coordinate = 0 shows only the roman lower case descenders!
+ const std::string text = "",
+ text_style ts = no_style, // Left to SVG defaults.
+ align_style align = left_align,
+ rotate_style rotate = horizontal)
: // Constructor.
- x_coord(x), y_coord(y),
- txt(text),
- size(size),
- font(font),
- style_(style), weight(weight), stretch(stretch), decoration(decoration),
- align(align), rotate(rotate), style_info_(ts)
+ x_(x), y_(y), // location.
+ text_(text),
+ //size(size), font(font), style_(style), weight(weight), stretch(stretch), decoration(decoration),
+ style_(ts),
+ align_(align),
+ rotate_(rotate)
{ // text_element default constructor, defines defaults for all private members.
}
- void write(std::ostream& rhs)
- { // text & atributes to stream.
+ void write(std::ostream& os)
+ { // text_element, style & attributes to stream.
// Changed to new convention on spaces:
// NO trailing space, but *start* each item with a space.
- rhs << "<text x=\"" << x_coord << "\" y=\"" << y_coord << "\"";
+ // For debug, may be convenient to start with newline.
+ // os << " <text x=\"" << x_ << "\" y=\"" << y_ << "\"";
+ os << "\n<text x=\"" << x_ << "\" y=\"" << y_ << "\"";
std::string anchor;
- switch(align)
+ switch(align_)
{
case left_align:
- anchor = "start";
+ // anchor = "start"; // This is the initial == default.
+ // so should be possible to reduce file size this by:
+ anchor = "";
break;
case right_align:
anchor = "end";
@@ -546,45 +477,57 @@
}
if(anchor != "")
{
- rhs << " text-anchor=\"" << anchor << "\"";
+ os << " text-anchor=\"" << anchor << "\"";
}
- if(rotate != 0)
+ if(rotate_ != 0)
{
- rhs << " transform = \"rotate("
- << rotate << " "
- << x_coord << " "
- << y_coord << " )\"";
+ os << " transform = \"rotate("
+ << rotate_ << " "
+ << x_ << " "
+ << y_ << " )\"";
}
- if (font.size() != 0)
+ if (style_.font_size() != 0)
{
- rhs << " font-family=\"" << font << "\"";
+ os << " font-size=\"" << style_.font_size() << "\"";
}
- if (style_.size() != 0)
- {
- rhs << " font-style=\"" << style_ << "\"";
+ if (style_.font_family() != "")
+ { // Example: Arial.
+ os << " font-family=\"" << style_.font_family() << "\"";
}
- if (weight.size() != 0)
- {
- rhs << " font-weight=\"" << weight << "\"";
+ if (style_.font_style().size() != 0)
+ { // Example: italic.
+ os << " font-style=\"" << style_.font_style() << "\"";
}
- if (stretch.size() != 0)
- {
- rhs << " font-stretch=\"" << stretch << "\"";
+ if (style_.font_weight().size() != 0)
+ { // Example: bold.
+ os << " font-weight=\"" << style_.font_weight() << "\"";
}
- if (decoration.size() != 0)
+ if (style_.font_stretch().size() != 0)
{
- rhs << " font-decoration=\"" << decoration << "\"";
+ os << " font-stretch=\"" << style_.font_stretch() << "\"";
}
- if(size != 0)
+ if (style_.font_decoration().size() != 0)
{
- rhs << " font-size=\"" << size << "\">";
+ os << " font-decoration=\"" << style_.font_decoration() << "\"";
}
- rhs << txt << "</text>";
- // Example: <text x="149" y="207" text-anchor=" middle" font-family="Lucida Sans Unicode" font-size="12">3 </text>
- } // void write(std::ostream& rhs)
+ os << '>' << text_ << "</text>";
+ // Example:
+ } // void write(std::ostream& os)
+
}; // class text_element
+ std::ostream& operator<< (std::ostream& os, text_element& t)
+ { //
+ os << "text(" << t.x() << ", " << t.y() << ", "
+ << t.text() << ", "
+ << t.alignment()<< ", "
+ << t.rotation() << ")" ;
+ // Usage: text_element t(20, 30, "sometest", left_align, horizontal); cout << t << endl;
+ // Outputs:
+ return os;
+ } // std::ostream& operator<<
+
class clip_path_element: public svg_element
{ // The clipping path restricts the region to which paint can be applied.
@@ -1066,7 +1009,7 @@
std::ostream& operator<< (std::ostream& os, const poly_path_point& p)
{ // May be needed for Boost.Test.
- os << "(" << p.x << ", " << p.y << ")" ;
+ os << "(" << p.x << ", " << p.y << ")";
// Usage: poly_path_point p0(100, 200);
// cout << p0 << endl;
// Outputs: (100, 200)
@@ -1081,6 +1024,9 @@
// A polygon is defined by including a 'path' element
// which contains a points="(path data)" attribute,
// where the d attribute contains the x, y coordinate pairs.
+ friend std::ostream& operator<< (std::ostream&, const polygon_element&);
+ friend std::ostream& operator<< (std::ostream&, polygon_element&);
+
private:
//using boost::ptr_vector;
ptr_vector<poly_path_point> poly_points; // All the x, y coordinate pairs,
@@ -1213,8 +1159,36 @@
// 850,325 742,262.6 742,137.5" />
} // void write(std::ostream& o_str)
+ std::ostream& operator<< (std::ostream& os)
+ { // May be needed for Boost.Test.
+ for(ptr_vector<poly_path_point>::iterator i = poly_points.begin(); i != poly_points.end(); ++i)
+ {
+ os << (*i); // x, y coordinates as " (1, 2)"
+ }
+ // using os << "(" << p.x << ", " << p.y << ")" ;
+ // Usage: polygon_element p(1, 2, 3, 4, 5, 6);
+ // my_polygon.operator<<(cout);
+ // But NOT cout << my_polygon << endl;
+ // Outputs: (1, 2)(3, 4)(5, 6)
+ return os;
+ } // std::ostream& operator<<
+
}; // class polygon_element
+ std::ostream& operator<< (std::ostream& os, polygon_element& p)
+ { // May be needed for Boost.Test.
+ // ptr_vector<poly_path_point> poly_points; // All the x, y coordinate pairs,
+ for(ptr_vector<poly_path_point>::iterator i = p.poly_points.begin(); i != p.poly_points.end(); ++i)
+ {
+ os << (*i); // x, y coordinates as " (1, 2)(3, 4)..."
+ // using os << "(" << p.x << ", " << p.y << ")" ;
+ }
+ // Usage: polygon_element p(1, 2, 3, 4, 5, 6);
+ // cout << p << endl;
+ // Outputs: (1, 2)(3, 4)(5, 6)
+ return os;
+ } // std::ostream& operator<<
+
class polyline_element: public svg_element
{ // http://www.w3.org/TR/SVG/shapes.html#PolylineElement
// 9.6 The 'polyline' element: defines a set of connected straight line segments.
@@ -1228,6 +1202,7 @@
// perform an absolute lineto operation to that coordinate pair.
// The advantage of polyline is in reducing file size,
// avoiding M and repeated L before x & y coordinate pairs.
+ friend std::ostream& operator<< (std::ostream&, polyline_element&);
private:
ptr_vector<poly_path_point> poly_points; // All the (x, y) coordinate pairs,
@@ -1288,11 +1263,26 @@
}; // class polyline_element
+ std::ostream& operator<< (std::ostream& os, polyline_element& p)
+ { // May be needed for Boost.Test.
+ // ptr_vector<poly_path_point> poly_points; // All the x, y coordinate pairs,
+ for(ptr_vector<poly_path_point>::iterator i = p.poly_points.begin(); i != p.poly_points.end(); ++i)
+ {
+ os << (*i); // x, y coordinates as " (1, 2)(3, 4)..."
+ // using os << "(" << p.x << ", " << p.y << ")" ;
+ }
+ // Usage: polyline_element p(1, 2, 3, 4, 5, 6);
+ // cout << p << endl;
+ // Outputs: (1, 2)(3, 4)(5, 6)
+ return os;
+ } // std::ostream& operator<<
+
+
// -------------------------------------------------------------------
// g_element (group element) is the node element of our document tree.
// 'g' element is a container element for grouping together <g /></g>
// related graphics elements, for example:
- // <g fill="rgb(255,255,255)" id="background"><rect width="500" height="350"/></g>
+ // <g id="background" fill="rgb(255,255,255)"><rect width="500" height="350"/></g>
// -------------------------------------------------------------------
class g_element: public svg_element
{
@@ -1378,23 +1368,13 @@
}
g_element& text(double x = 0., double y = 0.,
- // The order of arguments DOES NOW match svg& text_element!
- // text_element::text_element(double x, double y,
- // const std::string&,
- // int,
- // const std::string& font,
- // const std::string& style, const std::string& weight,
- // const std::string& stretch, const std::string& decoration,
- // int align, int rotate);
-
const std::string& text = "",
- int text_size = 12,
- const std::string& font = "Lucida Sans Unicode",
- const std::string& style = "", const std::string& weight = "",
- const std::string& stretch = "", const std::string& decoration = "",
- align_style align = center_align, int rotate = horizontal)
+ text_style& style = no_style, // Use svg implementation's defaults.
+ align_style align = left_align,
+ rotate_style rotate = horizontal)
{
- children.push_back(new text_element(x, y, text, text_size, font, style, weight, stretch, decoration, align, rotate));
+ children.push_back(new text_element(x, y, text, style, align, rotate));
+ // font, style, weight, stretch, decoration, now in text_style.
return *this;
}
@@ -1410,38 +1390,52 @@
return *this;
}
- g_element& polygon(double x1, double y1, bool f)
+ // TODO should the default be fill or not?
+ g_element& polygon(double x1, double y1, bool f = true)
{
children.push_back(new polygon_element(x1, y1, f));
return *this;
}
- g_element& polygon(std::vector<poly_path_point>& points, bool f)
+ g_element& polygon(std::vector<poly_path_point>& points, bool f = true)
{
children.push_back(new polygon_element(points, f));
return *this;
}
- g_element& triangle(double x1, double y1, double x2, double y2, double x3, double y3, bool f)
+ g_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 *this;
}
- g_element& rhombus(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, bool f)
+ g_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));
+ children.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, x4, y4, f = true));
return *this;
}
- g_element& polyline(double x1, double y1, bool f)
+ g_element& pentagon(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double x5, double y5, bool f = true)
+ { // push_back a complete pentagon to the document.
+ children.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, f));
+ return *this; // svg&
+ }
+
+ g_element& hexagon(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double x5, double y5, double x6, double y6, bool f = true)
+ { // push_back a complete 6-sided star to the document.
+ children.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, f));
+ return *this; // svg&
+ }
+
+ g_element& polyline(double x1, double y1, bool f = true)
{
children.push_back(new polygon_element(x1, y1, f));
return *this;
}
- // These return a reference to the last child node just pushed.
+ // These return a reference to the last child node just pushed.
// (Unlike the above functions that return a g_element&).
+ // TODO why?
polygon_element& polygon()
{
children.push_back(new polygon_element()); // Empty polygon,
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/stylesheet.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/stylesheet.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/stylesheet.hpp 2008-01-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -14,6 +14,8 @@
#include <boost/spirit/core.hpp>
#include <boost/spirit/utility/distinct.hpp>
+// TODO get some inscrutable errors from this and so commented out of other modules.
+
#include <exception>
#include <string>
#include <fstream>
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg.hpp 2008-01-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -17,7 +17,7 @@
#include <exception>
#include <vector>
-#include "stylesheet.hpp" // TODO better to be called svg_stylesheet.hpp?
+//#include "stylesheet.hpp" // TODO better to be called svg_stylesheet.hpp?
#include "detail/svg_tag.hpp" // element class definitions.
#include "svg_style.hpp"
@@ -91,12 +91,6 @@
// svg& circle(double x, double y, unsigned int radius = 5)
// svg& ellipse(double rx, double ry, double cx, double cy)
-// svg& text(double x, double y, const std::string& text, int text_size = 12,
-// const std::string& font = "Lucida Sans Unicode",
-// const std::string& style = "", const std::string& weight = "",
-// const std::string& stretch = "", const std::string& decoration = "",
-// align_style align = center_align, int rotate = 0)
-
// write image out to ostream and file:
// svg& write(std::ostream& s_out)
// svg& write(const std::string& file)
@@ -124,6 +118,7 @@
std::string filename_; // file written to.
std::string author_; // Probably == copyright holder.
bool is_license_;
+ bool is_boost_license_;
std::string reproduction_; // "permits", "requires", or "prohibits"
std::string attribution_;
std::string commercialuse_;
@@ -222,6 +217,7 @@
css(""), // stylesheet.
filename_(""), // If written only to ostream, filename will not appear in comment.
is_license_(false), // No default license.
+ is_boost_license_(false), // No Boost license unless requested.
reproduction_("permits"), // Set with license:
distribution_("permits"), // permits, requires, or prohibits.
attribution_("requires"),
@@ -371,6 +367,14 @@
}
s_out.precision(coord_precision());
+ if (is_boost_license_ == true)
+ {
+ s_out <<
+ "<!-- Use, modification and distribution of this Scalable Vector Graphic file -->"
+ "\n<!-- are subject to the Boost Software License, Version 1.0. -->"
+ "\n<!-- (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->\n"
+ << std::endl;
+ } // is_boost_license
if (is_license_ == true)
{
s_out <<
@@ -395,7 +399,7 @@
"</rdf:RDF>\n"
"</metadata>"
<< std::endl;
- }
+ } // is_license
write_css(s_out);// stylesheet, if any.
write_document(s_out); // write clip paths and all document elements.
s_out << "</svg>" << std::endl; // close off svg tag.
@@ -419,6 +423,7 @@
svg& license(bool l)
{ // Set (or not) license using all requirement (default permits).
is_license_ = l;
+ return *this;
}
bool is_license()
@@ -426,6 +431,16 @@
return is_license_;
}
+ svg& boost_license(bool l)
+ { // Set (or not) Boost license.
+ is_boost_license_ = l;
+ return *this;
+ }
+
+ bool is_boost_license()
+ { // Shows if a license has been requested in the svg header metatadata.
+ return is_boost_license_;
+ }
const std::string& reproduction()
{ // Gets license reproduction requirement.
return reproduction_;
@@ -553,15 +568,12 @@
// -------------------------------------------------
// push_back information about text to the document.
// -------------------------------------------------
- svg& text(double x, double y, const std::string& text, int text_size = 12,
- const std::string& font = "Lucida Sans Unicode",
- const std::string& style = "", const std::string& weight = "",
- const std::string& stretch = "", const std::string& decoration = "",
- align_style align = center_align, int rotate = 0)
- {
- document.push_back(new text_element(x, y,
- text, text_size, font, style, weight, stretch, decoration, align, rotate)
- );
+ svg& text(double x, double y, const std::string& text,
+ const text_style& style, // size, font etc.
+ align_style align = center_align, rotate_style rotate = horizontal
+ )
+ {
+ document.push_back(new text_element(x, y, text, style, align, rotate) );
return *this;
}
@@ -584,18 +596,18 @@
svg& triangle(double x1, double y1, double x2, double y2, double x3, double y3, bool f = true)
{ // push_back a complete triangle to the document.
- document.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, f));
+ document.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, f));
return *this; // svg&
}
svg& rhombus(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, bool f = true)
- { // push_back a complete rhobus to the document.
+ { // push_back a complete rhombus to the document.
document.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, x4, y4, f));
return *this; // svg&
}
svg& pentagon(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double x5, double y5, bool f = true)
- { // push_back a complete rhobus to the document.
+ { // push_back a complete pentagon to the document.
document.push_back(new polygon_element(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, f));
return *this; // svg&
}
@@ -660,32 +672,32 @@
return document.g_tag(i);
}
- // -------------------------------------------------------------
- // Load stylesheet
- // -------------------------------------------------------------
-
- svg& load_stylesheet(const std::string& input)
- { // Load a stylesheet into string css from an input file.
- std::ifstream if_str(input.c_str());
-
- if(if_str.fail())
- {
- throw std::runtime_error("Error opening file " + input);
- }
- if(!validate_stylesheet(if_str))
- {
- throw std::runtime_error("Error loading stylesheet!");
- }
- if_str.clear();
- if_str.seekg(0);
- std::string tmp;
- css = "";
- while(std::getline(if_str, tmp))
- {
- css += tmp;
- }
- return *this;
- } // svg& load_stylesheet
+ //// -------------------------------------------------------------
+ //// Load stylesheet
+ //// -------------------------------------------------------------
+
+ //svg& load_stylesheet(const std::string& input)
+ //{ // Load a stylesheet into string css from an input file.
+ // std::ifstream if_str(input.c_str());
+
+ // if(if_str.fail())
+ // {
+ // throw std::runtime_error("Error opening file " + input);
+ // }
+ // if(!validate_stylesheet(if_str))
+ // {
+ // throw std::runtime_error("Error loading stylesheet!");
+ // }
+ // if_str.clear();
+ // if_str.seekg(0);
+ // std::string tmp;
+ // css = "";
+ // while(std::getline(if_str, tmp))
+ // {
+ // css += tmp;
+ // }
+ // return *this;
+ //} // svg& load_stylesheet
}; // class svg
} // namespace svg
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-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -12,11 +12,6 @@
#ifndef BOOST_SVG_SVG_1D_PLOT_HPP
#define BOOST_SVG_SVG_1D_PLOT_HPP
-//#if defined (BOOST_MSVC)
-//# pragma warning (disable: 4005) // 'BOOST_PARAMETER_MAX_ARITY' : macro redefinition
-//#endif
-
-#define BOOST_PARAMETER_MAX_ARITY 12
#include <boost/bind.hpp>
@@ -126,10 +121,10 @@
// Stored so as to avoid rewriting style information constantly.
svg image;
- text_element title_info; // Title of whole plot.
+ text_element title_info_; // Title of whole plot.
text_element legend_header; // legend box header (if any).
- text_element x_label_info; // Example: "length of widget"
- text_element x_units_info; // For example, to display, "length (meter)"
+ text_element x_label_info_; // Example: "length of widget"
+ text_element x_units_info_; // For example, to display, "length (meter)"
// No Y-axis info for 1D.
// Note that text_elements hold font_size.
@@ -137,10 +132,10 @@
// Allows for title and legend to be separate.
// Initially set to the width and height of the image.
// TODO Should this be unsigned int??? to be consistent.
- int plot_x1; // calculate_plot_window() sets these values.
- int plot_y1;
- int plot_x2;
- int plot_y2;
+ int plot_left_; // calculate_plot_window() sets these values.
+ int plot_top_;
+ int plot_right_;
+ int plot_bottom_;
// X-Axis information.
unsigned int x_major_tick_length_; // pixels.
@@ -153,7 +148,7 @@
// TODO Not sure it is wise to store in two places?
unsigned int x_major_grid_width_; // pixels.
unsigned int x_minor_grid_width_; // pixels.
- //unsigned int x_major_label; // pixels. Now in x_units_info font size
+ //unsigned int x_major_label; // pixels. Now in x_units_info_ font size
// Other information.
double text_margin_; // Marginal space around text items like title,
@@ -174,9 +169,9 @@
// X-Axis information.
// (Y_axis stored as one point because this is a 1D graph).
- double x_min; // minimum x (Cartesian units).
- double x_max; // maximum x (Cartesian units).
- double x_axis; // stroke width (pixels). ????
+ double x_min_; // minimum x (Cartesian units).
+ double x_max_; // maximum x (Cartesian units).
+ double x_axis_; // stroke width (pixels). ????
double x_major_interval_; // Interval (Cartesian units) between major ticks.
// set/get by x_major_interval
double x_minor_interval_; // Interval (Cartesian units) between minor ticks.
@@ -184,11 +179,11 @@
// but one could calculate x_minor_interval_.
// Yes/no options.
- bool use_title; // Show plot title.
- bool use_legend; // Show legend box.
+ bool title_on_; // Show plot title.
+ bool legend_on_; // Show legend box.
bool use_plot_window; // rather than whole image.
- bool use_x_axis_lines_; // = x_axis_on()
- bool use_y_axis_lines_; // Note: is needed in 1D version too in draw_axes.
+ bool use_x_axis_line_; // = x_axis_on()
+ bool use_y_axis_line_; // Note: is needed in 1D version too in draw_axes.
bool use_x_major_labels; // For example, to show value (like 1.2) by major ticks.
//bool use_x_minor_labels; // For example, to show value (like 1.2) by minor ticks.
// Not yet implemented (doubt if needed).
@@ -196,15 +191,15 @@
bool use_x_major_grid; // provide major vertical lines.
bool use_x_minor_grid;// provide minor vertical lines.
bool use_x_label; // Show label text for the axis, like "X-axis"
- bool use_up_ticks; // ticks only up from Y = 0 horizontal X-axis.
- bool use_down_ticks;// ticks only down from Y = 0 horizontal X-axis.
- //bool use_left_ticks; // only for 2D.
- //bool use_right_ticks;
- bool use_x_ticks; // = use_up_ticks || use_down_ticks
- // bool use_y_ticks; // = use_left_ticks || use_right_ticks only for 2-D
+ bool up_ticks_on_; // ticks only up from Y = 0 horizontal X-axis.
+ bool down_ticks_on_;// ticks only down from Y = 0 horizontal X-axis.
+ //bool left_ticks_on_; // only for 2D.
+ //bool right_ticks_on_;
+ bool x_ticks_on_; // = up_ticks_on_ || down_ticks_on_
+ // bool y_ticks_on_; // = left_ticks_on_ || right_ticks_on_ only for 2-D
// Note: can have ticks both up and down (the original style).
bool use_x_ticks_on_plot_window_; // rather than on Y = 0 horizontal axis.
- bool use_line; // set by line_on(bool); // Not really useful for 1-D,
+ bool legend_lines_; // set by legend_lines(bool); // Not really useful for 1-D,
// TODO but needs Boost-Parameter removed to do properly.
private:
@@ -214,10 +209,10 @@
std::vector<svg_plot_series> series;
// These are sorted into two vectors for normal and abnormal (max, inf and NaN).
- double x_scale; // Used for transform from Cartesian to SVG coordinates.
- double x_shift; // SVG origin is top left, Cartesian is bottom right.
- double y_scale;
- double y_shift;
+ double x_scale_; // Used for transform from Cartesian to SVG coordinates.
+ double x_shift_; // SVG origin is top left, Cartesian is bottom right.
+ double y_scale_;
+ double y_shift_;
// Public member functions, defined below.
// void calculate_transform(); //
@@ -229,36 +224,36 @@
public:
svg_1d_plot() : // Default constructor.
// Many ( but not all - see below) default values here.
- title_info(0, 0, "Plot of data", 20, "Verdana", "", "", "", "", center_align, horizontal),
+ title_info_(0, 0, "Plot of data", 20, "Verdana", "", "", "", "", center_align, horizontal),
legend_header(0, 0, "Legend", 16, "Arial", "", "", "", "", center_align, horizontal),
- x_label_info(0, 0, "X Axis", 14, "Lucida Sans Console", "", "", "", "", center_align, horizontal), //
- x_units_info(0, 0, "(units)", 14, "Lucida Sans Console", "", "", "", "", right_align, horizontal),
- //x_units_info(0, 0, "(units)", 14, "Times New Roman", "italic", "bold", "wider", "underline", right_align, horizontal),
+ x_label_info_(0, 0, "X Axis", 14, "Lucida Sans Console", "", "", "", "", center_align, horizontal), //
+ x_units_info_(0, 0, "(units)", 14, "Lucida Sans Console", "", "", "", "", right_align, horizontal),
+ //x_units_info_(0, 0, "(units)", 14, "Times New Roman", "italic", "bold", "wider", "underline", right_align, horizontal),
text_margin_(2.), // for text was 1.5 // as a fraction of the font size.
border_margin_(5), // Prevent plot window box begin right on edge.
legend_left_(-1), legend_right_(-1),legend_top_(-1),legend_bottom_(-1), // Indicates not yet set.
- x_min(-10), x_max(10),
- use_legend(false),
- use_title(true),
+ x_min_(-10), x_max_(10),
+ legend_on_(false),
+ title_on_(true),
use_plot_window(false),
use_x_label(false), // Label like "volume".
use_x_label_units(false),
use_x_major_labels(true), // Values on major ticks.
x_major_grid_width_(3),
x_minor_grid_width_(1),
- use_up_ticks(false),
- use_down_ticks(true),
+ up_ticks_on_(false),
+ down_ticks_on_(true),
use_x_ticks_on_plot_window_(false), // was external_style
// use_y_ticks_on_plot_window_(false), // was external_style
- use_x_ticks(true), // use_up_ticks || use_down_ticks
+ x_ticks_on_(true), // up_ticks_on_ || down_ticks_on_
// 2D has left and right ticks too.
- use_line(true),
+ legend_lines_(true),
use_x_major_grid(false),
// x_minor_grid_width(1),
use_x_minor_grid(false),
- use_x_axis_lines_(true),
- use_y_axis_lines_(false), // Not needed for 1D, but leave at false.
+ use_x_axis_line_(true),
+ use_y_axis_line_(false), // Not needed for 1D, but leave at false.
x_major_interval_(2), // interval between x major ticks
x_major_tick_width_(3),
x_minor_tick_width_(1),
@@ -266,15 +261,15 @@
x_minor_tick_length_(5), // If both up and down, total is twice this.
x_num_minor_ticks_(2),
// legend_title_size(12), TD remove - now in text_element
- x_scale(1.), x_shift(0),
- y_scale(1.), y_shift(0)
+ x_scale_(1.), x_shift_(0),
+ y_scale_(1.), y_shift_(0)
// See documentation for default settings rationale.
{
image_size(500, 200); // Default image size.
// Only need to be quite shallow (y_size) for a 1-D plot.
// 200 barely leaves enough room for five data series in the legend).
// (2-D usually needs to be much more rectangular).
- use_x_ticks = use_up_ticks || use_down_ticks;
+ x_ticks_on_ = up_ticks_on_ || down_ticks_on_;
// Only 2D has left and right ticks.
// Build the document tree & add all the children of the root node.
@@ -303,10 +298,10 @@
//void calculate_transform()
//{ // Calculate scale and shift factors for transform from Cartesian to plot.
// // SVG image is 0, 0 at top left, Cartesian at bottom left.
- // x_scale = (plot_x2 - plot_x1) / (x_max - x_min);
- // x_shift = plot_x1 - (x_min * (plot_x2 - plot_x1) / (x_max - x_min));
- // y_scale = 1.;
- // y_shift = plot_y1 - (plot_y1 - plot_y2) / 2.;
+ // x_scale_ = (plot_right_ - plot_left_) / (x_max_ - x_min_);
+ // x_shift_ = plot_left_ - (x_min_ * (plot_right_ - plot_left_) / (x_max_ - x_min_));
+ // y_scale_ = 1.;
+ // y_shift_ = plot_top_ - (plot_top_ - plot_bottom_) / 2.;
//} // void calculate_transform()
void draw_axes()
@@ -316,23 +311,23 @@
double y2(image.y_size());
transform_x(x);
// Draw origin, making sure it is in the plot window.
- if(use_x_axis_lines_ && (x > plot_x1) && (x < plot_x2))
+ if(use_x_axis_line_ && (x > plot_left_) && (x < plot_right_))
{ // TODO >= and <= ? instead.
if(!use_plot_window)
{ // Use whole image.
- if(use_title)
+ if(title_on_)
{ // Allow space for title, taking account of font size.
- y1 += title_info.font_size() * (text_margin_ +1);
+ y1 += title_info_.font_size() * (text_margin_ +1);
}
if(use_x_label)
{// Allow space for x tick values, taking account of font size.
- y2 -= x_label_info.font_size() * text_margin_;
+ y2 -= x_label_info_.font_size() * text_margin_;
}
}
else
{ // Use plot window.
- y1 = plot_y1;
- y2 = plot_y2;
+ y1 = plot_top_;
+ y2 = plot_bottom_;
}
image.get_g_element(detail::PLOT_X_AXIS).line(x, y1, x, y2);
}
@@ -341,44 +336,40 @@
void calculate_plot_window()
{ // For 1-D
- x_axis = (plot_y2 + plot_y1) / 2.; // Put X-axis halfway up plot window.
- plot_x1 = 0; // Top left of image.
- plot_y1 = 0;
- plot_x2 = image.x_size(); // Bottom right of image.
- plot_y2 = image.y_size();
+ x_axis_ = (plot_bottom_ + plot_top_) / 2.; // Put X-axis halfway up plot window.
+ plot_left_ = 0; // Top left of image.
+ plot_top_ = 0;
+ plot_right_ = image.x_size(); // Bottom right of image.
+ plot_bottom_ = image.y_size();
if(use_plot_window)
{
- plot_x1 += border_margin_; // small margin around border.
- plot_x2 -= border_margin_; //
- plot_y1 += border_margin_; //
- plot_y2 -= border_margin_;
-
- if(use_title)
- {
- // Allow a blank line, title lines and a line space.
- plot_y1 += title_font_size() * 2;
+ plot_left_ += border_margin_; // small margin around border.
+ plot_right_ -= border_margin_; //
+ plot_top_ += border_margin_; //
+ plot_bottom_ -= border_margin_;
+
+ if(title_on_)
+ { // Allow a blank line, title lines and a line space.
+ plot_top_ += title_font_size() * 2;
}
- if(use_legend)
+ if(legend_on_)
{ // Allow space for legend at right.
- plot_x2 -= 150; // This 150 is an arbitrary legend box width.
+ plot_right_ -= 150; // This 150 is an arbitrary legend box width.
// TODO size could depend on font_size & length of text?
}
if(use_x_label)
{// Allow space for x_label at bottom.
- plot_y2 -= static_cast<int>(x_label_info.font_size() * text_margin_);
+ plot_bottom_ -= static_cast<int>(x_label_info_.font_size() * text_margin_);
}
- if(use_down_ticks)
+ if(down_ticks_on_)
{ // Allow space for the downward ticks
// (so don't go into/over the border margin).
- // TODO use std::max here.
- plot_y2 -=
- (x_major_tick_length_ > x_minor_tick_length_) ?
- x_major_tick_length_ : x_minor_tick_length_;
+ plot_bottom_ -= (std::max)(x_major_tick_length_, x_minor_tick_length_)
}
// Draw plot window rect.
image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).push_back(
- new rect_element(plot_x1, plot_y1, (plot_x2 - plot_x1), plot_y2 - plot_y1));
+ new rect_element(plot_left_, plot_top_, (plot_right_ - plot_left_), plot_bottom_ - plot_top_));
// <g id="plotBackground" fill="rgb(248,248,255)"><rect x="43" y="53" width="302" height="304"/></g>
} // use_plot_window
} // void calculate_plot_window()
@@ -395,11 +386,11 @@
calculate_plot_window();
//calculate_transform();
draw_title(); // Call after above to the plot_x and y are defined.
- if(use_x_axis_lines_)
+ if(use_x_axis_line_)
{
draw_axes();
}
- if(use_legend)
+ if(legend_on_)
{
draw_legend();
}
@@ -413,20 +404,20 @@
{ // For each of the data series.
g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_POINTS).add_g_element();
- g_ptr.style().stroke_color(series[i].point_style.stroke_color);
- g_ptr.style().fill_color(series[i].point_style.fill_color);
+ g_ptr.style().stroke_color(series[i].point_style_.stroke_color);
+ g_ptr.style().fill_color(series[i].point_style_.fill_color);
for(unsigned int j = 0; j < series[i].series.size(); ++j)
{ // Draw points for jth series.
double x = series[i].series[j];
transform_x(x);
if( // Check point is inside plot_window (otherwise ignore it).
- (x > plot_x1) // TODO <=?
- && (x < plot_x2)
- && (y > plot_y1)
- && (y < plot_y2) )
+ (x > plot_left_) // TODO <=?
+ && (x < plot_right_)
+ && (y > plot_top_)
+ && (y < plot_bottom_) )
{
- draw_plot_point(x, y, g_ptr, series[i].point_style);
+ draw_plot_point(x, y, g_ptr, series[i].point_style_);
}
} // for j
} // for
@@ -467,9 +458,9 @@
// Default stream precision 6 decimal digits is probably excessive.
// 4.1 Basic data types, integer or float in decimal or scientific (using e format).
// - probably enough if image size is under 1000 x 1000.
- // This will reduce .svg file sizes significantly for curves represented with many data points.
+ // Reduces .svg file sizes significantly for curves represented with many data points.
// For example, if a curve is shown using 100 points,
- // reducing to coord_precision(3) from 6 will reduce file size by 300 bytes.
+ // reducing to coord_precision(3) from default of 6 will reduce file size by 300 bytes.
image.write(s_out);
return (svg_1d_plot&)*this;
}
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-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -11,19 +11,15 @@
#ifndef BOOST_SVG_SVG_2D_PLOT_HPP
#define BOOST_SVG_SVG_2D_PLOT_HPP
-#define BOOST_PARAMETER_MAX_ARITY 12
-
-#include <boost/bind.hpp>
-
-#if defined (BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable: 4512) // "assignment operator could not be generated."
-# pragma warning(disable: 4127) // "conditional expression is constant."
-# pragma warning(disable: 4100) // "'boost_parameter_enabler_argument' : unreferenced formal parameter"
+#ifdef _MSC_VER
+#pragma warning(push)
+# pragma warning (disable : 4800) // forcing value to bool 'true' or 'false' (performance warning)
+# pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
+# pragma warning (disable : 4224) // nonstandard extension used : formal parameter 'function_ptr' was previously defined as a type
+# pragma warning (disable : 4512) // assignment operator could not be generated
+# pragma warning (disable : 4503) // decorated name length exceeded, name was truncated
#endif
-#include <boost/parameter/preprocessor.hpp>
-#include <boost/parameter/name.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include "svg_style.hpp"
@@ -32,10 +28,6 @@
#include "detail/functors.hpp"
#include "svg.hpp"
-#if defined (BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
#include <map>
#include <string>
#include <sstream>
@@ -49,42 +41,38 @@
{
namespace svg
{
+ // Forward declarations.
+ const std::string strip_e0s(std::string s); // Strip unncessary zeros and e and sign.
+ class svg_2d_plot; // Plot.
+ class svg_2d_plot_series; // plot data series.
+
+ 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.
-#ifndef BOOST_SVG_BOOST_PARAMETER_NAMES
-#define BOOST_SVG_BOOST_PARAMETER_NAMES
- BOOST_PARAMETER_NAME(my_plot)
- BOOST_PARAMETER_NAME(container)
- BOOST_PARAMETER_NAME(title)
- BOOST_PARAMETER_NAME(stroke_color)
- BOOST_PARAMETER_NAME(fill_color)
- BOOST_PARAMETER_NAME(point_style)
- BOOST_PARAMETER_NAME(x_functor)
- BOOST_PARAMETER_NAME(size)
-#endif
- // TODO Why are these outside the #endif? Subset?
- // Remove when class plot used instead of Boost.Parameter.
- BOOST_PARAMETER_NAME(bezier_on)
- BOOST_PARAMETER_NAME(line_on)
- BOOST_PARAMETER_NAME(line_color)
- BOOST_PARAMETER_NAME(area_fill_color)
-
- // -----------------------------------------------------------------
- // This allows us to store plot state locally in svg_plot. We don't
- // store it in "svg" because transforming the points after they are
- // written to the document would be difficult. We store the Cartesian
- // coordinates locally and transform them before we write them.
- // -----------------------------------------------------------------
- struct svg_2d_plot_series;
- class svg_2d_plot;
-
- static const double wh_ = 0.7; // font text width/height ratio.
static const double sin45 = 0.707; // Use if axis value labels are sloping.
- enum y_axis_intersect {left = -1, y_intersect = 0, right = +1};
+ // x_axis_position_ and y_axis_position_ use these.
enum x_axis_intersect {bottom = -1, x_intersect = 0, top = +1};
+ // bottom = X-axis free below bottom of end of Y-axis (case of all definitely < 0).
+ // top = X-axis free above top of X-axis (case of all definitely > 0).
+ // x_intersect when y values include zero, so intersects the Y axis.
- struct svg_2d_plot_series
+ enum y_axis_intersect {left = -1, y_intersect = 0, right = +1};
+ // left = Y-axis free to left of end of X-axis (case of all definitely < 0).
+ // right = Y-axis free to left of end of X-axis (case of all definitely > 0).
+ // y_intersect when y values include zero, so intersects the X axis.
+
+ // -----------------------------------------------------------------
+ // This allows us to store plot state locally in svg_plot. We don't
+ // store it in "svg" because transforming the points after they are
+ // written to the document would be difficult. We store the Cartesian
+ // coordinates locally and transform them before we write them.
+ // -----------------------------------------------------------------
+ class svg_2d_plot_series
{
+ public:
// 2-D Data series points to plot.
std::multimap<double, double> series; // Normal 'OK to plot' data values.
std::multimap<double, double> series_limits; // 'limit' values: too big or small, or NaN.
@@ -93,19 +81,20 @@
// are unaffected by the order in which data is presented.
// (For 1-D a vector of doubles can be used).
- std::string title;
- plot_point_style point_style;
- plot_line_style line_style;
+ std::string title_; // Title of data series.
+ plot_point_style point_style_;
+ plot_point_style limit_point_style_;
+ plot_line_style line_style_;
template <class T>
svg_2d_plot_series(T begin, T end,
- std::string title, // of data series.
- const plot_point_style& point,
- const plot_line_style& line)
+ std::string title) // Title of data series.
:
- title(title),
- point_style(point),
- line_style(line)
+ title_(title),
+ point_style_(black, blank, 10, round), // Default point style.
+ limit_point_style_(grey, blank, 10, cone), // Default limit (inf or NaN) point style.
+ // plot_line_style(const svg_color& col = black, const svg_color& acol = true, bool on = true, bool bezier_on = false)
+ line_style_(black, true, true, false) // Default line style, no fill.
{ // Constructor.
for(T i = begin; i != end; ++i)
{ // Sort into normal and limited series.
@@ -114,286 +103,199 @@
series_limits.insert(*i);
}
else
- { // normal point.
+ { // normal data values for both x and y.
series.insert(*i);
}
}
} // svg_2d_plot_series
- }; // struct svg_2d_plot_series
+ // Set functions for the plot series.
+ // TODO get functions for completeness?
+ svg_2d_plot_series& fill_color(const svg_color& col_)
+ {
+ point_style_.fill_color_ = col_;
+ return *this;
+ }
+
+ svg_2d_plot_series& stroke_color(const svg_color& col_)
+ {
+ point_style_.stroke_color_ = col_;
+ return *this;
+ }
+
+ svg_2d_plot_series& shape(point_shape shape_)
+ {
+ point_style_.shape_ = shape_;
+ return *this;
+ }
+
+ svg_2d_plot_series& size(int size_)
+ {
+ point_style_.size_ = size_;
+ return *this;
+ }
+
+ svg_2d_plot_series& line_color(const svg_color& col_)
+ {
+ line_style_.color_ = col_;
+ return *this;
+ }
+ svg_2d_plot_series& line_on(bool on_)
+ {
+ line_style_.line_on_ = on_;
+ return *this;
+ }
+
+ svg_2d_plot_series& bezier_on(bool on_)
+ {
+ line_style_.bezier_on_ = on_;
+ return *this;
+ }
+
+ }; // struct svg_2d_plot_series
class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
{ // See also svg_1d_plot.hpp for 1-D version.
private:
+ // Member data names conventionally end with _,
+ // for example: border_margin_
+ // and set/get accessor functions border_margin() & border_margin(int).
+
friend class detail::axis_plot_frame<svg_2d_plot>;
- // Contains functions common to 1 and 2-D.
+ // axis_plot_frame.hpp contains functions common to 1 and 2-D.
- double x_scale; // Use by function transform()
- double x_shift; // to go from Cartesian to svg coordinates.
- double y_scale;
- double y_shift;
+ double x_scale_; // Use by function transform()
+ double x_shift_; // to go from Cartesian to svg coordinates.
+ double y_scale_;
+ double y_shift_;
// Stored so as to avoid rewriting style information constantly.
svg image;
- text_style a_style; // Defaults.
+ double text_margin_; // Marginal space around text items like title,
+ // text_margin_ * font_size to get distance in svg units.
- text_element title_info; // Plot title.
+ text_style a_style_; // Defaults.
+ // text_style contains font size & type etc.
+ text_style title_style_;
+ text_style legend_style_;
+ text_style x_axis_label_style_;
+ text_style x_value_label_style_;
+ text_style y_axis_label_style_;
+ text_style y_value_label_style_;
+ text_style point_symbols_style_; // Used for data point marking.
+
+ text_element title_info_; // Plot title.
text_element legend_header_; // legend box header or title (if any).
- text_element x_label_info; // For example: "length"
- text_element x_label_value; // For example: "1.2" or "1.2e+001"
- text_element y_label_info; // For example: "volume"
- text_element x_units_info; // For example: "mm"
- text_element y_units_info; // 2-D only.
- text_element y_label_value; // For example: "1.2" or "1.2e+001"
-
- int x_value_precision_; // precision for tick value labels, usually 3 will suffice.
- int y_value_precision_; // precision for tick value labels, usually 3 will suffice.
- // Used to decide how much space to allow for tick values.
- int x_value_ioflags_; // IO formatting flags for X-axis.
- int y_value_ioflags_; // IO formatting flags for Y-axis.
- double text_margin_; // Marginal space around text items like title,
- // as a fraction of font size, (pixels) (was fixed at 1.5).
- double border_margin_; // Marginal (pixels) space around the plot border.
- double border_width_; // plot border rectangle width.
-
- // Border information for the plot window (<= image size).
- // Allows for title and legend to be separate.
- // Initially will be set to the width and height of the graph image.
- // calculate_plot_window() sets these values.
- double plot_x1; // TODO These (and many others) also could be float?
- double plot_x2;
- double plot_y1;
- double plot_y2;
-
- // X-Axis information.
- double x_min; // minimum x value (Cartesian units).
- double x_max; // maximum x value (Cartesian units).
- double x_axis; // // x-axis (y = 0) transformed into SVG Y coordinates. -1 if not caculated yet.
- double x_major_interval_; // x_major_interval_ is the stride or interval for major x ticks.
- // (Cartesian units) set/get by x_major_interval
- double x_minor_interval_; // Interval (Cartesian units) between minor ticks.
- // No set function because x_num_minor_ticks_ used to determine this instead,
- // but one could calculate x_minor_interval_.
-
- // text width is effectively the boldness of the font.
- // But only in graphics mode rather than text mode, and style "bold"
- // and this is poor on some browsers, so recommend to not set width.
- // 0 is default, 1 is bolder, 2 very bold and a not-yet-implemented boldness.
- double image_border_width_;
- double title_font_width_;
- double legend_font_width_;
- legend_places legend_place_;
- double legend_width_; // width of legend box in pixels.
- double legend_height_; // height of legend box in pixels.
- double legend_left_; // Left of legend box. (Optionally set by legend_top_left).
+ text_element x_label_info_; // For example: "length"
+ text_element x_label_value_; // For example: "1.2" or "1.2e+001"
+ text_element y_label_info_; // For example: "volume"
+ text_element x_units_info_; // For example: "mm"
+ text_element y_units_info_; // 2-D only.
+ text_element y_label_value_; // For example: "1.2" or "1.2e+001"
+
+ box_style image_border_;
+ box_style plot_window_border_;
+
+ // TODO doubles also could be float?
+ double plot_left_;
+ double plot_right_;
+ double plot_top_;
+ double plot_bottom_;
+
+ // enum legend_places{ nowhere, inside...}
+ legend_places legend_place_; // Place for any legend box.
+ double legend_width_; // Width of legend box (pixels).
+ double legend_height_; // Height of legend box (in pixels).
+ double legend_left_; // Left of legend box.
double legend_top_; // Top of legend box.
+ // Both optionally set by legend_top_left.
// Size of legend box is controlled by its contents,
- // but may be helpful to store bottom right coordinates.
+ // but helpful to store bottom right coordinates.
// legend_bottom_right() gives access.
- double legend_right_; // right of legend box.
+ double legend_right_; // SVG Coordinates of right of legend box,
double legend_bottom_; // bottom of legend box.
- size_t legend_longest_; // longest string in legend box.
- double x_label_width_; // Used for value too.
- double x_axis_width_; // X-axis horizontal line width. set/get by x_axis_width()
- double x_major_tick_length_; // pixels.
- double x_major_tick_width_; // pixels.
- double x_minor_tick_length_; // pixels.
- double x_minor_tick_width_; // pixels.
- // Avoid name clash with x_m*_tick_length and width.
- unsigned int x_num_minor_ticks_; // number of minor ticks, eg 4 gives major 0, minor 1,2,3,4, major 5
- double x_major_grid_width_; // pixels.
- double x_minor_grid_width_; // pixels.
- // grid width is set in style.stroke_width
- int x_axis_position_; //
-
- // Y-Axis information.
- unsigned int y_num_minor_ticks_; // number of minor ticks, eg 4 gives major 0, minor 1,2,3,4, major 5
- double y_min; // minimum y value (Cartesian units).
- double y_max; // maximum y value (Cartesian units).
- double y_major_interval_; // y_major_interval_ is the stride or interval for major y ticks.
- double y_minor_interval_; // y_minor_interval_ is the stride or interval for minor y ticks.
- double y_label_width_; // TODO used for axis width too for now. OK?
- double y_axis; // Y-axis (x = 0) transformed into X SVG coordinates. -1 if not caculated yet.
- double y_axis_width_; // Y-axis vertical line width. set/get by y_axis_width()
- double y_major_tick_length_; // pixels.
- double y_major_tick_width_; // pixels.
- double y_minor_tick_length_; // pixels.
- double y_minor_tick_width_; // pixels.
- // Avoid name clash with x_m*_tick_length and width.
- // grid width is set in style.stroke_width
- double y_major_grid_width_; // pixels.
- double y_minor_grid_width_; // pixels.
- double x_label_length_; // width (in SVG) of longest label on X-axis.
- double y_label_length_; // width (in SVG) of longest label on Y-axis.
- int y_axis_position_; //
-
- // Yes/no options.
- bool use_title; // Provide a title for the whole plot.
- bool use_legend; // Provide a legend box.
- bool use_outside_legend_;
- bool use_axis; // Draw x and y axes. TODO split so can have either or both.
- bool use_plot_window_; // Use a separate plot window.
- bool use_x_label; // Label axis with text.
- bool use_y_label;
- bool use_x_major_labels; // values for major ticks.
- bool use_y_major_labels;
- bool use_x_label_units;
- bool use_y_label_units;
- int x_label_rotation_; // X_axis value labels written.
- int y_label_rotation_; // Y_axis value labels written.
- bool use_x_major_grid_;
- bool use_x_minor_grid_;
- bool use_y_major_grid_;
- bool use_y_minor_grid_;
-
- // Note: can have ticks both up and/or down, and/or left and right.
- bool use_up_ticks;
- bool use_down_ticks;
- bool use_x_ticks; // = use_up_ticks || use_down_ticks
- bool use_left_ticks;
- bool use_right_ticks;
- // bool use_y_ticks; // = use_left_ticks || use_right_ticks
- // was external style.
- bool use_x_ticks_on_plot_window_; // Value labels & ticks on the plot window rather than on X-axis.
- bool use_y_ticks_on_plot_window_; // Value labels & ticks on the plot window rather than on Y-axis.
- bool use_x_axis_lines_; // Draw a horizontal X-axis line.
- bool use_y_axis_lines_; // Draw a vertical Y-axis line.
- bool use_line; // get/set by line_on(bool); // Not really useful for 1-D,
- // TODO but needs Boost-Parameter removed to do properly.
- bool strip_e0s_;
- unsigned int longest_; // string in legend box.
+ size_t legend_longest_; // longest (both header & data) string in legend box,
+
+ axis_line_style x_axis_;
+ axis_line_style y_axis_;
+
+ ticks_labels_style x_ticks_;
+ ticks_labels_style y_ticks_;
+
+ bool title_on_; // Provide a title for the whole plot.
+ bool legend_on_; // Provide a legend box.
+ bool outside_legend_on_; // legend box outside the plot window.
+ bool legend_lines_; // get/set by legend_lines(bool); data colored line type in legend box.
+ bool plot_window_on_; // Use a separate plot window (not whole image).
+ //bool axes_on_; // Draw *both* x and y axes lines. useful?
+ bool x_ticks_on_; // TODO check these are really useful.
+ bool y_ticks_on_;
+
+ int x_axis_position_; // TODO should these be in axis_style?
+ int y_axis_position_; // But complications with difference between X and Y.
// Where we will be storing the data points (series) for transformation.
std::vector<svg_2d_plot_series> series; // Defined above.
- std::string plot_window_clip; // = "clip_plot_window" id for clippath
-
+ std::string plot_window_clip_; // = "clip_plot_window" id for clippath
// http://www.w3.org/TR/SVG/masking.html#ClipPathElement 14.1 Introduction
// clipping paths, which uses any combination of 'path', 'text' and basic shapes
// to serve as the outline where everything on the "inside" of the outline
// is allowed to show through but everything on the outside is masked out.
- // So the plot_window_clip limits display to a plot_window rectangle.
-
- //text_style label_style(40); // Or use all defaults.
- //text_style(int size = 12, // defaults:
- //const std::string& font = "sans",
- //const std::string& style = "",
- //const std::string& weight = "",
- //const std::string& stretch = "",
- //const std::string& decoration = "")
- //label_style().font_weight("bold");
+ // So the plot_window_clip_ limits display to a plot_window rectangle.
public: // of class svg_2d_plot: public detail::axis_plot_frame<svg_2d_plot>
- svg_2d_plot() // Constructor, including all the very many default plot options.
+ svg_2d_plot() // Constructor, including all the very many default plot options,
+ // some which use some or all of the class defaults.
:
// TODO check that *all* options are initialized here.
// See documentation for default settings rationale.
+ // text_styles:
+ title_style_(16, "Verdana", "", ""), // last "bold" ?
+ legend_style_(14, "Verdana", "", ""), // 2nd "italic"?
+ x_axis_label_style_(14, "Verdana", "", ""),
+ x_value_label_style_(12, "Verdana", "", ""),
+ // Separate x and y to allow axes to have a different style.
+ y_axis_label_style_(14, "Verdana", "", ""),
+ y_value_label_style_(12, "Verdana", "", ""),
+ point_symbols_style_(12, "Lucida Sans Unicode"), // Used for data point marking.
+
+ title_info_(0, 0, "Plot of data", title_style_, center_align, horizontal),
+ x_label_info_(0, 0, "X Axis", x_axis_label_style_, center_align, horizontal),
+ 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), // For defaults see axis_line_style.
+ y_axis_(Y),
+ x_ticks_(X),// For defaults see ticks_labels_style.
+ y_ticks_(Y),
+ 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),
+ //image_border_width_(1), // Now in box_style
+ text_margin_(2.), // for axis label text, as a multiplier of the font size.
- a_style(16, "serif"),
- title_info(0, 0, "Plot of data", 16, "Verdana", "", "", "", "", center_align, horizontal),
- title_font_width_(1), // text width is effectively the boldness of the font.
+ image_border_(blue, whitesmoke, 2, 3, true, true),
+ plot_window_border_(yellow, svg_color(255, 255, 255), 2, 3, true, false),
+ legend_header_(0, 0, "", legend_style_, center_align, horizontal),
legend_width_(200), // width of legend box (pixels)
- legend_header_(0, 0, "", 14, "Verdana", "italic", "", "bold", "", center_align, horizontal),
- legend_font_width_(0.5),
- x_label_info(0, 0, "X Axis", 14, "Verdana", "", "bold", "", "", center_align, horizontal),
- x_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, horizontal, a_style),
- x_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, horizontal),
- // TODO use this and provide way to set'n'get separately.
- x_axis(-1), // -1 means not yet valid.
- y_axis(-1), // -1 means not yet valid.
- x_label_width_(2),
- x_axis_width_(2), // Width of X-axis line.
- y_label_info(0, 0, "Y Axis", 14, "Verdana", "", "bold", "", "", center_align, upward),
- y_units_info(0, 0, "(units)", 14, "Verdana", "", "", "", "", center_align, upward),
- y_label_value(0, 0, "", 12, "Verdana", "", "", "", "", center_align, upward),
- y_label_width_(5),
- y_axis_width_(2), // vertical line.
- x_label_rotation_(horizontal),
- y_label_rotation_(horizontal),
- // Plot may look odd if font and size of label & units are different!
- // y_units_info(0, 0, "(units)", 11, "Times New Roman", "italic", "bold", "wider", "underline", right_align, upsidedown),
- // shows some values that might be useful if svg browsers are fully implemented
- // to support font modification to text characters.
- // italic and bold seem the only ones working at present.
- x_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
- x_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
- y_value_precision_(3), // precision for tick value labels, usually 3 will suffice.
- y_value_ioflags_(std::ios::dec), // Provides a way of controlling scientific format, etc.
- // Note that ALL the flags are set, overwriting any defaults, so std::dec is wise.
- image_border_width_(1),
- text_margin_(2.), // for axis label text, as a multiplier of the font size.
- border_margin_(10), // Prevent plot window box beginning right on edge,
- border_width_(20), // width of any border to plot window and legend box.
- // less than half the font size of label value will result in clipping.
- // plot_x1, x2, y1, 2 are set in calculate_plot_window
+ legend_height_(0), // height of legend box (pixels)
legend_left_(-1), legend_right_(-1),legend_top_(-1),legend_bottom_(-1), // Default top left of plot window.
- legend_place_(inside), // default but interacts with using plot_window
- x_min(-10), x_max(10), // so plots range from -10 to +10
- y_min(-10), y_max(10),
- x_major_interval_(2), // x stride between major ticks & value label.
- y_major_interval_(2), // y stride
- // Ticks on axes.
- x_num_minor_ticks_(4), // suits
- y_num_minor_ticks_(4), // suits: major 0, minor 2, 4, 6, 8, major 10
- x_major_tick_length_(10.), // If both up and down, total is twice this.
- x_minor_tick_length_(5.),
- x_major_tick_width_(2.),
- x_minor_tick_width_(1.),
- y_major_tick_length_(10.), // If both left and right, total is twice this.
- y_minor_tick_length_(5.),
- y_major_tick_width_(2.),
- y_minor_tick_width_(1.),
- // grids
- x_major_grid_width_(1.),
- x_minor_grid_width_(0.5),
- y_major_grid_width_(1.),
- y_minor_grid_width_(0.5),
- // Use by transform Cartesian to SVG.
- x_scale(1.), x_shift(0.),
- y_scale(1.), y_shift(0.),
- x_minor_interval_(0), // These are calculated from x & y_num_minor_ticks_
- y_minor_interval_(0), // but given a value here for safety.
- x_axis_position_(0),
- y_axis_position_(0),
- x_label_length_(0),
- y_label_length_(0),
-
- plot_window_clip("plot_window"), // for <clipPath id="plot_window" ...
-
- // Boolean options.
- strip_e0s_(false),
- use_down_ticks(true), // On X-axis.
- use_up_ticks(false), // external ticks only.
- //use_x_ticks(false), // = use_up_ticks || use_down_ticks
- use_left_ticks(true), // On y-axis.
- use_right_ticks(false), // On y-axis
- //use_y_ticks(true), // = use_left_ticks || use_right_ticks TODO get rid of this. NOT useful
- use_x_ticks_on_plot_window_(false), // was external_style
- use_y_ticks_on_plot_window_(false), // was external_style
- use_x_label_units(false),
- use_y_label_units(false),
- use_x_major_labels(true), // tick value labels.
- use_y_major_labels(true),
- use_x_label(true), // "X-axis"
- use_y_label(true), // "Y-axis" - true for 2-D, false for 1-D.
- use_title(true),
- use_legend(false),
- use_outside_legend_(true),
- use_axis(true),
- use_x_axis_lines_(true), // draw horizontal X-axis line.
- use_y_axis_lines_(true), // draw vertical Y-axis line.
- use_x_major_grid_(true),
- use_x_minor_grid_(false),
- use_y_major_grid_(true),
- use_y_minor_grid_(false),
- use_plot_window_(false),
- use_line(true)
- // TODO but needs Boost-Parameter removed to do properly.
-
+ legend_place_(outside_right), // default but interacts with using plot_window
+ legend_longest_(0),
+ plot_window_clip_("plot_window"), // for <clipPath id="plot_window" ...
+ title_on_(true),
+ legend_on_(false),
+ outside_legend_on_(true),
+ plot_window_on_(true),
+ // Used by transform Cartesian to SVG.
+ x_scale_(1.), x_shift_(0.),
+ y_scale_(1.), y_shift_(0.),
+ x_axis_position_(0), // TODO move into axis_style?
+ y_axis_position_(0) // But some problems with this.
{
image_size(500, 400); // Default image size for 2-D.
// 2-D usually needs to be squarer than 1-D.
@@ -409,51 +311,53 @@
// Set other SVG color, stroke & width defaults for various child PLOT nodes.
- // Tick length etc is now set above in the constructor, but width & color here.
- image.get_g_element(PLOT_BACKGROUND).style().fill_color(white);
- image.get_g_element(PLOT_BACKGROUND).style().stroke_color(yellow); // TODO test only ?
- image.get_g_element(PLOT_BACKGROUND).style().stroke_width(image_border_width_); //
- image.get_g_element(PLOT_WINDOW_BACKGROUND).style().fill_color(white);
- image.get_g_element(PLOT_WINDOW_BACKGROUND).style().stroke_width(1).stroke_color(yellow);
+ 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_Y_AXIS).style().stroke_color(black).stroke_width(y_axis_width_);
+ image.get_g_element(PLOT_X_AXIS).style().stroke_color(black).stroke_width(x_axis_.width());
+ image.get_g_element(PLOT_Y_AXIS).style().stroke_color(black).stroke_width(y_axis_.width());
image.get_g_element(PLOT_X_LABEL).style().fill_color(black);
image.get_g_element(PLOT_Y_LABEL).style().fill_color(black);
- image.get_g_element(PLOT_VALUE_LABELS).style().fill_color(black); // text
+ 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);
- // If stroke color is not set, then get a very 'thin' font and width has no effect.
- // Firefox text is rather thin compared to IE.
// Note that widths are stored in member data *and* copied here.
// Not sure if this is wise but ...
// Ticks
- if(use_up_ticks || use_down_ticks)
+ if(x_ticks_.use_up_ticks() || x_ticks_.use_down_ticks())
{
- image.get_g_element(PLOT_X_MAJOR_TICKS).style().stroke_width(x_major_tick_width_).stroke_color(black);
- image.get_g_element(PLOT_X_MINOR_TICKS).style().stroke_width(x_minor_tick_width_).stroke_color(black);
+ 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);
}
- if(use_left_ticks || use_right_ticks)
+ if(y_ticks_.left_ticks_on_ || y_ticks_.right_ticks_on_)
{
- image.get_g_element(PLOT_Y_MAJOR_TICKS).style().stroke_width(y_major_tick_width_).stroke_color(black);
- image.get_g_element(PLOT_Y_MINOR_TICKS).style().stroke_width(y_minor_tick_width_).stroke_color(black);
+ image.get_g_element(PLOT_Y_MAJOR_TICKS).style().stroke_width(y_ticks_.major_tick_width_).stroke_color(black);
+ image.get_g_element(PLOT_Y_MINOR_TICKS).style().stroke_width(y_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_major_grid_width_).stroke_color(svg_color(200, 220, 255));
+ 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_minor_grid_width_).stroke_color(svg_color(200, 220, 255));
- image.get_g_element(PLOT_Y_MAJOR_GRID).style().stroke_width(y_major_grid_width_).stroke_color(svg_color(200, 220, 255));
- image.get_g_element(PLOT_Y_MINOR_GRID).style().stroke_width(y_minor_grid_width_).stroke_color(svg_color(200, 220, 255));
- image.get_g_element(PLOT_DATA_LINES).style().stroke_width(2);
+ 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_Y_MAJOR_GRID).style().stroke_width(y_ticks_.major_grid_width_).stroke_color(svg_color(200, 220, 255));
+ image.get_g_element(PLOT_Y_MINOR_GRID).style().stroke_width(y_ticks_.minor_grid_width_).stroke_color(svg_color(200, 220, 255));
+ image.get_g_element(PLOT_DATA_LINES).style().stroke_width(1.);
- legend_place_ = (use_plot_window_) ? outside_right : inside; // Defaults.
+ legend_place_ = (plot_window_on_) ? outside_right : inside; // Defaults.
// Note if set plot_window_on() then also need to set legend_place.
// (if set a default in plot_window then call to set legend place must to come *after* it.
// So not set a default? But leaving it as inside is worse?)
+ //axes_on_ = x_axis_.axis_line_on_ || y_axis_.axis_line_on_;
+ x_ticks_on_ = x_ticks_.up_ticks_on_ || x_ticks_.down_ticks_on_;
+ y_ticks_on_ = y_ticks_.left_ticks_on_ || y_ticks_.right_ticks_on_;
+
+ title_info_.style().font_size(20);
} // svg_2d_plot() default constructor.
private:
@@ -467,15 +371,6 @@
}
} // void set_ids()
- //void calculate_transform() now inline in calcualte_plot_window
- //{ // Calculate scale and shift factors for transform from Cartesian to plot.
- // // SVG image is 0, 0 at top left, Cartesian at bottom left.
- // x_scale = (plot_x2 - plot_x1) / (x_max - x_min);
- // x_shift = plot_x1 - x_min *(plot_x2 - plot_x1) / (x_max - x_min);
- // y_scale = -(plot_y2-plot_y1) / (y_max-y_min);
- // y_shift = plot_y1 - (y_max * (plot_y1 - plot_y2) / (y_max - y_min));
- //} // void calculate_transform()
-
void transform_pair(std::pair<double, double>& pt)
{ // Transform both x and y from Cartesian to SVG coordinates.
// SVG image is 0, 0 at top left, Cartesian at bottom left.
@@ -486,225 +381,212 @@
// this ensures that data points and lines (and anything else)
// outside this window are NOT drawn.
// Start by assuming we can use all the svg image,
- // but reduce by width of any image border.
- plot_x1 = 0 + image_border_width_; // left
- plot_y1 = 0 + image_border_width_; // top
- plot_x2 = image.x_size() - image_border_width_; // right
- plot_y2 = image.y_size() - image_border_width_; // bottom
+ // but reduce by the width of any image border.
+ plot_left_ = 0 + image_border_width();
+ plot_top_ = 0 + image_border_width();
+ plot_right_ = image.x_size() - image_border_width();
+ plot_bottom_ = image.y_size() - image_border_width();
- if(use_title)
+ if(title_on_)
{ // Leave space at top for title.
// TODO what if want to put title at bottom?
- plot_y1 += title_font_size() * (text_margin_ + 0.5);
+ plot_top_ += title_font_size() * (text_margin_ + 0.5);
}
- size_legend_box();
- place_legend_box();
- if(use_x_label)
- { // Leave space at bottom for X axis label.
- plot_y2 -= x_label_info.font_size() * (text_margin_);
- }
- if(use_y_label)
+ size_legend_box();
+ place_legend_box();
+ if(x_axis_.label_on_)
+ { // Leave space at bottom for X axis label.
+ plot_bottom_ -= x_axis_label_style_.font_size() * (text_margin_);
+ }
+ if(y_axis_.label_on_)
{ // Leave space at left for Y axis label.
- plot_x1 += y_label_info.font_size() * (text_margin_ - 0.5);
+ plot_left_ += x_axis_label_style_.font_size() * (text_margin_ - 0.5);
}
- if(use_plot_window_)
- { // Reduce to allow for legend, axes ticks to be on or outside plot_window.
- // Give the plot window a border (set with plot_border_width(double)).
+ if(plot_window_on_)
+ { // Reduce to allow plot window border.
// Needed to allow any plot window border rectangle to show OK.
- // border_margin is to prevent it being right on the image border.
- plot_x1 += plot_border_width() + border_margin(); // pixels.
- plot_x2 -= plot_border_width() + border_margin();
- plot_y1 += plot_border_width() + border_margin();
- plot_y2 -= plot_border_width() + border_margin();
+ // margin is to prevent it being right on the image border.
+ plot_left_ += image_border_.margin_; // pixels.
+ plot_right_ -= image_border_.margin_;
+ plot_top_ += image_border_.margin_;
+ plot_bottom_ -= image_border_.margin_;
+ }
+ if(x_axis_.label_on_)
+ { // Need to avoid rightmost X-axis label running off image.
+ // Might need more if a long horizontal label?
+ plot_right_ -= text_margin_ * x_value_label_style_.font_size();
}
// Check if the axes will intersect.
- y_axis_position_ = y_intersect; // Y-axis will intersect X-axis.
- if (x_min > std::numeric_limits<double>::min())
- { // Y-axis > 0 so will not intersect X -axis, (all positive)
+ // X axis position is determined by the range of Y label values.
+ x_axis_position_ = x_intersect; // 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.
+ { // y_min_ > 0 so X-axis will not intersect Y-axis, so use bottom plot window.
+ x_axis_position_ = bottom; // X-axis to bottom of plot window.
+ x_ticks_.ticks_on_plot_window_on_ = true;
+ }
+ else if(y_axis_.max_ < -std::numeric_limits<double>::min()) // all Y values definitely < zero.
+ { // // y_max_ < 0 so X-axis will not intersect Y-axis, so use top plot window.
+ x_axis_position_ = top; // X-axis to top of plot window.
+ x_ticks_.ticks_on_plot_window_on_ = true;
+ }
+ // Y axis position is determined by the range of X values.
+ y_axis_position_ = y_intersect; // Assume Y-axis will intersect X-axis (X range includes zero).
+ if (x_axis_.min_ > std::numeric_limits<double>::min()) // X values all definitely > zero.
+ { // Y-axis > 0 so will not intersect X-axis.
y_axis_position_ = left; // Y-axis free to left of end of X-axis.
- use_y_ticks_on_plot_window_ = true;
+ y_ticks_.ticks_on_plot_window_on_ = true; // because floating off end of X-axis.
+ // so need to put the labels on the plot window instead of the X-axis.
}
- else if (y_max < -std::numeric_limits<double>::min())
- { // Y-axis < 0 so will not intersect X -axis, (all negative)
+ else if (y_axis_.max_ < -std::numeric_limits<double>::min()) // Y all definitely < zero.
+ { // Y-axis < 0 so will not intersect X-axis.
y_axis_position_ = right;
- use_y_ticks_on_plot_window_ = true;
- }
- x_axis_position_ = x_intersect; // X-axis will intersect Y-axis.
- if (y_min > std::numeric_limits<double>::min()) // all definitely > zero.
- { // y_min > 0 so X-axis will not intersect Y-axis, so use bottom plot window.
- x_axis_position_ = bottom; // X-axis to bottom.
- use_x_ticks_on_plot_window_ = true;
- }
- else if(y_max < -std::numeric_limits<double>::min()) // all definitely < zero.
- { // // y_max < 0 so X-axis will not intersect Y-axis, so use top plot window.
- x_axis_position_ = top; // X-axis to top.
- use_x_ticks_on_plot_window_ = true;
- }
-
- // Also need a >half font to allow the value label on any max major tick to avoid clipping.
- // Even after reading http://www.w3.org/TR/SVG/fonts.html, unclear how to
- // determine the width of digits, so an arbitrary average width height ratio wh is used:
-
- // We would really like to know the length of the longest value label here!
- // Might convert the max and then use its .length()?
- int chars = (y_value_precision_ + 1 + 1); // sign & decimal point.
- if((y_value_ioflags_ & std::ios::scientific) == std::ios::scientific)
- { // precision is number of decimal places in the fractional part (default 6).
- chars += 5; // Also need space for e, sign & 3 exponent digits = 5)
- }
- else if((y_value_ioflags_ & std::ios::fixed) == std::ios::fixed)
- { // precision is
- chars += 2; // Need space for decimal point & at least 1 more digit)
- }
- else
- { // Default neither fixed nor scientific, no leading or trailing zero(s).
- // allowing sign and decimal point should probably be enough,
- // but only a check of the actual values will be accurate. TODO?
+ y_ticks_.ticks_on_plot_window_on_ = true;
}
- y_label_length_ = 0; // SVG units.
- if (y_label_rotation_ == horizontal)
+
+ // Calculate the lengths of the longest value labels.
+ x_ticks_.longest_label();
+ y_ticks_.longest_label();
+
+ //std::cout << "label_max_chars_() " << x_ticks_.label_max_chars_ << std::endl; // label_max_chars_ 3
+ //std::cout << "label_max_chars_() " << y_ticks_.label_max_chars_ << std::endl;
+
+ // Check that labels won't collide and advise if they will.
+ // Change rotation to avoid collision?
+
+ double y_label_length_ = 0.; // SVG units.
+ if (y_ticks_.label_rotation_ == horizontal)
{ // Move edge right to give space for y_value_precision_ digits.
- y_label_length_ += y_label_value.font_size() * (chars * wh_);
+ y_label_length_ += y_axis_label_style_.font_size() * y_ticks_.label_max_chars_ * wh; // SVG units
}
- else if((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
+ else if((y_ticks_.label_rotation_ == upward) || (y_ticks_.label_rotation_ == downward))
{ // Only need one char width from Y-axis label.
- y_label_length_ += y_label_value.font_size() * 1.5;
+ y_label_length_ += y_value_label_style_.font_size() * 1.5;
}
else
{ // Assume some slope 45, so diagonally down from tick,
// and takes a bit less room.
- y_label_length_ = y_label_value.font_size() * chars * wh_ * sin45;
+ y_label_length_ = y_value_label_style_.font_size() * y_ticks_.label_max_chars_ * wh * sin45;
}
- if (use_y_major_labels && (y_axis_position_ != right) )
+ if (y_ticks_.major_value_labels_on && (y_axis_position_ != right) )
{
- //if (abs(x_min/(x_max - x_min)) < 0.05) // < 5% of range.
- // // Y-axis is too close to the axis label.
+ // TODO sort out this unusual case of Y-axis line too close to the axis label.
+ //if (abs(x_min_/(x_max_ - x_min_)) < 0.05) // < 5% of range?
// // Want to do this:
- // //((y_axis - plot_x1) < (y_label_length_ - y_major_tick_width_)) )
- // // needs to calculate transform to get into SVG units, but this is changing plot_x1 !!
+ // //((y_axis_ - plot_left_) < (y_label_length_ - y_major_tick_width_)) )
+ // // needs to calculate transform to get into SVG units, but this is changing plot_left_ !!
//{ // force onto plot window. BUT this only looks right if plot window is on.
- // // because makr ticks and label are on the plot window
+ // // because major ticks and label are on the plot window
// use_y_ticks_on_plot_window_ = true;
//}
- //if (use_y_ticks_on_plot_window_) // on plot window
+ if (y_ticks_.ticks_on_plot_window_on_)
{ // Move plot window right to make space for value labels,
- plot_x1 += y_label_length_;
+ plot_left_ += y_label_length_;
}
}
- if (use_x_major_labels && (use_x_ticks_on_plot_window_ || (x_axis_position_ != top) ))
+ if (x_ticks_.major_value_labels_on && (x_ticks_.ticks_on_plot_window_on_ || (x_axis_position_ != top) ))
{ // Move bottom of plot window up to give space for x value labels.
- // x_value_precision_ digits etc.
- double l = x_value_precision_ + 1 + 1; // sign & decimal point.
- if(x_label_rotation_ == horizontal)
- { // Only 1 char height & 1 space needed if horizontal.
- l = 2;
+ double x_label_length_ = 0;
+ if(x_ticks_.label_rotation_ == horizontal)
+ { // Only 1 char height & 1 space needed if labels are horizontal.
+ x_label_length_ = 2; // SVG chars
}
else
- { // will need more than 2
- //l += 1; // extra space at top and bottom?
- if ((x_value_ioflags_ & std::ios::scientific) == std::ios::scientific)
- { // space for "e+000"
- l += 5;
- }
- else if((x_value_ioflags_ & std::ios::fixed) == std::ios::fixed)
- { // Need space for decimal point & sign & at least 1 more digit)
- l += 3;
- }
- if ((x_label_rotation_ == upward) || (x_label_rotation_ == downward))
+ { // ! horizontal so will need more than 2
+ if ((x_ticks_.label_rotation_ == upward) || (x_ticks_.label_rotation_ == downward))
{ // Need space for longest.
+ x_label_length_+= x_ticks_.label_max_chars_ * wh; // SVG chars.
}
else
- { // Assume some slope, say 45, so * sin(45) = 0.707.
- l *= sin45;
+ { // Assume label is sloping, say 45, so * sin(45) = 0.707.
+ x_label_length_+= x_ticks_.label_max_chars_ * wh * sin45; // SVG 'chars'.
}
}
- plot_y2 -= x_label_value.font_size() * l * wh_; // Move up.
+ x_label_length_ *= x_value_label_style_.font_size(); // Total length in SVG.
+ plot_bottom_ -= x_label_length_; // Move up.
}
- if(use_left_ticks)
+ if(y_ticks_.left_ticks_on_)
{ // Start left of plot to right to give space for biggest of any external left ticks.
- plot_x1 += (std::max)(y_major_tick_length_, y_minor_tick_length_); // Avoid macro max trap!
+ plot_left_ += (std::max)(y_ticks_.major_tick_length_, y_ticks_.minor_tick_length_); // Avoid macro max trap!
}
- if(use_down_ticks)
+ if(x_ticks_.down_ticks_on_)
{ // Start bottom of plot higher to give space for any external down ticks.
- plot_y2 -= (std::max)(x_major_tick_length_, x_minor_tick_length_);
+ plot_bottom_ -= (std::max)(x_ticks_.major_tick_length_, x_ticks_.minor_tick_length_);// Avoid macro max trap!
}
-
- if (use_x_axis_lines_)
- { // Want a X-axis line, so check if range include zero, so axes intersect,
- // and x_axis is svg coordinate of Y-axis (usually y = 0).
+ if (x_axis_.axis_line_on_)
+ { // Want a 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
- // and leave space (and quiggle between) to show this.
+ // and leave space (and squiggle between) to show this?
if (x_axis_position_ == bottom) // All definitely > zero.
- { // y_min > 0 so X-axis will not intersect Y-axis, so use plot window.
- x_axis = plot_y2; // X-axis to bottom,
- //plot_y2 -= 2 * y_label_info.font_size(); // with a space.
+ { // y_min_ > 0 so X-axis will not intersect Y-axis, so use plot window.
+ x_axis_.axis_ = plot_bottom_; // X-axis to bottom,
+ //plot_bottom_ -= 2 * y_label_info_.font_size(); // with a space.
}
else if(x_axis_position_ == top) // definitely < zero.
- { // // y_max < 0 so X-axis will not intersect Y-axis, so use plot window.
- x_axis = plot_y1; // X-axis to top,
- //plot_y1 += 2 * y_label_info.font_size(); // with a space.
+ { // // y_max_ < 0 so X-axis will not intersect Y-axis, so use plot window.
+ x_axis_.axis_ = plot_top_; // X-axis to top,
+ //plot_top_ += 2 * y_label_info_.font_size(); // with a space.
}
else
{ // y_axis_position_ == y_intersect
// Calculate below after transform is calculated.
}
- } // if (use_x_axis_)
+ } // if (use_x_axis_line_)
- if (use_y_axis_lines_)
- { // Want a Y-axis line, so check if range include zero, so axes intersect,
- // and y_axis is svg coordinate of X-axis (usually x = 0).
+ 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 leave space (and quiggle between) to show this.
+ // and leave space (and squiggle 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.
- y_axis = plot_x1; // Y-axis to left,
- //plot_x1 += 2 * y_label_info.font_size(); // with a space.
+ 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)
{
- y_axis = plot_x2; // Y-axis to right of plot window,
- //plot_x2 -= 2 * y_label_info.font_size(); // with a space.
+ y_axis_.axis_ = plot_right_; // Y-axis to right of plot window,
+ //plot_right_ -= 2 * y_label_info_.font_size(); // with a space.
}
else
{ // x_axis_position_ == x_intersect
// Calculate below after transform is calculated.
}
- } // if (use_y_axis_)
-
+ } // if (use_y_axis_line_)
// 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_x2 - plot_x1) / (x_max - x_min);
- x_shift = plot_x1 - x_min *(plot_x2 - plot_x1) / (x_max - x_min);
- y_scale = -(plot_y2-plot_y1) / (y_max-y_min);
- y_shift = plot_y1 - (y_max * (plot_y1 - plot_y2) / (y_max - y_min));
+ 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_);
+ 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_));
- if (use_x_axis_lines_)
+ if (x_axis_.axis_line_on_)
{
if(x_axis_position_ == x_intersect)
- { // Y Range *does* include zero, so x_axis not yet calculated.
+ { // Y Range *does* include zero, so x_axis_ not yet calculated.
double y(0.); // Use y = 0
transform_y(y);
- x_axis = y; // svg Y coordinate of horizontal X-axis line.
+ x_axis_.axis_ = y; // svg Y coordinate of horizontal X-axis line.
}
}
- if (use_y_axis_lines_)
+ if (y_axis_.axis_line_on_)
{ // May need to calculate axes, if will intersect.
if(y_axis_position_ == y_intersect)
- { // X Range *does* include zero, so y_axis not yet calculated.
+ { // X Range *does* include zero, so y_axis_ not yet calculated.
double x(0.);
transform_x(x);
- y_axis = x; // SVG x coordinate of vertical Y-axis.
+ y_axis_.axis_ = x; // SVG x coordinate of vertical Y-axis.
}
}
- if (use_plot_window_)
- { // Draw plot window rectangle with background and/or border.
+ if (plot_window_on_)
+ { // Draw plot window rectangle with border and/or background.
image.get_g_element(detail::PLOT_WINDOW_BACKGROUND).push_back(
- new rect_element(plot_x1, plot_y1, (plot_x2 - plot_x1), plot_y2 - plot_y1));
+ new rect_element(plot_left_, plot_top_, (plot_right_ - plot_left_), plot_bottom_ - plot_top_));
}
} // calculate_plot_window
@@ -712,17 +594,17 @@
void draw_y_axis()
{
double x;
- x = y_axis; // Y-axis (x = 0) transformed into X SVG coordinates.
+ x = y_axis_.axis_; // Y-axis (x = 0) transformed into X SVG coordinates.
// Perhaps shifted to left or right if origin is missing.
- if(use_y_axis_lines_)
+ if(y_axis_.axis_line_on_)
{ // Draw the vertical Y-axis line (at cartesian x = 0).
- double ybottom = plot_y2;
- if (use_down_ticks && use_y_ticks_on_plot_window_ && (x_axis_position_ == x_intersect) )
+ double ybottom = plot_bottom_;
+ if (x_ticks_.down_ticks_on_ && y_ticks_.ticks_on_plot_window_on_ && (x_axis_position_ == x_intersect) )
{ // Extend the vertical line down in lieu of a tick.
- ybottom += (std::max)(x_minor_tick_length_, x_major_tick_length_);
+ ybottom += (std::max)(x_ticks_.minor_tick_length_, x_ticks_.major_tick_length_);// Avoid macro max trap!
}
- image.get_g_element(detail::PLOT_Y_AXIS).line(x, plot_y1, x, ybottom);
+ image.get_g_element(detail::PLOT_Y_AXIS).line(x, plot_top_, x, ybottom);
// <g id="yAxis" stroke="rgb(0,0,0)"><line x1="70.5" y1="53" x2="70.5" y2="357"/>
}
// Access the paths for the ticks & grids, ready for additions.
@@ -731,23 +613,23 @@
path_element& minor_grid_path = image.get_g_element(detail::PLOT_Y_MINOR_GRID).path();
path_element& major_grid_path = image.get_g_element(detail::PLOT_Y_MAJOR_GRID).path();
- if(use_y_ticks_on_plot_window_)
+ if(y_ticks_.ticks_on_plot_window_on_)
{ // TODO ensure that labels allow space. - they don't at present.
// Was y_external style - so both labels and ticks are OUTSIDE the plot window.
//
}
// y_minor_jump is the interval between minor ticks.
- double y_minor_jump = y_major_interval_ / ((double)(y_num_minor_ticks_ + 1.) );
+ double y_minor_jump = y_ticks_.major_interval_ / ((double)(y_ticks_.num_minor_ticks_ + 1.) );
// TODO Problem here with using floating point?
- // Was i < y_max; but didn't show the tick and value at y_max so now i <= y_max;
+ // Was i < y_max_; but didn't show the tick and value at y_max_ so now i <= y_max_;
// But may still fail if a ls or few bits out? Seems to fail for y = 100, for example.
// Draw the ticks on the positive side.
- for(double y = 0; y <= y_max; y += y_major_interval_)
+ for(double y = 0; y <= y_axis_.max_; y += y_ticks_.major_interval_)
{
for(double j = y + y_minor_jump;
- j < (y + y_major_interval_) * (1. - 2 * std::numeric_limits<double>::epsilon());
+ j < (y + y_ticks_.major_interval_) * (1. - 2 * std::numeric_limits<double>::epsilon());
j += y_minor_jump)
{ // Draw minor ticks.
// This will output 'orphaned' minor ticks that are beyond the plot window,
@@ -756,13 +638,13 @@
// There might be 9 of them,
// if you have the common 9 minor tick between major ticks!
// TODO this seems ugly - as does the negative ones below.
- if (j != 0. || ! use_x_axis_lines_)
+ if (j != 0. || ! x_axis_.axis_line_on_)
{ // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
// (won't be X-axis line for 1-D where the zero tick is always wanted).
draw_y_minor_ticks(j, minor_tick_path, minor_grid_path);
}
}
- if ((y != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
+ if ((y != 0. || ! x_axis_.axis_line_on_) || y_ticks_.ticks_on_plot_window_on_)
{ // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
// (won't be X-axis line for 1-D where the zero tick is always wanted).
draw_y_major_ticks(y, major_tick_path, major_grid_path);
@@ -770,17 +652,17 @@
}
// Draw the ticks on the negative side.
- for(double y = 0; y >= y_min; y -= y_major_interval_)
+ for(double y = 0; y >= y_axis_.min_; y -= y_ticks_.major_interval_)
{
- for(double j=y; j > y-y_major_interval_; j-= y_major_interval_ / (y_num_minor_ticks_ + 1))
+ for(double j = y; j > y - y_ticks_.major_interval_; j-= y_ticks_.major_interval_ / (y_ticks_.num_minor_ticks_ + 1))
{ // Draw minor ticks.
- if ((j != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
+ if ((j != 0. || ! y_axis_.axis_line_on_) || y_ticks_.ticks_on_plot_window_on_)
{ // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
// (won't be X-axis line for 1-D where the zero tick is always wanted).
draw_y_minor_ticks(j, minor_tick_path, minor_grid_path);
}
}
- if ((y != 0. || ! use_x_axis_lines_) || use_y_ticks_on_plot_window_)
+ if ((y != 0. || ! x_axis_.axis_line_on_) || y_ticks_.ticks_on_plot_window_on_)
{ // Avoid a major tick at y == 0 where there *is* a horizontal X-axis line.
// (won't be X-axis line for 1-D where the zero tick is always wanted).
draw_y_major_ticks(y, major_tick_path, major_grid_path);
@@ -789,79 +671,70 @@
} // draw_y_axis
void draw_y_label()
- {
- // image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_color(black);
- // Now set in constructor, and can be changed with member function .
-
- std::string label = y_label_info.text(); // x_axis label, and optional units.
- if (use_x_label_units && (y_units_info.text() != ""))
- { // Append the units, if any, providing brackets ().
- // TODO Is this the best policy - or should the user provide the ()s????
- label += " (" + y_units_info.text() + ")";
+ { // Draw vertical y_axis_ label, and optional units.
+ std::string label = y_label_info_.text();
+ if (x_ticks_.label_units_on_ && (y_units_info_.text() != ""))
+ { // Append the units, user must provide any ()s, if wanted.
+ label += y_units_info_.text() ;
}
+ double y = image_border_.width_ + image_border_.margin_ + y_axis_label_style_.font_size();
image.get_g_element(detail::PLOT_Y_LABEL).push_back(new
- text_element(y_label_info.font_size() * 1.5,
+ text_element(y,
// shift over one char height to right from left edge of image.
- (plot_y2 + plot_y1) / 2., // center on the plot window.
+ (plot_bottom_ + plot_top_) / 2., // center on the plot window.
label, // "Y-Axis" for example.
- y_label_info.font_size(),
- y_label_info.font_family(),
- "", "", "", "",
+ y_axis_label_style_,
center_align, // One might want it to left or right_align?
upward)); // Y label must be drawn vertically.
} // draw_y_label
void draw_y_major_ticks(double value, path_element& tick_path, path_element& grid_path)
{ // Draw Y axis major ticks, tick value labels & grids.
- double y1(value);
- transform_y(y1); // cartesian to SVG coordinates.
- double x1(0.); // left end of tick.
+ double y1(value); // for tick and/or grid.
+ transform_y(y1); // Cartesian to SVG coordinates.
+ double x1(0.); // Left end of tick.
double x2(image.y_size()); // right end of tick.
- if(use_y_major_grid_)
+ if(y_ticks_.major_grid_on_)
{ // Draw horizontal major grid line.
- if(!use_plot_window_)
+ if(!plot_window_on_)
{ // TODO is this right?
- //if (use_title())
- //{ // title has no effect if at the top.
- // y1 += title_info.font_size() * text_margin_;
- //}
- if(use_y_label)
+ if(y_ticks_.major_value_labels_on)
{ // Start further right to give space for y axis value label.
- y1 -= y_label_value.font_size() * text_margin_ ;
+ y1 -= y_value_label_style_.font_size() * text_margin_;
}
- if(use_left_ticks)
+ if(y_ticks_.left_ticks_on_)
{ // And similarly for left ticks.
- y1 -= y_major_tick_length_;
+ y1 -= y_ticks_.major_tick_length_;
}
}
else
- { // Do use_plot_window.
- x1 = plot_x1 + 1;
- x2 = plot_x2 - 1;
+ { // plot_window_on_ to use full width of plot window.
+ x1 = plot_left_ + plot_window_border_.width_; // Don't write over border.
+ x2 = plot_right_ - plot_window_border_.width_;
}
- grid_path.M(x1, y1).L(x2, y1);
+ grid_path.M(x1, y1).L(x2, y1); // horizontal line.
} // use_y_major_grid_
- if((y1 <= plot_y2) && (y1 >= plot_y1))
+ if((y1 <= plot_bottom_) && (y1 >= plot_top_))
{ // Make sure that we are drawing inside the allowed window.
- double y_tick_length = y_major_tick_length_;
- if(use_y_ticks_on_plot_window_) // (was external_style)
+ double y_tick_length = y_ticks_.major_tick_length_;
+ if(y_ticks_.ticks_on_plot_window_on_) // (was external_style)
{ // Start ticks on the plot window border.
- x1 = plot_x1; // x1 = left,
- x2 = plot_x1; // x2 = right.
+ x1 = plot_left_; // x1 = left,
+ x2 = plot_left_; // x2 = right.
}
else
{ // Internal style ticks on vertical Y-axis.
- x1 = y_axis; // Y-axis line.
- x2 = y_axis;
+ x1 = y_axis_.axis_; // Y-axis line.
+ x2 = y_axis_.axis_;
}
- if(use_left_ticks)
+ if(y_ticks_.left_ticks_on_)
{
x1 -= y_tick_length; // left
}
- if (use_right_ticks)
+ if (y_ticks_.right_ticks_on_)
{
x2 += y_tick_length; // right.
}
@@ -869,20 +742,18 @@
// leaving x1 at the left most end of any tick.
}
- if(use_y_major_labels)
+ if(y_ticks_.major_value_labels_on)
{ // Label the tick with value, for example "1.2"
std::stringstream label;
- label.precision(y_value_precision_);
- label.flags(y_value_ioflags_); // set ALL IOflags.
+ label.precision(y_ticks_.value_precision_);
+ label.flags(y_ticks_.value_ioflags_); // set ALL IOflags.
label << value; // Example: label.str() == "20" or "0.25" or "1.2e+015"
- if(use_left_ticks)
+ if(y_ticks_.left_ticks_on_)
{
- if (y_minor_tick_length_ > y_minor_tick_length_)
- { // In case some joker has made the minor ticks longer than the major,
+ // In case some joker has made the minor ticks longer than the major,
// we might need to move left more for the longer tick.
- x1 -= (y_minor_tick_length_ - y_minor_tick_length_);
- }
- x1 -= y_label_value.font_size(); // move left by a font width.
+ x1 -= (std::max)(y_ticks_.major_tick_length_, y_ticks_.minor_tick_length_);// Avoid macro max trap!
+ // x1 -= y_value_label_style_.font_size() * wh; // move left by a font width.
}
else
{ // No need to move if right tick, or none.
@@ -890,42 +761,43 @@
// Need to work out how much space value labels will need.
double y = y1;
align_style alignment = center_align;
- if(use_y_ticks_on_plot_window_)
+ if(y_ticks_.ticks_on_plot_window_on_)
{ // External to plot window style.
- if(y_label_rotation_ == horizontal)
+ if(y_ticks_.label_rotation_ == horizontal)
{ // Just shift down half a digit to center value digits on tick.
alignment = right_align;
- y += y_label_value.font_size() / 2;
+ y += y_value_label_style_.font_size() / 2;
}
- else if ((y_label_rotation_ == upward) || (y_label_rotation_ == downward))
+ else if ((y_ticks_.label_rotation_ == upward) || (y_ticks_.label_rotation_ == downward))
{// Tick value label straight up or down vertically on y axis.
// No shift y down to center.
alignment = center_align;
}
else
{ // Assume some 45 slope, so need about sqrt(2) less space?
- x1 += y_label_value.font_size() * 0.5; // move left by half a font width.
+ x1 += y_value_label_style_.font_size() * 0.5; // move left by half a font width.
// no y shift needed.
alignment = right_align;
}
// Always want all values including "0", if labeling external to plot window.
- // use_ticks_on_plot_window_ == true
+ // ticks_on_plot_window_on_ == true
image.get_g_element(detail::PLOT_VALUE_LABELS).text(
x1,
y,
- label.str(), y_label_value.font_size(), "", "", "", "", "", alignment, y_label_rotation_);
+ label.str(), y_value_label_style_, alignment, y_ticks_.label_rotation_);
}
else
{ // ! use_y_ticks_on_plot_window_ == Internal - value labels close to left of vertical Y-axis.
- if ((value != 0) && use_x_axis_lines_)
+ if ((value != 0) && y_axis_.axis_line_on_)
{ // Avoid a zero ON the Y-axis if it would be cut through by any horizontal X-axis line.
- y += y_label_value.font_size() / 2;
+ y += y_value_label_style_.font_size() / 2;
image.get_g_element(detail::PLOT_VALUE_LABELS).text(
x1 ,
y, // Just shift down half a digit to center value digits on tick.
- label.str(), y_label_value.font_size(), y_label_value.font_family(), "", "", "", "",
+ label.str(),
+ y_value_label_style_,
alignment, // on the tick ???
- y_label_rotation_);
+ y_ticks_.label_rotation_);
}
}
} // if(use_y_major_labels)
@@ -934,63 +806,60 @@
void draw_y_minor_ticks(double value, path_element& tick_path, path_element& grid_path)
{
double x1(0.);
- double y1(value); // for tick position and value label.
- transform_y(y1);
+ double y(value); // tick position and value label.
+ transform_y(y); // to svg.
double x2(image.y_size()); // right edge of image.
- if(use_y_minor_grid_)
+ if(y_ticks_.minor_grid_on_)
{ // Draw the minor grid, if wanted.
- if(!use_plot_window_)
- { // Use whole image, but make space for title & labels text.
- //if(use_title)
- //{ // If title at top, should make no difference, unlike X grid.
- // x2 -= title_info.font_size() * text_margin_;
- //}
- if(use_y_label)
+ if(!plot_window_on_)
+ { // TODO now wrong?????
+ if(x_axis_.label_on_)
{
- x1 += y_label_info.font_size() * text_margin_;
- x2 -= y_label_info.font_size() * text_margin_;
+ x1 += y_value_label_style_.font_size() * text_margin_;
+ x2 -= y_value_label_style_.font_size() * text_margin_;
}
}
else
- { // Use plot window.
- x1 = plot_x1 + 1; // TODO what is the +1 for?
- x2 = plot_x2 - 1; // Ensure *inside* window?
- }
- if((y1 >= plot_y1) && (x1 >= plot_x1) && (x2 <= plot_x2) )
- { // // Make sure that we are drawing inside the allowed window.
- grid_path.M(x1, y1).L(x2, y1);
+ { // plot_window_on_
+ x1 = plot_left_ + plot_window_border_.width_;
+ x2 = plot_right_ - plot_window_border_.width_; // Ensure just *inside* window?
+ }
+ if((y >= plot_top_) && (y <= plot_bottom_) && (x1 >= plot_left_) && (x2 <= plot_right_) )
+ { // Make sure that we are drawing inside the allowed window.
+ // Note comparisons are 'upside-down' - y is increasing downwards!
+ grid_path.M(x1, y).L(x2, y);
}
// TODO else just ignore outside plot window?
}
- if(use_y_ticks_on_plot_window_)
+ if(y_ticks_.ticks_on_plot_window_on_)
{ // Put y minor ticks on the plot window border. External style.
- x1 = plot_x1; // On the plot window border.
- x2 = plot_x1;
+ x1 = plot_left_; // On the plot window border.
+ x2 = plot_left_;
}
else
{ // Internal style.
- x1 = y_axis; // On the Y-axis line.
- x2 = y_axis;
+ x1 = y_axis_.axis_; // On the Y-axis line.
+ x2 = y_axis_.axis_;
}
- if(use_left_ticks)
+ if(y_ticks_.left_ticks_on_)
{
- x1 -= y_minor_tick_length_;
+ x1 -= y_ticks_.minor_tick_length_;
}
- if(use_right_ticks)
+ if(y_ticks_.right_ticks_on_)
{
- x2 += y_minor_tick_length_;
+ x2 += y_ticks_.minor_tick_length_;
}
- //if((x1 >= plot_x1) && (x2 <= plot_x2) && (y1 <= plot_y2) && (y1 >= plot_y1))
+ //if((x1 >= plot_left_) && (x2 <= plot_right_) && (y <= plot_bottom_) && (y >= plot_top_))
// but can never be inside if left tick!
- if((y1 <= plot_y2) && (y1 >= plot_y1))
+ if((y <= plot_bottom_) && (y >= plot_top_))
{ // Make sure that we are drawing inside of the allowed plot window.
- tick_path.M(x1, y1).L(x2, y1); // Draw the tick.
+ tick_path.M(x1, y).L(x2, y); // Draw the tick.
}
else
{// Do nothing? warn?
- // std::cout << "y minor tick OUTside " << x1 << ' ' << y1 << ' ' << x2 << std::endl;
+ // std::cout << "y minor tick OUTside " << x1 << ' ' << y << ' ' << x2 << std::endl;
}
} // void draw_y_minor_ticks
@@ -1003,13 +872,13 @@
double temp_y;
g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_LINES).add_g_element();
- g_ptr.clip_id(plot_window_clip);
- g_ptr.style().stroke_color(series.line_style.color);
- g_ptr.style().fill_color(series.line_style.area_fill);
+ g_ptr.clip_id(plot_window_clip_);
+ g_ptr.style().stroke_color(series.line_style_.color_);
+ g_ptr.style().fill_color(series.line_style_.area_fill_);
path_element& path = g_ptr.path();
- path.style().fill_color(series.line_style.area_fill);
+ path.style().fill_color(series.line_style_.area_fill_);
- bool is_fill = !series.line_style.area_fill.blank;
+ bool is_fill = !series.line_style_.area_fill_.blank;
path.fill = is_fill; // Ensure includes a fill="none".
if(series.series.size() > 1)
@@ -1024,13 +893,13 @@
transform_point(prev_x, prev_y);
if(is_fill)
{ // Move to 1st point.
- path.style().fill_color(series.line_style.area_fill);
+ path.style().fill_color(series.line_style_.area_fill_);
path.M(prev_x, prev_y);
}
transform_y(prev_y = (*j).second);
if(is_fill)
{ // fill wanted.
- path.style().fill_color(series.line_style.area_fill); // TOD why again?
+ path.style().fill_color(series.line_style_.area_fill_); // TODO why again?
path.L(prev_x, prev_y); // Line from X-axis to 1st point.
}
else
@@ -1065,8 +934,8 @@
void draw_bezier_lines(const svg_2d_plot_series& series)
{
g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_LINES).add_g_element();
- g_ptr.clip_id(plot_window_clip);
- g_ptr.style().stroke_color(series.line_style.color);
+ g_ptr.clip_id(plot_window_clip_);
+ g_ptr.style().stroke_color(series.line_style_.color_);
path_element& path = g_ptr.path();
std::pair<double, double> n; // current point.
@@ -1075,14 +944,14 @@
std::pair<double, double> fwd_vtr;
std::pair<double, double> back_vtr;
- bool is_fill = !series.line_style.area_fill.blank;
+ bool is_fill = !series.line_style_.area_fill_.blank;
if(is_fill == false)
{
path.fill = false; // default path constructor is true - TODO why??
}
else
{ // fill
- path.style().fill_color(series.line_style.area_fill);
+ path.style().fill_color(series.line_style_.area_fill_);
}
if(series.series.size() > 2)
@@ -1142,7 +1011,7 @@
{ // Draw line through data series, Bezier curved or straight.
for(unsigned int i = 0; i < series.size(); ++i)
{
- if(series[i].line_style.bezier_on)
+ if(series[i].line_style_.bezier_on_)
{ // curved.
draw_bezier_lines(series[i]);
}
@@ -1171,28 +1040,25 @@
// thus the minor adjustments.
// TODO should this be border thickness?
- image.clip_path(rect_element(plot_x1 + 1, plot_y1 + 1,
- plot_x2 - plot_x1 - 2, plot_y2 - plot_y1 - 2),
- plot_window_clip);
+ image.clip_path(rect_element(plot_left_ + 1, plot_top_ + 1,
+ plot_right_ - plot_left_ - 2, plot_bottom_ - plot_top_ - 2),
+ plot_window_clip_);
// <clipPath id="plot_window"><rect x="35" y="38" width="309" height="322"/></clipPath>
- image.get_g_element(detail::PLOT_DATA_POINTS).clip_id(plot_window_clip);
+ image.get_g_element(detail::PLOT_DATA_POINTS).clip_id(plot_window_clip_);
// Draw axes, labels & legend, as required.
- if(use_axis)
- {
- draw_x_axis(); // Must do X-axis first.
- draw_y_axis(); // TODO is draw_axes used?
- }
- if(use_legend)
+ draw_x_axis(); // Must do X-axis first.
+ draw_y_axis(); // TODO is draw_axes used?
+ if(legend_on_)
{
draw_legend();
}
- if(use_x_label)
+ if(x_axis_.label_on_)
{
draw_x_label();
}
- if(use_y_label)
+ if(y_axis_.label_on_)
{
draw_y_label();
}
@@ -1207,8 +1073,8 @@
g_element& g_ptr = image.get_g_element(detail::PLOT_DATA_POINTS).add_g_element();
g_ptr.style()
- .fill_color(series[i].point_style.fill_color_)
- .stroke_color(series[i].point_style.stroke_color_);
+ .fill_color(series[i].point_style_.fill_color_)
+ .stroke_color(series[i].point_style_.stroke_color_);
for(std::multimap<double, double>::const_iterator j = series[i].series.begin();
j != series[i].series.end(); ++j)
@@ -1216,9 +1082,9 @@
x = j->first;
y = j->second;
transform_point(x, y);
- if((x > plot_x1) && (x < plot_x2) && (y > plot_y1) && (y < plot_y2))
+ if((x > plot_left_) && (x < plot_right_) && (y > plot_top_) && (y < plot_bottom_))
{ // Onside plot window, so draw a point.
- draw_plot_point(x, y, g_ptr, series[i].point_style);
+ draw_plot_point(x, y, g_ptr, series[i].point_style_);
}
} // for
} // for normal points
@@ -1234,8 +1100,8 @@
x = j->first;
y = j->second;
transform_point(x, y);
- draw_plot_point(x, y, g_ptr, plot_point_style(blank, blank, series[i].point_style.size_, cone));
- // TODO why are fill and stroke blank? How is point style for 'bad' values determined?
+ // draw_plot_point(x, y, g_ptr, plot_point_style(blank, blank, s, cone));
+ draw_plot_point(x, y, g_ptr, series[i].limit_point_style_);
}
} // limits point
} // void update_image()
@@ -1268,54 +1134,75 @@
return *this;
}
- // Member functions to set plot options.
+ // Member functions to set and get plot options.
// All return *this to permit chaining.
// These below only refer to 2D plot.
// See axis_plot_label.hpp for all the many 1D functions X-Axis.
+
+ axis_line_style& x_axis()
+ {
+ return x_axis_;
+ }
+
+ axis_line_style& y_axis()
+ {
+ return y_axis_;
+ }
+
+ ticks_labels_style& x_ticks()
+ {
+ return x_ticks_;
+ }
+
+ ticks_labels_style& y_ticks()
+ {
+ return y_ticks_;
+ }
+
svg_2d_plot& y_label_on(bool cmd)
{ // Y axis name or label.
- use_y_label = cmd;
- return *this;
+ y_axis_.label_on_ = cmd;
+ return *this; // Make chainable.
}
bool y_label_on()
{
- return use_y_label;
+ return y_axis_.label_on_;
}
svg_2d_plot& x_label_on(bool cmd)
{
- use_x_label = cmd;
+ x_axis_.label_on_ = cmd;
return *this;
}
bool x_label_on()
{
- return use_x_label;
+ return x_axis_.label_on_;
}
svg_2d_plot& y_major_labels_on(bool cmd)
{
- use_y_major_labels = cmd;
+ y_ticks_.major_value_labels_on = cmd;
return *this;
}
bool y_major_labels_on()
{
- return use_y_major_labels;
+ return y_ticks_.major_value_labels_on;
}
- svg_2d_plot& y_major_label_rotation(int rot)
+ svg_2d_plot& y_major_label_rotation(rotate_style rot)
{
- y_label_rotation_ = rot;
+ y_ticks_.label_rotation_ = rot;
return *this;
}
int y_major_label_rotation()
{
- return y_label_rotation_;
+ return y_ticks_.label_rotation_ ;
}
svg_2d_plot& y_axis_width(double width)
@@ -1331,24 +1218,24 @@
svg_2d_plot& y_value_precision(int digits)
{ // Precision of Y tick label values in decimal digits (default 3).
- y_value_precision_ = digits;
+ y_ticks_.value_precision_ = digits;
return *this;
}
int y_value_precision()
{ // Precision of Y tick label values in decimal digits (default 3).
- return y_value_precision_;
+ return y_ticks_.value_precision_;
}
svg_2d_plot& y_value_ioflags(int flags)
{ // IO flags of Y tick label values (default 0X201).
- y_value_ioflags_ = flags;
+ y_ticks_.value_ioflags_ = flags;
return *this;
}
int y_value_ioflags()
{ // ALL stream ioflags for control of format of Y value labels.
- return y_value_ioflags_;
+ return y_ticks_.value_ioflags_;
}
svg_2d_plot& y_axis_color(const svg_color& col)
@@ -1363,8 +1250,7 @@
}
svg_2d_plot& y_axis_label_color(const svg_color& col)
- { // Set BOTH stroke and fill to the same color.
- image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
+ { // Set stroke color.
image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
return *this;
}
@@ -1376,29 +1262,28 @@
svg_2d_plot& y_label_units_on(bool b)
{
- use_y_label_units = b;
+ y_axis_.label_units_on_ = b;
return *this;
}
bool y_label_units_on()
{ // But only return the stroke color.
- return use_y_label_units;
+ return y_axis_.label_units_on_;
}
svg_2d_plot& y_axis_value_color(const svg_color& col)
- { // Set BOTH stroke and fill to the same color. TODO only stroke color?
- image.get_g_element(detail::PLOT_VALUE_LABELS).style().fill_color(col);
+ {
image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color(col);
return *this;
}
svg_color y_axis_value_color()
- { // But only return the stroke color.
+ { // Only return the stroke color.
return image.get_g_element(detail::PLOT_VALUE_LABELS).style().stroke_color();
}
svg_2d_plot& y_label_width(double width)
- { // width of text is effectively the boldness
+ {
image.get_g_element(detail::PLOT_Y_LABEL).style().stroke_width(width);
return *this;
}
@@ -1414,7 +1299,7 @@
return *this;
}
- const svg_color& y_major_grid_color()
+ const svg_color y_major_grid_color()
{
return image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_color();
}
@@ -1425,7 +1310,7 @@
return *this;
}
- const svg_color& y_minor_grid_color()
+ const svg_color y_minor_grid_color()
{
return image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_color();
}
@@ -1436,7 +1321,7 @@
return *this;
}
- const svg_color& y_major_tick_color()
+ const svg_color y_major_tick_color()
{
return image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_color();
}
@@ -1447,308 +1332,302 @@
return *this;
}
- const svg_color& y_minor_tick_color()
+ const svg_color y_minor_tick_color()
{
return image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_color();
}
- svg_2d_plot& y_range(double y1, double y2)
- { // Set the range (max and min) for Y values.
- y_min = y1;
- y_max = y2;
- if(y2 <= y1)
+ const std::string y_axis_position()
+ {
+ switch(y_axis_position_)
{
- throw std::runtime_error("Illegal Argument: X scale: x2 < x1");
+ case left:
+ return "y_axis_position left (all values < 0)"; break;
+ case y_intersect:
+ return "y_axis_position intersects X axis (range includes zero)"; break;
+ case right:
+ return "y_axis_position right (all values > 0)"; break;
+ default:
+ return "?"; break;
}
- return *this;
+ }
+
+ svg_2d_plot& y_range(double min_y, double max_y)
+ { // Set the range (max and min) for Y values.
+ if(max_y <= min_y)
+ { // max <= min.
+ throw std::runtime_error("Y range: y max <= y min!");
+ }
+ if((max_y - min_y) < std::numeric_limits<double>::epsilon() * 1000)
+ { // Range too small to display.
+ throw std::runtime_error("Y range too small!" );
+ }
+ y_axis_.min_ = min_y;
+ y_axis_.max_ = max_y;
+
+ return *this;
}
std::pair<double, double> y_range()
{
std::pair<double, double> r;
- r.first = y_min;
- r.second = y_max;
+ r.first = y_axis_.min_;
+ r.second = y_axis_.max_;
return r;
}
- double y_minimum()
+ double y_min()
{
- return y_min;
+ return y_axis_.min_;
}
- double y_maximum()
+ double y_max()
{
- return y_max;
+ return y_axis_.max_;
}
svg_2d_plot& y_major_interval(double inter)
{
- y_major_interval_ = inter;
+ y_ticks_.major_interval_ = inter;
return *this;
}
double y_major_interval()
{
- return y_major_interval_;
+ return y_ticks_.major_interval_;
}
svg_2d_plot& y_major_tick_length(double length)
{
- y_major_tick_length_ = length;
+ y_ticks_.major_tick_length_ = length;
return *this;
}
double y_major_tick_length()
{
- return y_major_tick_length_;
+ return y_ticks_.major_tick_length_;
}
svg_2d_plot& y_minor_tick_length(double length)
{
- y_minor_tick_length_ = length;
+ y_ticks_.minor_tick_length_ = length;
return *this;
}
double y_minor_tick_length()
{
- return y_minor_tick_length_;
+ return y_ticks_.minor_tick_length_;
}
svg_2d_plot& y_num_minor_ticks(unsigned int num)
{
- y_num_minor_ticks_ = num;
+ y_ticks_.num_minor_ticks_ = num;
return *this;
}
unsigned int y_num_minor_ticks()
{
- return y_num_minor_ticks_;
+ return y_ticks_.num_minor_ticks_;
}
svg_2d_plot& y_label_axis(const std::string& str)
{ // Label for Y-axis.
- y_label_info.text(str);
+ y_label_info_.text(str);
return *this;
}
std::string y_label_axis()
{
- return y_label_info.text();
+ return y_label_info_.text();
}
svg_2d_plot& y_major_tick_width(double width)
{
- y_major_tick_width_ = width;
+ y_ticks_.major_tick_width_ = width;
image.get_g_element(detail::PLOT_Y_MAJOR_TICKS).style().stroke_width(width);
return *this;
}
double y_major_tick_width()
{
- return y_major_tick_width_;
+ return y_ticks_.major_tick_width_;
}
svg_2d_plot& y_minor_tick_width(double width)
{
- y_minor_tick_width_ = width;
+ y_ticks_.minor_tick_width_ = width;
image.get_g_element(detail::PLOT_Y_MINOR_TICKS).style().stroke_width(width);
return *this;
}
double y_minor_tick_width()
{
- return y_minor_tick_width_;
+ return y_ticks_.minor_tick_width_;
}
svg_2d_plot& x_ticks_on_plot_window_on(bool is)
{
- use_x_ticks_on_plot_window_ = is;
+ x_ticks_.ticks_on_plot_window_on_ = is;
return *this;
}
bool x_ticks_on_plot_window_on()
{
- return use_x_ticks_on_plot_window_;
+ return x_ticks_.ticks_on_plot_window_on_;
}
svg_2d_plot& y_ticks_on_plot_window_on(bool is)
{
- use_y_ticks_on_plot_window_ = is;
+ y_ticks_.ticks_on_plot_window_on_ = is;
return *this;
}
bool y_ticks_on_plot_window_on()
{
- return use_y_ticks_on_plot_window_;
+ return y_ticks_.ticks_on_plot_window_on_;
}
svg_2d_plot& y_ticks_left_on(bool cmd)
{
- use_left_ticks = cmd;
+ y_ticks_.left_ticks_on_ = cmd;
return *this;
}
bool y_ticks_left_on()
{
- return use_left_ticks;
+ return y_ticks_.left_ticks_on_;
}
svg_2d_plot& y_ticks_right_on(bool cmd)
{
- use_right_ticks = cmd;
+ y_ticks_.right_ticks_on_ = cmd;
return *this;
}
bool y_ticks_right_on()
{
- return use_right_ticks;
+ return y_ticks_.right_ticks_on_;
}
// Only need y_ticks_left_on & y_ticks_right_on in 2D
svg_2d_plot& y_major_grid_on(bool is)
{
- use_y_major_grid_ = is;
+ y_ticks_.major_grid_on_ = is;
return *this;
}
bool y_major_grid_on()
{
- return use_y_major_grid_;
+ return y_ticks_.major_grid_on_;
}
svg_2d_plot& y_minor_grid_on(bool is)
{
- use_y_minor_grid_ = is;
+ y_ticks_.minor_grid_on_ = is;
return *this;
}
bool y_minor_grid_on()
{
- return use_y_minor_grid_;
+ return y_ticks_.minor_grid_on_;
}
svg_2d_plot& y_minor_grid_width(double width)
{
- y_minor_grid_width_ = width;
+ y_ticks_.minor_grid_width_ = width;
image.get_g_element(detail::PLOT_Y_MINOR_GRID).style().stroke_width(width);
return *this;
}
double y_minor_grid_width()
{
- return y_minor_grid_width_;
+ return y_ticks_.minor_grid_width_;
}
svg_2d_plot& y_major_grid_width(double width)
{
- y_major_grid_width_ = width;
+ y_ticks_.major_grid_width_ = width;
image.get_g_element(detail::PLOT_Y_MAJOR_GRID).style().stroke_width(width);
return *this;
}
double y_major_grid_width()
{
- return y_major_grid_width_;
+ return y_ticks_.major_grid_width_;
}
svg_2d_plot& y_label_font_size(unsigned int i)
{ // May be best to tie label & unit font sizes together?
- y_label_info.font_size(i);
- // y_units_info.font_size(i);
+ x_axis_label_style_.font_size(i);
+ // y_units_info_.font_size(i);
return *this;
}
unsigned int y_label_font_size()
{
- return y_label_info.font_size();
+ return x_axis_label_style_.font_size();
}
svg_2d_plot& y_label_weight(std::string s)
- { // "bold2 is only one that works so far.
- y_label_info.font_weight(s);
+ { // "bold" is only one that works so far.
+ x_axis_label_style_.font_weight(s);
return *this;
}
const std::string& y_label_weight()
{
- return y_label_info.font_weight();
+ return x_axis_label_style_.font_weight();
}
svg_2d_plot& y_label_font_family(const std::string& family)
{
- y_label_info.font_family(family);
+ x_axis_label_style_.font_family(family);
return *this;
}
const std::string& y_label_font_family();
//const std::string& y_label_font_family()
//{
- // return y_label_info.font_family();
+ // return y_label_info_.font_family();
//}
// Example of declaration but definition below.
// TODO Probably better done this way,
// but wait until parameter system removed.
- // plot member function, with several parameters, using Boost.Parameter,
- // to add data series to the plot window.
- // TODO replace this with chainable member functions.
-
-#if defined (BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable: 4100) // "'boost_parameter_enabler_argument' : unreferenced formal parameter"
-#endif
-
- BOOST_PARAMETER_MEMBER_FUNCTION
- (
- (void),
- plot,
- tag,
- (required
- (container, *)
- (title, (const std::string&))
- )
- (optional
- (fill_color, (const svg_color&), white)
- (stroke_color, (const svg_color&), black)
- (line_color, (const svg_color&), black)
- (area_fill_color, (const svg_color&), true) // == is blank
- // (area_fill_color, (svg_color_constant), blank)
- (point_style, (point_shape), round)
- (size, (int), 10)
- (line_on, (bool), true)
- (bezier_on, (bool), false)
- (x_functor, *, detail::boost_default_2d_convert())
- )
- )
- {
- // This line has the error in GCC. Also, operator() in boost_default_2d_convert
- // has been changed so that the value of i is not updated. I would like
- // the start to be set, as well as i to update in operator().
- // x_functor.start(1.);
- plot_line_style line_style(line_color, blank, line_on, bezier_on);
-
- line_style.area_fill = area_fill_color;
+ template <class T>
+ svg_2d_plot_series& plot(const T& container, const std::string& title)
+ {
+ series.push_back(
+ svg_2d_plot_series(
+ boost::make_transform_iterator(container.begin(), detail::boost_default_2d_convert()),
+ boost::make_transform_iterator(container.end(), detail::boost_default_2d_convert()),
+ title)
+ );
+ return series[series.size()-1];
+ }
+ template <class T, class U>
+ svg_2d_plot_series& plot(const T& container, const std::string& title, U functor)
+ { // Version with functor.
series.push_back(
svg_2d_plot_series(
- boost::make_transform_iterator(container.begin(), x_functor),
- boost::make_transform_iterator(container.end(), x_functor),
- title,
- plot_point_style(fill_color, stroke_color, size, point_style),
- line_style
- ));
+ boost::make_transform_iterator(container.begin(), functor),
+ boost::make_transform_iterator(container.end(), functor),
+ title)
+ );
+ return series[series.size()-1];
}
- }; // class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
+ }; // class svg_2d_plot : public detail::axis_plot_frame<svg_2d_plot>
// sample of declared function, externally defined in another .cpp file.
// TODO May be useful to refactor all functions this way.
const std::string& svg_2d_plot::y_label_font_family()
{
- return y_label_info.font_family();
+ return y_axis_label_style_.font_family();
}
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-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -163,36 +163,36 @@
// Stored so as to avoid rewriting style information constantly.
svg image;
- double y_scale;
- double y_shift;
+ double y_scale_;
+ double y_shift_;
- text_element title_info;
- text_element x_label_info;
- text_element y_label_info;
+ text_element title_info_;
+ text_element x_label_info_;
+ text_element y_label_info_;
// Border information for the plot window.
- int plot_x1;
- int plot_x2;
- int plot_y1;
- int plot_y2;
+ int plot_left_;
+ int plot_right_;
+ int plot_top_;
+ int plot_bottom_;
// Yes/no questions.
bool use_x_label; // // Show X-axis label text.
bool use_x_major_labels;
bool use_y_major_labels;
bool use_y_label;
- bool use_title;
+ bool title_on_;
// Where we will be storing the data points for transformation.
std::vector<svg_boxplot_series> series;
- std::string plot_window_clip;
+ std::string plot_window_clip_;
// Axes information.
- double y_min;
- double y_max;
+ double y_min_;
+ double y_max_;
double y_major_interval_;
- double y_axis;
- double x_axis;
+ double y_axis_;
+ double x_axis_;
unsigned int x_major_tick_length_;
unsigned int x_major_tick_width_; // pixels.
@@ -209,14 +209,14 @@
void transform_y(double& y)
{
- y = y * y_scale + y_shift;
+ y = y * y_scale_ + y_shift_;
}
void draw_y_minor_ticks(double j, path_element& tick_path)
{
- double y1(j), x1(plot_x1);
+ double y1(j), x1(plot_left_);
double y_tick_length = y_minor_tick_length_ / 2.;
- double x2(plot_x1 - y_tick_length / 2.);
+ double x2(plot_left_ - y_tick_length / 2.);
transform_y(y1);
@@ -232,8 +232,8 @@
// Draw major tick.
x1=i;
- y1 = plot_y2;
- y2 = plot_y2 + x_major_tick_length_;
+ y1 = plot_bottom_;
+ y2 = plot_bottom_ + x_major_tick_length_;
tick_path.M(x1, y1).L(x1, y2);
@@ -255,8 +255,8 @@
double y_tick_length = y_minor_tick_length_ / 2.;
- x1 = plot_x1;
- x2 = plot_x1 - y_tick_length / 2.;
+ x1 = plot_left_;
+ x2 = plot_left_ - y_tick_length / 2.;
tick_path.M(x1, y1).L(x2, y1);
@@ -284,7 +284,7 @@
double y_minor_jump = y_major_interval_/((double)(y_num_minor_ticks_ + 1.) );
// Draw the ticks on the positive side.
- for(double i = 0; i < y_max; i += y_major_interval_)
+ for(double i = 0; i < y_max_; i += y_major_interval_)
{
for(double j = i + y_minor_jump;
j < i + y_major_interval_;
@@ -297,7 +297,7 @@
}
// Draw the ticks on the negative side.
- for(double i = 0; i > y_min; i -= y_major_interval_)
+ for(double i = 0; i > y_min_; i -= y_major_interval_)
{
// draw minor ticks
for(double j=i; j>i-y_major_interval_; j-=y_major_interval_ / (y_num_minor_ticks_+1))
@@ -316,7 +316,7 @@
// Draw the axis line.
transform_y(y1);
- x_axis = y1;
+ x_axis_ = y1;
path_element& major_tick_path =
image.get_g_element(boxplot::X_TICKS).path();
@@ -325,7 +325,7 @@
for(size_t i = 0; i < series.size(); ++i)
{
draw_x_major_ticks(
- plot_x1 + (plot_x2-plot_x1)*((double)(i + 1)) /
+ plot_left_ + (plot_right_-plot_left_)*((double)(i + 1)) /
(double)(series.size() + 1),
major_tick_path, series[i].title);
}
@@ -340,18 +340,18 @@
void draw_title()
{
text_element title(image.x_size()/2.,
- title_info.font_size(),
- title_info.text());
+ title_info_.font_size(),
+ title_info_.text());
title.font_alignment(center_align);
- title.font_size(title_info.font_size());
+ title.font_size(title_info_.font_size());
image.get_g_element(boxplot::TITLE).push_back(new text_element(title));
}
void draw_x_label()
{
- text_element to_use((plot_x2 + plot_x1) / 2.,
- image.y_size() - 8, x_label_info.text());
+ text_element to_use((plot_right_ + plot_left_) / 2.,
+ image.y_size() - 8, x_label_info_.text());
to_use.font_size(12);
to_use.font_alignment(center_align);
@@ -363,54 +363,54 @@
{
image.get_g_element(boxplot::Y_LABEL).style().stroke_color(black);
image.get_g_element(boxplot::Y_LABEL).push_back(new
- text_element(12, (plot_y2 + plot_y1) /2.,
- y_label_info.text(), 12, "", "", "", "", "",center_align, upward));
+ text_element(12, (plot_bottom_ + plot_top_) /2.,
+ y_label_info_.text(), 12, "", "", "", "", "",center_align, upward));
}
void calculate_transform()
{
- y_scale = -(plot_y2-plot_y1)/(y_max-y_min);
- y_shift = plot_y1 - (y_max *(plot_y1-plot_y2)/(y_max-y_min));
+ y_scale_ = -(plot_bottom_-plot_top_)/(y_max_-y_min_);
+ y_shift_ = plot_top_ - (y_max_ *(plot_top_-plot_bottom_)/(y_max_-y_min_));
}
void calculate_plot_window()
{
- plot_x1 = plot_y1 = 0;
+ plot_left_ = plot_top_ = 0;
- plot_x2 = image.x_size();
- plot_y2 = image.y_size();
+ plot_right_ = image.x_size();
+ plot_bottom_ = image.y_size();
if(use_x_label)
{
- plot_y2 -= (int)(x_label_info.font_size() * 2);
+ plot_bottom_ -= (int)(x_label_info_.font_size() * 2);
}
if(use_y_label)
{
- plot_x1 += (int)(y_label_info.font_size() * text_margin_);
+ plot_left_ += (int)(y_label_info_.font_size() * text_margin_);
}
- if(use_title)
+ if(title_on_)
{
- plot_y1 += (int)(title_info.font_size() * text_margin_);
+ plot_top_ += (int)(title_info_.font_size() * text_margin_);
}
// Give the plot window a natural bit of padding.
- plot_x1+=5;
- plot_x2-=5;
- plot_y1+=5;
- plot_y2-=5;
+ plot_left_+=5;
+ plot_right_-=5;
+ plot_top_+=5;
+ plot_bottom_-=5;
- plot_x1 +=
+ plot_left_ +=
y_minor_tick_length_ > y_minor_tick_length_ ?
y_minor_tick_length_ : y_minor_tick_length_ ;
- plot_y2 -= x_major_tick_length_ + 10;
+ plot_bottom_ -= x_major_tick_length_ + 10;
image.get_g_element(boxplot::PLOT_BACKGROUND).push_back(
- new rect_element(plot_x1, plot_y1,
- (plot_x2-plot_x1), plot_y2-plot_y1));
+ new rect_element(plot_left_, plot_top_,
+ (plot_right_-plot_left_), plot_bottom_-plot_top_));
}
@@ -455,8 +455,8 @@
g_axis_ptr.line(x, min, x, max);
// Clip elements.
- g_axis_ptr.clip_id(plot_window_clip);
- g_whisk_ptr.clip_id(plot_window_clip);
+ g_axis_ptr.clip_id(plot_window_clip_);
+ g_whisk_ptr.clip_id(plot_window_clip_);
}
void draw_box(double q1, double q3, double x, double width,
@@ -476,7 +476,7 @@
g_ptr.rect(x - half_width, q3, width, q1 - q3);
// Clip elements.
- g_ptr.clip_id(plot_window_clip);
+ g_ptr.clip_id(plot_window_clip_);
}
void draw_median(double median, double x_offset, double box_width,
@@ -496,7 +496,7 @@
x_offset + half_width, median);
// Clip elements.
- g_ptr.clip_id(plot_window_clip);
+ g_ptr.clip_id(plot_window_clip_);
}
void draw_outliers(double x, const std::vector<double>& outliers,
@@ -530,8 +530,8 @@
}
// Clip elements.
- g_mild_ptr.clip_id(plot_window_clip);
- g_ext_ptr.clip_id(plot_window_clip);
+ g_mild_ptr.clip_id(plot_window_clip_);
+ g_ext_ptr.clip_id(plot_window_clip_);
}
void draw_boxplot(const svg_boxplot_series& series, double x_offset)
@@ -568,9 +568,9 @@
// We don't want to allow overlap of the plot window lines,
// thus the minor adjustments.
- image.clip_path(rect_element(plot_x1 + 1, plot_y1 + 1,
- plot_x2 - plot_x1 - 2, plot_y2 - plot_y1 - 2),
- plot_window_clip);
+ image.clip_path(rect_element(plot_left_ + 1, plot_top_ + 1,
+ plot_right_ - plot_left_ - 2, plot_bottom_ - plot_top_ - 2),
+ plot_window_clip_);
draw_y_axis();
draw_x_axis();
@@ -588,7 +588,7 @@
for(unsigned int i=0; i<series.size(); ++i)
{
draw_boxplot(series[i],
- plot_x1 + (plot_x2-plot_x1)*((double)(i + 1)) / (double)(series.size() + 1));
+ plot_left_ + (plot_right_-plot_left_)*((double)(i + 1)) / (double)(series.size() + 1));
}
}
@@ -596,22 +596,22 @@
svg_boxplot()
:
- title_info(0, 0, "Plot of data", 30),
- x_label_info(0, 0, "X Axis", 12,"Lucida Sans Console", "", "", "", "", center_align, horizontal),
- y_label_info(0, 0, "Y Axis", 12, "Lucida Sans Console", "", "", "", "", center_align, upward),
- // x_units_info(0, 0, "(units)", 12, "Lucida Sans Console", "", "", "", "", center_align, horizontal),
- // y_units_info(0, 0, "(units)", 12, "Lucida Sans Console", "", "", "", "", center_align, upward),
+ title_info_(0, 0, "Plot of data", 30),
+ x_label_info_(0, 0, "X Axis", 12,"Lucida Sans Console", "", "", "", "", center_align, horizontal),
+ y_label_info_(0, 0, "Y Axis", 12, "Lucida Sans Console", "", "", "", "", center_align, upward),
+ // x_units_info_(0, 0, "(units)", 12, "Lucida Sans Console", "", "", "", "", center_align, horizontal),
+ // y_units_info_(0, 0, "(units)", 12, "Lucida Sans Console", "", "", "", "", center_align, upward),
- y_min(0), y_max(100),
+ y_min_(0), y_max_(100),
y_major_interval_(10),
use_y_label(true),
use_x_label(true),
x_major_tick_length_(10),
y_num_minor_ticks_(1),
y_minor_tick_length_(20),
- plot_window_clip("__clip_window"), // TODO Why the __???
+ plot_window_clip_("__clip_window"), // TODO Why the __???
use_x_major_labels(true),
- use_title(true),
+ title_on_(true),
use_y_major_labels(true)
{
@@ -671,7 +671,7 @@
svg_boxplot& title_on(bool cmd)
{
- use_title = cmd;
+ title_on_ = cmd;
return *this;
}
@@ -749,8 +749,8 @@
svg_boxplot& y_range(double y1, double y2)
{
- y_min = y1;
- y_max = y2;
+ y_min_ = y1;
+ y_max_ = y2;
if(y2 <= y1)
{
@@ -762,7 +762,7 @@
svg_boxplot& y_label(const std::string& str)
{
- y_label_info.text(str);
+ y_label_info_.text(str);
return *this;
}
@@ -774,7 +774,7 @@
svg_boxplot& y_label_size(unsigned int size)
{
- y_label_info.font_size(size);
+ y_label_info_.font_size(size);
return *this;
}
@@ -786,25 +786,25 @@
svg_boxplot& title(const std::string& str)
{
- y_label_info.text(str);
+ y_label_info_.text(str);
return *this;
}
svg_boxplot& title_size(unsigned int size)
{
- y_label_info.font_size(size);
+ y_label_info_.font_size(size);
return *this;
}
svg_boxplot& x_label(const std::string& str)
{
- x_label_info.text(str);
+ x_label_info_.text(str);
return *this;
}
svg_boxplot& x_label_size(unsigned int size)
{
- x_label_info.font_size(size);
+ x_label_info_.font_size(size);
return *this;
}
@@ -875,7 +875,7 @@
std::string title()
{
- return title_info.text();
+ return title_info_.text();
}
bool x_label()
@@ -931,7 +931,7 @@
std::string x_label_text()
{
- return x_label_info.text();
+ return x_label_info_.text();
}
svg& get_svg()
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-13 10:12:10 EST (Sun, 13 Jan 2008)
@@ -1,6 +1,7 @@
// svg_style.hpp
// Copyright Jacob Voytko 2007
+// Copyright Paul A. Bristow 2007
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -20,6 +21,10 @@
#include <ostream>
// using std::ostream;
+#include <sstream>
+// using std::stringstream;
+#include <limits>
+// using numeric_limits;
namespace boost
{
@@ -28,9 +33,348 @@
// Forward declarations of classes in svg_style.hpp
class svg_style;
+class text_style;
class plot_point_style;
class plot_line_style;
-class text_style;
+class axis_line_style;
+class ticks_labels_style;
+
+enum rotate_style
+{ // Rotation in degrees from horizontal.
+ horizontal = 0, // normal left to right.
+ uphill = -45, // slope up.
+ upward = -90, // vertical writing up.
+ backup = -135, // slope up backwards.
+ downhill = 45, // slope down.
+ downward = 90, // vertical writing down.
+ backdown = 135, // slope down backwards.
+ upsidedown = 180 // == -180
+};
+
+const std::string strip_e0s(std::string s);
+// Ugly hack to remove unwanted sign and leading zero(s) in exponent.
+
+// -----------------------------------------------------------------
+// This is the style information for any <g> tag.
+// This may be expanded to include more data from the SVG standard.
+// -----------------------------------------------------------------
+class svg_style
+{
+ friend std::ostream& operator<< (std::ostream&, svg_style&);
+
+private: // Accesses only by set and get member functions below.
+ // Names changed so private data member variables end with _,
+ // to permit use of names for set & get member functions.
+ svg_color fill_;
+ svg_color stroke_;
+ double width_; // Only valid if > 0 & width_on_ == true
+ bool fill_on_; // true means there is fill info.
+ bool stroke_on_;
+ bool width_on_;
+
+public:
+ svg_style() :
+ fill_(svg_color(0, 0, 0)), // == black
+ stroke_(svg_color(0, 0, 0)), // == black
+ width_(0), // No width
+ fill_on_(false), stroke_on_(false), width_on_(false)
+ { // Default constructor initialises all private data.
+ }
+
+ svg_style(const svg_color& fill, const svg_color& stroke, unsigned int width = 0) :
+ fill_(fill), stroke_(stroke), width_(width),
+ fill_on_(false), stroke_on_(false), width_on_(false)
+ { // Construct with specified fill and stroke colors, and width.
+ }
+
+ // Set & get svg_style member functions
+ // to return fill color and stroke color & width.
+ svg_color fill_color() const
+ {
+ return svg_color(fill_);
+ }
+
+ svg_color stroke_color() const
+ {
+ return svg_color(stroke_);
+ }
+
+ double stroke_width() const
+ {
+ return width_;
+ }
+
+ bool fill_on() const
+ {
+ return fill_on_;
+ }
+
+ // TODO why are these not chainable? svg_style& fill_on(bool is)
+ void fill_on(bool is)
+ {
+ fill_on_ = is;
+ // return *this; // Make chainable.
+ }
+
+ bool stroke_on() const
+ {
+ return stroke_on_;
+ }
+
+ void stroke_on(bool is)
+ {
+ stroke_on_ = is;
+ }
+
+ bool width_on() const
+ {
+ return width_on_;
+ }
+
+ void width_on(bool is)
+ {
+ width_on_ = is;
+ }
+
+ // Set svg_style member functions to set fill, stroke & width.
+ svg_style& fill_color(const svg_color& col)
+ {
+ fill_ = col;
+ fill_on_ = ! col.blank; // if blank fill is off or "none"
+ return *this; // Make chainable.
+ }
+
+ svg_style& stroke_color(const svg_color& col)
+ {
+ stroke_ = col;
+ stroke_on_ = true; // Assume want a stroke if color is set.
+ return *this;
+ }
+
+ svg_style& stroke_width(double width)
+ {
+ width_ = width;
+ width_on_ = ((width > 0) ? true : false);
+ return *this;
+ }
+
+ void write(std::ostream& rhs)
+ { // Write any stroke, fill colors and/or width info (start with space).
+ if(stroke_on_)
+ {
+ rhs << " stroke=\"";
+ stroke_.write(rhs);
+ rhs << "\"";
+ }
+ if(fill_on_)
+ {
+ rhs << " fill=\"";
+ fill_.write(rhs);
+ rhs << "\"";
+ }
+ if(width_on_ && (width_ > 0))
+ { // We never want a 0 (or <0) width output?
+ rhs << " stroke-width=\""
+ << width_
+ << "\"";
+ }
+ // Examples: <g id="yMinorTicks" stroke="rgb(0,0,0)" stroke-width="1">
+ } // void write
+
+ // operators needed for testing at least.
+
+ bool operator==(svg_style& s)
+ {
+ return (s.fill_color() == fill_)
+ && (s.stroke_color() == stroke_)
+ && (s.stroke_width() == width_)
+ && (s.fill_on() == fill_on_)
+ && (s.stroke_on() == stroke_on_)
+ && (s.width_on() == width_on_);
+ }
+
+ bool operator!=(svg_style& s)
+ {
+ return (s.fill_color() != fill_)
+ || (s.stroke_color() != stroke_)
+ || (s.stroke_width() != width_)
+ || (s.fill_on() != fill_on_)
+ || (s.stroke_on() != stroke_on_)
+ || (s.width_on() != width_on_);
+ }
+}; // class svg_style
+
+std::ostream& operator<< (std::ostream& os, svg_style& s)
+{ //
+ os << "svg_style("
+ << s.fill_ << ", "
+ << s.stroke_ << ", "
+ << s.width_ << ", " // italic
+ << ((s.fill_on_) ? "fill, " : "no fill, ")
+ << ((s.stroke_on_) ? "stroke, " : "no stroke, ")
+ << ((s.fill_on_) ? "width)" : "no width)");
+ // Usage: svg_style my_svg_style; cout << my_svg_style << endl;
+ // Outputs: svg_style(RGB(0,0,0), RGB(0,0,0), 0, no fill, no stroke, no width)
+
+ return os;
+} // std::ostream& operator<<
+
+class text_style
+{
+ friend std::ostream& operator<< (std::ostream&, const text_style&);
+ friend bool operator== (const text_style&, const text_style&);
+ friend bool operator!= (const text_style&, const text_style&);
+
+private:
+ int font_size_;
+ std::string font_family_;
+ std::string weight_;
+ std::string style_;
+ std::string stretch_;
+ std::string decoration_;
+
+public:
+ text_style(int size = 20,
+ const std::string& font = "", // default is sans with Firefox & IE but serif with Opera
+ const std::string& style = "",
+ const std::string& weight = "",
+ const std::string& stretch = "",
+ const std::string& decoration = "")
+ : // Constructor.
+ font_size_(size),
+ font_family_(font),
+ style_(style),
+ weight_(weight),
+ stretch_(stretch),
+ decoration_(decoration)
+ { // text_style default constructor, defines defaults for all private members.
+ }
+
+ int font_size()
+ {
+ return font_size_;
+ }
+
+ text_style& font_size(unsigned int i)
+ { // pixels, default 10.
+ font_size_ = i;
+ return *this;
+ }
+
+ const std::string& font_family() const
+ {
+ return font_family_;
+ }
+
+ text_style& font_family(const std::string& s)
+ { // Examples: "Arial", "Times New Roman", "Verdana", "Lucida Sans Unicode"
+ font_family_ = s;
+ return *this;
+ }
+
+ const std::string& font_style() const
+ { // font-style: normal | bold | italic | oblique
+ return style_; // example "normal"
+ }
+
+ text_style& font_style(const std::string& s)
+ { // Examples: "italic"
+ style_ = s;
+ return *this;
+ }
+
+ const std::string& font_weight() const
+ {
+ return weight_;
+ }
+
+ text_style& font_weight(const std::string& s)
+ { // svg font-weight: normal | bold | bolder | lighter | 100 | 200 .. 900
+ // Examples: "bold", "normal"
+ weight_ = s;
+ return *this;
+ }
+
+ const std::string& font_stretch() const
+ {
+ return stretch_;
+ }
+
+ text_style& font_stretch(const std::string& s)
+ { // Examples: "wider" but implementation?
+ // font-stretch: normal | wider | narrower ...
+ stretch_ = s;
+ return *this;
+ }
+
+ const std::string& font_decoration() const
+ {
+ return decoration_;
+ }
+
+ text_style& font_decoration(const std::string& s)
+ { // Examples: "underline" | "overline" | "line-through"
+ decoration_ = s; // But implementation doubtful.
+ return *this;
+ }
+
+ // operators needed for testing at least.
+ bool operator==(const text_style& ts)
+ {
+ return (ts.font_size_ == font_size_)
+ && (ts.font_family_ == font_family_)
+ && (ts.stretch_ == stretch_)
+ && (ts.style_ == style_)
+ && (ts.weight_ == weight_)
+ && (ts.decoration_ == decoration_);
+ } // operator==
+
+ bool operator!=(const text_style& ts)
+ {
+ return (ts.font_size_ != font_size_)
+ || (ts.font_family_ != font_family_)
+ || (ts.stretch_ != stretch_)
+ || (ts.style_ != style_)
+ || (ts.weight_ != weight_)
+ || (ts.decoration_ != decoration_);
+ } // operator!=
+
+}; // class text_style
+
+bool operator== (const text_style& lhs, const text_style& rhs)
+{ // Note operator== and operator << both needed to use Boost.text.
+ return (lhs.font_size_ == rhs.font_size_)
+ && (lhs.font_family() == rhs.font_family())
+ && (lhs.stretch_ == rhs.stretch_)
+ && (lhs.style_ == rhs.style_)
+ && (lhs.weight_ == rhs.weight_)
+ && (lhs.decoration_ == rhs.decoration_);
+} // operator==
+
+//bool operator!= (const text_style& lhs, const text_style& rhs)
+//{ // Note operator== and operator << both needed to use Boost.text.
+// return false;
+//}
+
+std::ostream& operator<< (std::ostream& os, const text_style& ts)
+{ //
+ os << "text_style("
+ << ts.font_size_ << ", "
+ << ts.font_family_ << ", "
+ << ts.style_ << ", " // italic
+ << ts.weight_ // bold
+ // enable if implemented by rendering programs.
+ // << ", "
+ // << ts.stretch_ << ", "
+ //<< ts.decoration_
+ << ")" ;
+ // Usage: text_style ts(12, "Arial", "italic", "bold", "", ""); cout << t << endl;
+ // Outputs: text_style(12, Arial, italic, bold)
+
+ return os;
+} // std::ostream& operator<<
+
+text_style no_style; // Uses all constructor defaults.
enum point_shape
{ // Marking a data point.
@@ -61,6 +405,8 @@
class plot_point_style
{
+ friend std::ostream& operator<< (std::ostream&, plot_point_style);
+
public:
svg_color fill_color_; // Color of the centre of the shape.
svg_color stroke_color_; // Color of circumference of shape.
@@ -68,20 +414,22 @@
point_shape shape_; // round, square, point...
std::string symbols_; // Unicode symbol (letters, digits, squiggles etc)
// Caution: not all Unicode symbols are output by all browsers!
- // const std::string font = "Lucida Sans Unicode";
- // TODO? devise way of setting this font?
- //text_style style_;
+ // Set symbol(s) font using .style().font_family("arial");
+ text_style symbols_style_;
plot_point_style(const svg_color& fill = blank, const svg_color& stroke = blank,
int size = 10, point_shape shape = round, const std::string& symbols = "X")
:
fill_color_(fill), stroke_color_(stroke), size_(size), shape_(shape), symbols_(symbols)
{ // TODO Should there be default colors? or "none" == blank?
+ symbols_style_.font_size(size);
+ symbols_style_.font_family("Lucida Sans Unicode");
}
plot_point_style& size(int i)
{
size_ = i;
+ symbols_style_.font_size(i); // in case using a symbol.
return *this;
}
@@ -123,250 +471,439 @@
return shape_;
}
- //text_style& style()
- //{
- // return style_;
- //}
+ plot_point_style& symbols(const std::string s)
+ {
+ symbols_ = s;
+ return *this;
+ }
+
+ std::string& symbols()
+ {
+ return symbols_;
+ }
+ plot_point_style& style(text_style ts)
+ {
+ symbols_style_ = ts;
+ return *this;
+ }
+
+ text_style& style() const
+ {
+ return const_cast<text_style&>(symbols_style_);
+ // error C2440: 'return' : cannot convert from 'const boost::svg::text_style' to 'boost::svg::text_style &'
+ }
}; // struct plot_point_style
+std::ostream& operator<< (std::ostream& os, plot_point_style p)
+{ //
+ os << "point_style("
+ << p.shape_ << ", "
+ << p.stroke_color_ << ", "
+ << p.fill_color_ << ", "
+ << p.size_ << ", "
+ << p.symbols_ << ")" ;
+// Usage: plot_point_style p; cout << p << endl;
+// Outputs: point_style(1, RGB(0,0,0), RGB(0,0,0), 10, X)
+ return os;
+} // std::ostream& operator<<
+
class plot_line_style
-{ // TODO dotted and dashed line style? Useful for B&W?
+{ // Style of line joining data series values.
+ // TODO dotted and dashed line style? Useful for B&W?
public:
- svg_color color; // line stroke color.
- svg_color area_fill; // Fill color from line to axis. == true means color.blank = true.
- bool line_on;
- bool bezier_on;
+ svg_color color_; // line stroke color. (no fill color for lines)
+ svg_color area_fill_; // Fill color from line to axis. == true means color.blank = true.
+ bool line_on_;
+ bool bezier_on_;
- plot_line_style(const svg_color& col, const svg_color& acol = true, bool on = true, bool bezier_on = false)
+ plot_line_style(const svg_color& col = black, const svg_color& acol = true, bool on = true, bool bezier_on = false)
:
- color(col), area_fill(acol), line_on(on), bezier_on(bezier_on)
- {
+ color_(col), area_fill_(acol), line_on_(on), bezier_on_(bezier_on)
+ { // Defaults for all private data.
}
-}; // struct plot_line_style
-
-
-class text_style
-{
-private:
- int font_size_;
- std::string font_family_;
- std::string weight_;
- std::string style_;
- std::string stretch_;
- std::string decoration_;
+}; // class plot_line_style
+std::ostream& operator<< (std::ostream& os, plot_line_style p)
+{ //
+ os << "point_line_style("
+ << p.color_ << ", "
+ << p.area_fill_ << ", "
+ //<< ((p.area_fill) ? "area fill, " : ", ")
+ << ((p.line_on_) ? "line, " : "no line, ")
+ << ((p.bezier_on_) ? "bezier)" : "no bezier)");
+// Usage: plot_line_style p; cout << p << endl;
+// Outputs: point_line_style(RGB(0,0,0), blank, line, )
+ return os;
+} // std::ostream& operator<<
+
+enum dim{X = 1, Y = 2, Z = 3}; // Used so that an axis knows what type it is.
+
+class axis_line_style
+{ // Style of the x and/or y axes lines.
+ // But NOT the ticks and value labels.
+ // (Different styles for x and y are possible).
public:
- text_style(int size = 12,
- const std::string& font = "sans",
- const std::string& style = "",
- const std::string& weight = "",
- const std::string& stretch = "",
- const std::string& decoration = "")
- : // Constructor.
- font_size_(size),
- font_family_(font),
- style_(style),
- weight_(weight),
- stretch_(stretch),
- decoration_(decoration)
- { //text_style default constructor, defines defaults for all private members.
- }
+ dim dim_; // x, y or z
+ double min_; // minimum x value (Cartesian units).
+ double max_; // maximum x value (Cartesian units).
+ double axis_; //
+ // X-axis (y = 0) transformed into SVG Y coordinates. -1 if not calculated yet.
+ // or Y-axis (x = 0) transformed into SVG X coordinates. -1 if not calculated yet.
+
+ svg_color color_; // line stroke color.
+ double axis_width_; // line width.
+ int axis_position_; // How the axes intersect with values as below:
+ // enum x_axis_intersect {bottom = -1, x_intersect = 0, top = +1};
+ // enum y_axis_intersect {left = -1, y_intersect = 0, right = +1};
+ // If axes look like an L, then is bottom left.
+ // If a T then y intersects and x is at bottom.
+ // TODO check this is right!
+ bool label_on_; // Label X-axis with text - example: "length".
+ bool label_units_on_; // Label X-axis units, example: "cm".
+ bool axis_line_on_; // Draw a X horizontal or Y vertical axis line.
+
+ axis_line_style(dim d = X,
+ double min = -10., double max = +10., // defaults.
+ const svg_color col = black, double width = 1,
+ int axis_position = 0, bool use_label = true)
+ :
+ dim_(d), min_(min), max_(max), color_(col), axis_width_(width),
+ axis_position_(axis_position),
+ label_on_(use_label),
+ label_units_on_(true), // default is include units.
+ axis_line_on_(true),
+ axis_(-1) // Not calculated yet.
+ { // Initialize all private data.
+ if(max_ <= min_)
+ { // max_ <= min_.
+ throw std::runtime_error("Axis range: max <= min!");
+ }
+ if((max_ - min_) < std::numeric_limits<double>::epsilon() * 1000)
+ { // Range too small to display.
+ throw std::runtime_error("Axis range too small!" );
+ }
+ } // axis_line_style constructor
- int font_size()
+ // Set and get functions.
+ axis_line_style& color(const svg_color& color)
{
- return font_size_;
- }
-
- text_style& font_size(unsigned int i)
- { // pixels, default 10.
- font_size_ = i;
- return *this;
+ color_ = color;
+ return *this; // Make chainable.
}
- const std::string& font_family() const
+ svg_color color()
{
- return font_family_;
+ return color_;
}
-
- text_style& font_family(const std::string& s)
- { // Examples: "Arial", "Times New Roman", "Verdana", "Lucida Sans Unicode"
- font_family_ = s;
- return *this;
+
+ axis_line_style& width(double w)
+ {
+ axis_width_ = w;
+ return *this; // Make chainable.
}
- const std::string& font_style() const
- { // font-style: normal | bold | italic | oblique
- return style_; // example "normal"
+ double width()
+ {
+ return axis_width_;
}
- text_style& font_style(const std::string& s)
- { // Examples: "italic"
- style_ = s;
- return *this;
- }
- const std::string& font_weight() const
+ bool label_on() const
{
- return weight_;
+ return label_on_;
}
- text_style& font_weight(const std::string& s)
- { // svg font-weight: normal | bold | bolder | lighter | 100 | 200 .. 900
- // Examples: "bold", "normal"
- weight_ = s;
- return *this;
- }
-
- const std::string& font_stretch() const
+ axis_line_style& label_on(bool is)
{
- return stretch_;
+ label_on_ = is;
+ return *this; // Make chainable.
}
- text_style& font_stretch(const std::string& s)
- { // Examples: "wider" but implementation?
- // font-stretch: normal | wider | narrower ...
- stretch_ = s;
- return *this;
+ bool label_units_on() const
+ {
+ return label_units_on_;
}
- const std::string& font_decoration() const
+ axis_line_style& label_units_on(bool is)
{
- return decoration_;
+ label_units_on_ = is;
+ return *this; // Make chainable.
}
+}; // class axis_line_style
- text_style& font_decoration(const std::string& s)
- { // Examples: "underline" | "overline" | "line-through"
- decoration_ = s; // But implementation doubtful.
- return *this;
- }
-}; // class text_style
-text_style no_style;
+class ticks_labels_style
+{ // Style of the x and y axes ticks, grids and their value labels.
+ // But NOT the x and y axes lines.
+ // These can be either on the axis lines or on the plot window edge(s).
+ // (Different styles for x and y are possible).
+ friend class svg_2d_plot;
-// -----------------------------------------------------------------
-// This is the style information for any <g> tag.
-// This may be expanded to include more data from the SVG standard.
-// -----------------------------------------------------------------
-class svg_style
-{
-private: // Accesses only by set and get member functions below.
- // Names changed so private data member variables end with _,
- // to permit use of names for set & get member functions.
- svg_color fill_;
- svg_color stroke_;
- double width_;
- bool fill_on_; // true means there is fill info.
- bool stroke_on_;
- bool width_on_;
-
public:
- svg_style() :
- fill_(svg_color(0, 0, 0)), // == black
- stroke_(svg_color(0, 0, 0)), // == black
- width_(0),
- fill_on_(false), stroke_on_(false), width_on_(false)
- { // Default constructor initialises all private data.
- }
+ dim dim_;
+ double min_; // minimum x value (Cartesian units).
+ double max_; // maximum x value (Cartesian units).
+ double major_interval_; // x_major_interval_ is the stride or interval for major x ticks.
+ // (Cartesian units) set/get by x or y _major_interval
+ double minor_interval_; // Interval (Cartesian units) between minor ticks.
+ // No set function because x_num_minor_ticks_ used to determine this instead,
+ // but one could calculate x_minor_interval_.
+ unsigned int num_minor_ticks_; // number of minor ticks, eg 4 gives major 0, minor 1,2,3,4, major 5
+ // All units in pixels.
+ svg_color major_tick_color_; // line stroke color.
+ double major_tick_width_;
+ double major_tick_length_;
+ svg_color minor_tick_color_; // line stroke color.
+ double minor_tick_width_;
+ double minor_tick_length_;
+ svg_color major_grid_color_;
+ double major_grid_width_; // pixels.
+ svg_color minor_grid_color_;
+ double minor_grid_width_; // pixels.
+
+ bool up_ticks_on_; // Draw ticks up from horizontal X-axis line.
+ bool down_ticks_on_; // Draw ticks down from horizontal X-axis line.
+ bool left_ticks_on_; // Draw ticks left from vertical Y-axis line.
+ bool right_ticks_on_; // Draw ticks right from vertical Y-axis line.
+ // Simplest to have all of these although only one pair like up or down is used.
+ // Unused are always false.
+ bool major_value_labels_on; // Label X values for major ticks.
+ bool label_units_on_; // Label X-axis units.
+ rotate_style label_rotation_; // Direction X_axis value labels written.
+ 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.
+ int value_ioflags_; // IO formatting flags for the axis.
+ bool strip_e0s_;
+ rotate_style x_label_rotation_; // Direction X_axis value labels written.
+ //double label_length_; // width (in SVG units) of longest label on axis.
+ size_t label_max_chars_; // width (in SVG units) of longest label on axis.
+ // TODO appear to be duplicates.
+ bool ticks_on_plot_window_on_; // Value labels & ticks on the plot window rather than on X or Y-axis.
+
+ ticks_labels_style(dim d = X,
+ double max = 10., double min = -10.,
+ double major_interval = 2.,
+ unsigned int num_minor_ticks = 4)
+ : // Constructor.
+ dim_(d),
+ max_(max), min_(min),
+ major_interval_(major_interval),
+ num_minor_ticks_(num_minor_ticks),
+ // Other data can be changed by set functions.
+
+ // Initialize all private data.
+ // These are the defaults.
+ //major_interval_(2.), // x stride between major ticks & value label.
+ //num_minor_ticks_(4), // suits: major 0, minor 2, 4, 6, 8, major 10
+ minor_interval_(0), // Calculated from x & y_num_minor_ticks_
+ // but given a value here for safety.
+ major_tick_color_(black), // line stroke color.
+ major_tick_width_(2),
+ major_tick_length_(5),
+ minor_tick_color_(black), // line stroke color.
+ minor_tick_width_(1),
+ minor_tick_length_(2),
+ major_grid_color_(svg_color(200, 220, 255)),
+ minor_grid_color_(svg_color(200, 220, 255)),
+ major_grid_width_(1.), // pixels.
+ minor_grid_width_(0.5), // pixels.
+ up_ticks_on_(false), // Draw ticks up from horizontal X-axis line.
+ down_ticks_on_(true), // Draw ticks down from horizontal X-axis line.
+ left_ticks_on_(true), // Draw ticks left from vertical Y-axis line.
+ right_ticks_on_(false), // Draw ticks right from vertical Y-axis line.
+ // Simplest to have all of these although only one pair like up or down is used.
+ // Unused are always false.
+ major_value_labels_on(true), // Label values for major ticks.
+ label_units_on_(true), // Label axis units.
+ label_rotation_(horizontal), // Direction axis value labels written.
+ major_grid_on_(false), // Draw grid at major ticks.
+ minor_grid_on_(false),// Draw grid at minor ticks.
+ value_precision_(3), // precision for tick value labels, usually 3 will suffice.
+ 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.
+ ticks_on_plot_window_on_(true) // Value labels & ticks on the plot window rather than on X or Y-axis.
+ {
+ if(max_ <= min_)
+ { // max_ <= min_.
+ throw std::runtime_error("Axis ticks & labels range: max <= min!");
+ }
+ if((max_ - min_) < std::numeric_limits<double>::epsilon() * 1000)
+ { // Range too small to display.
+ throw std::runtime_error("Axis ticks & labels range too small!" );
+ }
+ }
- svg_style(const svg_color& fill, const svg_color& stroke, unsigned int width = 0) :
- fill_(fill), stroke_(stroke), width_(width),
- fill_on_(false), stroke_on_(false), width_on_(false)
- { // Construct with specified fill and stroke colors, and width.
- }
+ size_t 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.
+ std::stringstream label;
+ label.precision(value_precision_);
+ label.flags(value_ioflags_);
+ label << value; // "1.2" or "3.4e+000"...
+ 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
+
+ size_t longest_label()
+ { // Update label_max_chars_ with the longest value label as pixels,
+ // return the count of digits etc.
+ if(major_value_labels_on)
+ { // Show values by the tick as "1.2" or "3.4e+000"...
+ size_t 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.
+ // Zero isn't likely to be the longest value label.
+ // ticks_labels_style& tick_labels = (dim_ = X) ? x_ticks() : y_ticks(); // doesn't work.
+ //
- // Set & get svg_style member functions
- // to return fill color and stroke color & width.
- svg_color fill_color() const
- {
- return svg_color(fill_);
+ // Check length of label for the ticks on the positive side (right or above zero).
+ for(double v = 0.; v <= max_; v += major_interval_)
+ {
+ if (v != 0. || ticks_on_plot_window_on_)
+ { // Avoid a major tick at x == 0 where there *is* a vertical Y-axis line,
+ // 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);
+ if (l > longest)
+ {
+ longest = l;
+ }
+ }
+ } // for v
+ // Check length of label of the ticks on the negative side (left of zero).
+ for(double v = 0.; v >= min_; v -= major_interval_)
+ {
+ if (v != 0. || ticks_on_plot_window_on_)
+ { // 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);
+ if (l > longest)
+ {
+ longest = l;
+ }
+ }
+ } // for v
+ label_max_chars_ = longest;
+ return longest;
}
-
- svg_color stroke_color() const
+ else
{
- return svg_color(stroke_);
+ label_max_chars_ = 0;
+ return 0;
}
+ } // longest_label()
- double stroke_width() const
- {
- return width_;
- }
- bool fill_on() const
- {
- return fill_on_;
- }
+ bool use_up_ticks() const
+ {
+ return up_ticks_on_;
+ }
- void fill_on(bool is)
- {
- fill_on_ = is;
- }
+ ticks_labels_style& use_up_ticks(bool is)
+ {
+ up_ticks_on_ = is;
+ return *this; // Make chainable.
+ }
- bool stroke_on() const
- {
- return stroke_on_;
- }
+ bool use_down_ticks() const
+ {
+ return down_ticks_on_;
+ }
- void stroke_on(bool is)
- {
- stroke_on_ = is;
- }
+ ticks_labels_style& use_down_ticks(bool is)
+ {
+ down_ticks_on_ = is;
+ return *this; // Make chainable.
+ }
- bool width_on() const
- {
- return width_on_;
- }
- void width_on(bool is)
- {
- width_on_ = is;
- }
-
- // Set svg_style member functions to set fill, stroke & width.
- svg_style& fill_color(const svg_color& col)
- {
- fill_ = col;
- fill_on_ = ! col.blank; // if blank fill is off or "none"
- return *this; // Chainable.
- }
+}; // class ticks_labels_style
- svg_style& stroke_color(const svg_color& col)
- {
- stroke_ = col;
- stroke_on_ = true;
- return *this;
+class box_style
+{ // Style of a rectangular box.
+ // Use for image and plot window.
+public:
+ svg_color stroke_; // box line stroke color.
+ svg_color fill_; // box fill color.
+ double width_; // plot border rectangle width.
+ double margin_; // Marginal (pixels) space around the box (nside or out).
+ bool border_on_; // Display the border.
+ bool fill_on_; // Color fill the box.
+
+ box_style(const svg_color& scolor = black,
+ const svg_color& fcolor = antiquewhite,
+ double width = 1, // of border
+ double margin = 2.,
+ bool border_on = true,
+ bool fill_on = false)
+ :
+ stroke_(scolor), fill_(fcolor), width_(width),
+ margin_(margin),
+ border_on_(border_on),
+ fill_on_(fill_on)
+ { // Initializes all private data.
}
+}; // class axis_line_style
+
+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.
+ // Should also be useful for values that spill over into exponent format
+ // 'by accident' - when leading zeros are likely.
+ // For example, "1.2e+000" becomes "1.2"
+ using std::string;
+ size_t j = s.find("e+000");
+ if (j != string::npos)
+ {
+ s.erase(j, 5); // remove "e+000"
+ return s;
+ }
+ j = s.find("e-000");
+ if (j != string::npos)
+ {
+ s.erase(j, 5); // remove "e-000"
+ return s;
+ }
+ j = s.find("e+00");
+ if (j != string::npos)
+ {
+ s.erase(j + 1, 3); // remove "+00", leave d
+ return s;
+ }
+
+ j = s.find("e-00");
+ if (j != string::npos)
+ {
+ s.erase(j+2, 2); // remove "00", leave "-"
+ return s;
+ }
+ j = s.find("e+0");
+ if (j != string::npos)
+ {
+ s.erase(j + 1, 2); // remove "+0", leave "dd"
+ return s;
+ }
+ j = s.find("e-0");
+ if (j != string::npos)
+ {
+ s.erase(j+2, 1); // remove "0", leave "-dd"
+ }
+ return s; // Perhaps unchanged.
+} // const std::string strip(double d)
+
- svg_style& stroke_width(double width)
- {
- width_ = width;
- width_on_ = true;
- return *this;
- }
-
- void write(std::ostream& rhs)
- { // Write any stroke, fill colors and/or width info (start with space).
- if(stroke_on_)
- {
- rhs << " stroke=\"";
- stroke_.write(rhs);
- rhs << "\"";
- }
- if(fill_on_)
- {
- rhs << " fill=\"";
- fill_.write(rhs);
- rhs << "\"";
- }
- if(width_on_)
- { // TODO DO we ever want a 0 (or <0) width output???
- rhs << " stroke-width=\""
- << width_
- << "\"";
- }
- // Examples: <g id="yMinorTicks" stroke="rgb(0,0,0)" stroke-width="1">
- } // void write
-}; // class svg_style
}//svg
}//boost
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