Boost logo

Boost-Commit :

From: jakevoytko_at_[hidden]
Date: 2007-06-25 22:19:41


Author: jakevoytko
Date: 2007-06-25 22:19:40 EDT (Mon, 25 Jun 2007)
New Revision: 7156
URL: http://svn.boost.org/trac/boost/changeset/7156

Log:
Decoupled svg and svg_plot classes, added lots of customization

Text files modified:
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style.hpp | 27
   sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp | 102 +++
   sandbox/SOC/2007/visualization/boost/svg_plot/svg.hpp | 65 +
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_plot.hpp | 986 ++++++++++++++++++++++++++-------------
   sandbox/SOC/2007/visualization/boost/svg_plot/svg_test.cpp | 71 ++
   5 files changed, 851 insertions(+), 400 deletions(-)

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_style.hpp 2007-06-25 22:19:40 EDT (Mon, 25 Jun 2007)
@@ -266,7 +266,7 @@
 // expanded to include more data from the SVG standard when the
 // time comes.
 // -----------------------------------------------------------------
-class svg_g_style
+class svg_style
 {
 private:
     svg_color fill_color;
@@ -275,8 +275,8 @@
     unsigned int stroke_width;
     
 public:
- svg_g_style();
- svg_g_style(const svg_color&, const svg_color&);
+ svg_style();
+ svg_style(const svg_color&, const svg_color&);
 
     void set_fill_color(const svg_color&);
     void set_stroke_color(const svg_color&);
@@ -291,10 +291,9 @@
 };
 
 // -----------------------------------------------------------------
-// These are the defaults that I used in the prototype, and they
-// looked decent enough.
+// Black seems to me to be as good a default as any
 // -----------------------------------------------------------------
-svg_g_style::svg_g_style():fill_color(svg_color(255, 0, 0)),
+svg_style::svg_style():fill_color(svg_color(0, 0, 0)),
     stroke_color(svg_color(0, 0, 0)), stroke_width(0)
 {
 
@@ -304,43 +303,43 @@
 // -----------------------------------------------------------------
 // For changing the defaults for the colors
 // -----------------------------------------------------------------
-svg_g_style::svg_g_style(const svg_color& _fill, const svg_color& _stroke)
+svg_style::svg_style(const svg_color& _fill, const svg_color& _stroke)
 :fill_color(_fill), stroke_color(_stroke), stroke_width(0)
 {
 
 }
 
-void svg_g_style::set_stroke_color(const svg_color& rhs)
+void svg_style::set_stroke_color(const svg_color& rhs)
 {
     stroke_color = rhs;
 }
 
-void svg_g_style::set_fill_color(const svg_color& rhs)
+void svg_style::set_fill_color(const svg_color& rhs)
 {
     fill_color = rhs;
 }
 
-void svg_g_style::set_stroke_width(unsigned int _width)
+void svg_style::set_stroke_width(unsigned int _width)
 {
     stroke_width = _width;
 }
 
-svg_color svg_g_style::get_fill_color()
+svg_color svg_style::get_fill_color()
 {
     return svg_color(fill_color);
 }
 
-svg_color svg_g_style::get_stroke_color()
+svg_color svg_style::get_stroke_color()
 {
     return svg_color(stroke_color);
 }
 
-unsigned int svg_g_style::get_stroke_width()
+unsigned int svg_style::get_stroke_width()
 {
     return stroke_width;
 }
 
-void svg_g_style::write(std::ostream& rhs)
+void svg_style::write(std::ostream& rhs)
 {
     rhs << "stroke=\"";
     stroke_color.write(rhs);

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/svg_tag.hpp 2007-06-25 22:19:40 EDT (Mon, 25 Jun 2007)
@@ -33,9 +33,22 @@
     
 class svg_element
 {
+protected:
+ svg_style style_info;
+
 public:
     virtual void write(std::ostream&) = 0;
     virtual ~svg_element();
+
+ void set_stroke_color(const svg_color&);
+ void set_fill_color(const svg_color&);
+ void set_stroke_width(unsigned int);
+
+ svg_color get_stroke_color();
+ svg_color get_fill_color();
+
+ unsigned int get_stroke_width();
+
 };
 
 svg_element::~svg_element()
@@ -43,6 +56,36 @@
 
 }
 
+void svg_element::set_stroke_color(const svg_color& _col)
+{
+ style_info.set_stroke_color(_col);
+}
+
+void svg_element::set_fill_color(const svg_color& _col)
+{
+ style_info.set_fill_color(_col);
+}
+
+void svg_element::set_stroke_width(unsigned int _width)
+{
+ style_info.set_stroke_width(_width);
+}
+
+svg_color svg_element::get_stroke_color()
+{
+ return style_info.get_stroke_color();
+}
+
+svg_color svg_element::get_fill_color()
+{
+ return style_info.get_stroke_color();
+}
+
+unsigned int svg_element::get_stroke_width()
+{
+ return style_info.get_stroke_width();
+}
+
 // -----------------------------------------------------------------
 // The node element of our document tree
 // -----------------------------------------------------------------
@@ -50,23 +93,21 @@
 class g_element: public svg_element
 {
 private:
- svg_g_style style_info;
-
-public:
     boost::ptr_vector<svg_element> children;
     
+public:
+
     svg_element& operator[](unsigned int);
     size_t size();
-
- void set_stroke_color(const svg_color&);
- void set_fill_color(const svg_color&);
- void set_stroke_width(unsigned int);
-
- svg_color get_stroke_color();
 
     void write(std::ostream&);
 
     g_element& g_tag(int);
+ g_element& add_g_element();
+
+ void push_back(svg_element*);
+
+ void clear();
 };
 
 svg_element& g_element::operator[](unsigned int i)
@@ -99,24 +140,21 @@
     return *(static_cast<g_element*>(&children[i]));
 }
 
-void g_element::set_stroke_color(const svg_color& _col)
-{
- style_info.set_stroke_color(_col);
-}
-
-void g_element::set_fill_color(const svg_color& _col)
+//returns a reference to the node created
+g_element& g_element::add_g_element()
 {
- style_info.set_fill_color(_col);
+ children.push_back(new g_element);
+ return *(static_cast<g_element*>(&children[children.size()-1]));
 }
 
-void g_element::set_stroke_width(unsigned int _width)
+void g_element::push_back(svg_element* _g)
 {
- style_info.set_stroke_width(_width);
+ children.push_back(_g);
 }
 
-svg_color g_element::get_stroke_color()
+void g_element::clear()
 {
- return style_info.get_stroke_color();
+ children.clear();
 }
 
 // -----------------------------------------------------------------
@@ -192,6 +230,23 @@
     {
         alignment = _a;
     }
+
+ std::string get_text();
+
+ int get_font_size()
+ {
+ return font_size;
+ }
+
+ double set_x(double _x)
+ {
+ x = _x;
+ }
+
+ double set_y(double _y)
+ {
+ y = _y;
+ }
 };
 
 text_element::text_element(double _x, double _y, std::string _text)
@@ -231,7 +286,7 @@
         rhs << "text-anchor=\""<<align<<"\" ";
     }
 
- rhs <<" fill=\"black\" stroke=\"black\" font-family=\"verdana\"";
+ rhs <<" font-family=\"verdana\"";
 
     if(font_size == 0)
     {
@@ -252,6 +307,11 @@
     font_size = _size;
 }
 
+std::string text_element::get_text()
+{
+ return text;
+}
+
 // -----------------------------------------------------------------
 // Represents a single block of text
 // -----------------------------------------------------------------

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 2007-06-25 22:19:40 EDT (Mon, 25 Jun 2007)
@@ -54,12 +54,20 @@
     svg& line(double, double, double, double, g_element&);
     
     svg& text(double, double, std::string);
- svg& line_color(svg_color);
 
     svg& rect(double, double, double, double);
- svg& rect(double, double, double, double, g_element&);
+ svg& rect(double, double, double, double, g_element&);
+
+ g_element& add_g_element();
+ g_element& add_g_element(g_element&);
+
+ g_element& get_g_element(int i);
+ g_element& svg::get_g_element(int, g_element&);
 
     friend std::ostream& operator<<(std::ostream&, const svg&);
+
+ unsigned int get_x_size();
+ unsigned int get_y_size();
 };
 
 // -----------------------------------------------------------------
@@ -163,26 +171,26 @@
 // this overload has a pointer to a node in the document tree
 svg& svg::point(double x, double y, g_element& location)
 {
- location.children.push_back(new point_element(x, y));
+ location.push_back(new point_element(x, y));
 
     return *this;
 }
 
 svg& svg::point(double x, double y)
 {
- document.children.push_back(new point_element(x, y));
+ document.push_back(new point_element(x, y));
 
     return *this;
 }
 
 // -----------------------------------------------------------------
 // Writes the information about lines to the document
-// TODO: Allow other line thicknesses
+// TODO: Allow other line width
 // TODO: Allow other line colors
 // -----------------------------------------------------------------
 svg& svg::line(double x1, double y1, double x2, double y2)
 {
- document.children.push_back(new line_element(x1, y1, x2, y2));
+ document.push_back(new line_element(x1, y1, x2, y2));
 
     return *this;
 }
@@ -190,7 +198,7 @@
 svg& svg::line(double x1, double y1, double x2, double y2,
                 g_element& location)
 {
- location.children.push_back(new line_element(x1, y1, x2, y2));
+ location.push_back(new line_element(x1, y1, x2, y2));
 
     return *this;
 }
@@ -201,22 +209,14 @@
 // -----------------------------------------------------------------
 svg& svg::text(double x, double y, std::string text)
 {
- document.children.push_back(new text_element(x, y, text));
+ document.push_back(new text_element(x, y, text));
 
     return *this;
 }
 
-// -----------------------------------------------------------------
-// Hopefully this one will be filld out next week
-// -----------------------------------------------------------------
-svg& svg::line_color(svg_color col)
-{
- return *this;
-}
-
 svg& svg::rect(double x1, double y1, double x2, double y2)
 {
- document.children.push_back(new rect_element(x1, y1, x2, y2));
+ document.push_back(new rect_element(x1, y1, x2, y2));
 
     return *this;
 }
@@ -224,11 +224,40 @@
 svg& svg::rect(double x1, double y1, double x2, double y2,
                 g_element& location)
 {
- location.children.push_back(new rect_element(x1, y1, x2, y2));
+ location.push_back(new rect_element(x1, y1, x2, y2));
 
     return *this;
 }
 
+g_element& svg::add_g_element()
+{
+ return document.add_g_element();
+}
+
+g_element& svg::add_g_element(g_element& _g)
+{
+ return _g.add_g_element();
+}
+
+g_element& svg::get_g_element(int i)
+{
+ return document.g_tag(i);
+}
+
+g_element& svg::get_g_element(int i, g_element& _g)
+{
+ return _g.g_tag(i);
+}
+
+unsigned int svg::get_x_size()
+{
+ return x_size;
+}
+
+unsigned int svg::get_y_size()
+{
+ return y_size;
+}
 
 }
 }

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_plot.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_plot.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_plot.hpp 2007-06-25 22:19:40 EDT (Mon, 25 Jun 2007)
@@ -1,3 +1,7 @@
+
+
+
+
 // svg_plot.hpp
 
 // Copyright (C) Jacob Voytko 2007
@@ -14,93 +18,140 @@
 #include <ostream>
 #include <sstream>
 #include <iterator>
-#include <limits>
 
 #include "svg.hpp"
 #include "detail/svg_plot_instruction.hpp"
 
+#include <boost/parameter/name.hpp>
+#include <boost/parameter/preprocessor.hpp>
 
-#include <boost/array.hpp>
 
-namespace boost {
-namespace svg {
-
-// -----------------------------------------------------------------
-// The following enums define the tree for the document. The reason
-// that they are defined here is so that I can easily refer to them
-// when I'm building data. It's easier to refer to:
-// document[SVG_PLOT_BACKGROUND].color()
-//
-// than other possibilities I can think of!
-//
-// "legend" is on top because either it'll be laid on top of the graph,
-// or it'll be off to the side.
-// -----------------------------------------------------------------
-#define SVG_PLOT_DOC_CHILDREN 4
-
-enum svg_plot_doc_structure{SVG_PLOT_BACKGROUND, SVG_PLOT_PLOT,
- SVG_PLOT_LEGEND, SVG_PLOT_TITLE};
-
-// -----------------------------------------------------------------
-// The following enums define the children for the legend. This will be
-// incomplete, as the actual definition of the legend is fuzzy.
-// -----------------------------------------------------------------
 
-#define SVG_PLOT_DOC_LEGEND_CHILDREN 3
 
-enum svg_plot_doc_legend_structure{SVG_PLOT_LEGEND_BACKGROUND,
- SVG_PLOT_LEGEND_POINTS, SVG_PLOT_LEGEND_TEXT};
+namespace boost {
+namespace svg {
 
 // -----------------------------------------------------------------
-// The following enums define the tree for the plot itself.
-// -----------------------------------------------------------------
-
-#define SVG_PLOT_DOC_PLOT_CHILDREN 5
-
-enum svg_plot_doc_plot_structure{SVG_PLOT_PLOT_BACKGROUND, SVG_PLOT_PLOT_AXIS,
- SVG_PLOT_PLOT_LABELS, SVG_PLOT_PLOT_LINES, SVG_PLOT_PLOT_POINTS};
-
+// This is the base level of the "tree" for the SVG document. It is
+// flattened in order to facilitate using other image formats in the
+// future that don't have the benefit of a document tree. It also
+// greatly simplifies the logic of the methods below
+// -----------------------------------------------------------------
+enum plot_doc_structure{PLOT_BACKGROUND, PLOT_LEGEND_BACKGROUND,
+ PLOT_LEGEND_POINTS, PLOT_LEGEND_TEXT, PLOT_PLOT_BACKGROUND,
+ PLOT_PLOT_AXIS, PLOT_X_MINOR_TICKS, PLOT_X_MAJOR_TICKS,
+ PLOT_PLOT_LABELS, PLOT_PLOT_LINES, PLOT_PLOT_POINTS, PLOT_X_LABEL,
+ PLOT_TITLE};
+
+#define SVG_PLOT_DOC_CHILDREN 13
+
+// -----------------------------------------------------------------
+// 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_plot_series
+{
+ std::vector<double> series;
+ std::string title;
+ svg_color style;
+
+ svg_plot_series(std::vector<double>::const_iterator _begin,
+ std::vector<double>::const_iterator _end,
+ std::string _title,
+ const svg_color& _style):
+ series(_begin,_end),
+ title(_title),
+ style(_style)
+ {
 
+ }
+};
 
-class svg_plot: public svg
+class svg_plot
 {
 private:
+ //todo: replace with x_scale, x_shift, since I don't use the full matrix
     double transform_matrix[3][3];
- double x_min, x_max;
 
- //Still keep track of this for when we have a view window
- //for the graph
+ // stored so as to avoid rewriting style information constantly
+ svg image;
 
- double y_window_min, y_window_max;
+ // where we will be storing the data points for transformation
+ std::vector<svg_plot_series> series;
 
- double y_axis;
+ // strings having to do with labels
+ std::string x_label, title;
+
+ // axis information. y_axis stored as one point because this is a 1D graph
+ double x_min, x_max;
+ double x_axis;
     
+ double x_major_tick;
+
+ unsigned int x_major_tick_length, x_minor_tick_length,
+ x_num_minor_ticks, legend_title_font_size;
+
+ // border information for the plot window. Initially will be set to the width
+ // and height of the graph
+ int plot_window_x1, plot_window_x2,
+ plot_window_y1, plot_window_y2;
+
+ // Yes/no questions
     bool legend_on;
- std::vector<legend_point> legend;
+ bool axis_on;
+ bool plot_window_on;
+ bool x_label_on;
+ bool x_major_labels_on;
 
+ // internal helper functions
     void _transform_point(double &x);
     void _clear_legend();
- void _draw_legend_header(int, int, int, int);
+ void _draw_legend_header(int, int, int);
     void _draw_legend();
+ void _draw_axis();
+ void _draw_x_label();
 
+ svg_plot(const svg_plot&);
+
+ svg_plot& operator=(const svg_plot&);
 public:
+
+ // constructors
     svg_plot();
     svg_plot(const std::string& file);
-
- svg_plot& x_scale(double, double);
-
- svg_plot& draw_axis();
- svg_plot& show_legend();
-
- svg_plot& line_color(const svg_color&);
 
+ // output
     svg_plot& write(const std::string&);
     svg_plot& write(std::ostream&);
 
- svg_plot& image_size(unsigned int, unsigned int);
+
+ // plot functions
+ void plot_range(std::vector<double>::const_iterator,
+ std::vector<double>::const_iterator, const std::string&);
+
+ void plot_range(std::vector<double>::const_iterator,
+ std::vector<double>::const_iterator, const std::string&, svg_color_constant);
+
+ //setters
 
+ // misc
+ svg_plot& set_image_size(unsigned int, unsigned int);
     svg_plot& set_title(const std::string&);
     svg_plot& set_title_font_size(unsigned int);
+ svg_plot& set_legend_title_font_size(unsigned int);
+
+ // commands
+ svg_plot& set_axis(bool);
+ svg_plot& set_legend(bool);
+ svg_plot& set_plot_window(bool);
+ svg_plot& set_x_label(bool);
+ svg_plot& set_x_major_labels(bool);
+
+ // color information
+ svg_plot& set_title_color(svg_color_constant);
+ svg_plot& set_title_color(const svg_color&);
 
     svg_plot& set_background_color(svg_color_constant);
     svg_plot& set_background_color(const svg_color&);
@@ -108,29 +159,47 @@
     svg_plot& set_legend_background_color(svg_color_constant);
     svg_plot& set_legend_background_color(const svg_color&);
 
- svg_plot& set_axis_color(svg_color_constant);
- svg_plot& set_axis_color(const svg_color&);
+ svg_plot& set_plot_background_color(svg_color_constant);
+ svg_plot& set_plot_background_color(const svg_color&);
+
+ svg_plot& set_x_axis_color(svg_color_constant);
+ svg_plot& set_x_axis_color(const svg_color&);
 
- svg_plot& set_axis_thickness(unsigned int);
+ svg_plot& set_x_major_tick_color(svg_color_constant);
+ svg_plot& set_x_major_tick_color(const svg_color&);
 
- void plot_range(std::vector<double>::const_iterator,
- std::vector<double>::const_iterator, const std::string&);
-
- void plot_range(std::vector<double>::const_iterator,
- std::vector<double>::const_iterator, const std::string&, svg_color_constant);
+ svg_plot& set_x_minor_tick_color(svg_color_constant);
+ svg_plot& set_x_minor_tick_color(const svg_color&);
+
+ // axis information
+ svg_plot& set_x_scale(double, double);
+
+ svg_plot& set_x_axis_width(unsigned int);
+
+ svg_plot& set_x_major_tick(double);
+ svg_plot& set_x_major_tick_length(unsigned int);
+ svg_plot& set_x_minor_tick_length(unsigned int);
+ svg_plot& set_x_num_minor_ticks(unsigned int);
+ svg_plot& set_x_label_text(const std::string&);
+ svg_plot& set_x_major_tick_width(unsigned int);
+ svg_plot& set_x_minor_tick_width(unsigned int);
+
+ // getters
+ const std::string& get_title();
+ unsigned int get_title_font_size();
+
+ svg_color get_background_color();
+ svg_color get_legend_background_color();
+ svg_color get_axis_color();
+
+ unsigned int get_axis_width();
 };
 
-// -----------------------------------------------------------------
-// Constructors will be added so that the user can specify
-// a stream instead of a filename
-//
-// This performs work for default values so that if the user starts
-// adding data right away, we won't get abnormal results
-//
-// Note: All of the points are going to be on the same line, so
-// there is no sense calculating any aspect of the y value
-// -----------------------------------------------------------------
-svg_plot::svg_plot()
+svg_plot::svg_plot(): x_label(""), x_min(-10), x_max(10), plot_window_x1(0),
+ plot_window_y1(0), plot_window_x2(100),
+ plot_window_y2(100), x_axis(50), legend_on(false),
+ axis_on(false), x_minor_tick_length(10),
+ legend_title_font_size(12)
 {
     for(int i = 0; i < 3; ++i)
     {
@@ -141,78 +210,133 @@
     }
     
     //to determine: reasonable default values
- image_size(100, 100);
-
- y_window_min = 0;
- y_window_max = 100;
+ set_image_size(100, 100);
 
- y_axis = (y_window_min + y_window_max) / 2.;
+ //build the document tree.. add children of the root node
+ for(int i=0; i<SVG_PLOT_DOC_CHILDREN; ++i)
+ {
+ image.add_g_element();
+ }
+}
 
- x_min = -10;
- x_max = 10;
 
- legend_on = false;
+svg_plot& svg_plot::write(const std::string& _str)
+{
+ // Hold off drawing the legend until the very end.. it's
+ // easier to draw the size that it needs at the end than
+ // it is to
+ // Don't bother with re-adding things if we don't need to
 
- transform_matrix[0][0] = transform_matrix[2][2] = transform_matrix[1][1] = 1;
+ int x_size = image.get_x_size();
+ int y_size = image.get_y_size();
+
+ x_axis = (plot_window_y2 + plot_window_y1)/2.;
+
+ plot_window_x1 = plot_window_y1 = 0;
+ plot_window_x2 = image.get_x_size();
+ plot_window_y2 = image.get_y_size();
+
+ if(plot_window_on)
+ {
+ plot_window_x1+=5;
+ plot_window_x2-=5;
+ plot_window_y1+=5;
+ plot_window_y2-=5;
 
- transform_matrix[0][2] = x_size * (-x_min / (x_min - x_max));
+ if(axis_on)
+ {
+ plot_window_x2 -= 155;
+ }
 
- //build the document tree.. add children of the root node
- for(int i=0; i<SVG_PLOT_DOC_CHILDREN; ++i)
+ if(x_label_on)
+ {
+ plot_window_y2 -= 20;
+ }
+
+ //for the title. Will take into account font size soon
+ plot_window_y1 +=40;
+
+ image.get_g_element(PLOT_PLOT_BACKGROUND).push_back(
+ new rect_element(plot_window_x1, plot_window_y1,
+ (plot_window_x2-plot_window_x1), plot_window_y2-plot_window_y1));
+ }
+
+ transform_matrix[0][0] = (plot_window_x2-plot_window_x1)/(x_max-x_min);
+ transform_matrix[0][2] = plot_window_x1 - (x_min *(plot_window_x2-plot_window_x1)/(x_max-x_min));
+
+ if(axis_on)
     {
- document.children.push_back(new g_element());
+ _draw_axis();
     }
 
- //add children of the plot node
- for(int i=0; i<SVG_PLOT_DOC_PLOT_CHILDREN; ++i)
+ if(legend_on)
     {
- (static_cast<g_element*>
- (&(document.children[SVG_PLOT_PLOT])))
- ->children.push_back(new g_element());
+ _draw_legend();
     }
-
- //add children of the legend node
- for(int i=0; i<SVG_PLOT_DOC_LEGEND_CHILDREN; ++i)
+
+ if(x_label_on)
     {
- (static_cast<g_element*>
- (&(document.children[SVG_PLOT_LEGEND])))
- ->children.push_back(new g_element());
+ _draw_x_label();
     }
-}
 
-// -----------------------------------------------------------------
-// Set the scale for x values
-// -----------------------------------------------------------------
-svg_plot& svg_plot::x_scale(double x1, double x2)
-{
- x_min = x1;
- x_max = x2;
+ double x1(0);
 
- if(x2 <= x1)
+ //draw points
+ for(unsigned int i=0; i<series.size(); ++i)
     {
- throw "Illegal Argument: X scale: x2 < x1";
+ g_element& g_ptr = image.get_g_element(PLOT_PLOT_POINTS).add_g_element();
+ g_ptr.set_fill_color(series[i].style);
+
+ for(unsigned int j=0; j<series[i].series.size(); ++j)
+ {
+ x1 = series[i].series[j];
+
+ _transform_point(x1);
+
+ if(x1 > plot_window_x1 && x1 < plot_window_x2)
+ {
+ image.point(x1, x_axis, g_ptr);
+ }
+ }
     }
 
- transform_matrix[0][0] = x_size/(x2-x1);
- transform_matrix[0][2] = x_size*(-x1 / (x2 - x1));
+ image.write(_str);
 
- return (svg_plot&)*this;
+ return *this;
 }
 
-// -----------------------------------------------------------------
-// set the size of the svg image produced
-// -----------------------------------------------------------------
-svg_plot& svg_plot::image_size(unsigned int x, unsigned int y)
+svg_plot& svg_plot::write(std::ostream& s_out)
 {
- svg::image_size(x, y);
+ if(legend_on)
+ {
+ _draw_legend();
+ }
+
+ if(axis_on)
+ {
+ _draw_axis();
+ }
+
+ image.write(s_out);
     
- y_window_max = y;
+ return (svg_plot&)*this;
+}
 
- y_axis = (y + y_window_min)/2.;
+template <class iter>
+void plot_range(svg_plot& _cont, iter _begin, iter _end, std::string _str)
+{
+ vector<double> vect(_begin, _end);
 
- transform_matrix[0][2] = x_size * (-x_min / (x_min - x_max) );
+ _cont.plot_range(vect.begin(), vect.end(), _str);
+}
 
- return (svg_plot&)*this;
+template <class iter>
+void plot_range(svg_plot& _cont, iter _begin, iter _end, std::string _str,
+ svg_color_constant _col)
+{
+ vector<double> vect(_begin, _end);
+
+ _cont.plot_range(vect.begin(), vect.end(), _str, _col);
 }
 
 // -----------------------------------------------------------------
@@ -222,33 +346,7 @@
                             std::vector<double>::const_iterator end,
                             const std::string& _str)
 {
- double x;
-
- double i=0;
-
- g_element* g_ptr = &(document.g_tag(SVG_PLOT_PLOT).
- g_tag(SVG_PLOT_PLOT_POINTS));
-
- g_ptr->children.push_back(new g_element);
-
- // this sets the current <g> element to the one that will contain
- // the data that is being pushed back.
- g_ptr = &(g_ptr->g_tag((int)(g_ptr->size())-1));
-
- g_ptr->set_fill_color(black);
-
- for(std::vector<double>::const_iterator b = begin; b!=end; ++b)
- {
- x = *b;
- _transform_point(x);
- point(x, y_axis,
- *g_ptr);
- }
-
- // no matter what, we need to store information for the legend
- // so that it's easier to deal with when when turn it on after
- // we call this function =)
- legend.push_back(legend_point(g_ptr->get_stroke_color(), black, _str));
+ series.push_back(svg_plot_series(begin, end, _str, svg_color(0,0,0)));
 }
 
 // -----------------------------------------------------------------
@@ -259,90 +357,168 @@
                             const std::string& _str,
                             svg_color_constant _col)
 {
- double x;
+ series.push_back(svg_plot_series(begin, end, _str, constant_to_rgb(_col)));
+}
+
+// -----------------------------------------------------------------
+// Miscellaneous setter methods: those with no clear, definable home
+// in another category
+//
+// set_image_size(): sets image size in pixels. (x,y) corresponds
+// to point at lower right of graph
+//
+// set_title(): adds the text _title to the top of the screen
+//
+// set_title_font_size(): uses an internal variable to save state, to
+// avoid crashes when the title hasn't been
+// set yet
+//
+// set_legend_title_font_size(): As above
+// -----------------------------------------------------------------
+svg_plot& svg_plot::set_image_size(unsigned int x, unsigned int y)
+{
+ image.image_size(x, y);
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_title(const std::string& _title)
+{
+ text_element title(image.get_x_size()/2., 30, _title);
 
- double i=0;
+ title.set_alignment(center_align);
 
- g_element* g_ptr = &(document.g_tag(SVG_PLOT_PLOT).
- g_tag(SVG_PLOT_PLOT_POINTS));
+ image.get_g_element(PLOT_TITLE).push_back(new text_element(title));
 
- g_ptr->children.push_back(new g_element);
+ return *this;
+}
 
- // this sets the current <g> element to the one that will contain
- // the data that is being pushed back.
- g_ptr = &(g_ptr->g_tag((int)(g_ptr->size())-1));
+svg_plot& svg_plot::set_title_font_size(unsigned int _size)
+{
+ text_element* t_ptr = static_cast<text_element*>(
+ &(image.get_g_element(PLOT_TITLE)[0]));
 
- g_ptr->set_fill_color(_col);
+ t_ptr->set_font_size(_size);
 
- for(std::vector<double>::const_iterator b = begin; b!=end; ++b)
- {
- x = *b;
- _transform_point(x);
- point(x, y_axis,
- *g_ptr);
- }
+ return *this;
+}
+
+svg_plot& svg_plot::set_legend_title_font_size(unsigned int _size)
+{
+ legend_title_font_size = _size;
 
- // no matter what, we need to store information for the legend
- // so that it's easier to deal with when when turn it on after
- // we call this function =)
- legend.push_back(legend_point(g_ptr->get_stroke_color(), _col, _str));
+ return *this;
 }
 
 // -----------------------------------------------------------------
-// Sets the title. Currently, the title is centered at the top of
-// the screen
+// Commands: Answers to yes or no questions (Example: Show the legend?)
+//
+// set_axis(): Whether or not the axis will show
+//
+// set_legend(): Whether or not the legend will show
+//
+// set_plot_window(): Whether or not the plot will be full screen or
+// in its own contained window
+//
+// set_x_label(): Whether or not the label for the X axis will show
+//
+// set_x_major_labels(): Whether or not the major ticks will have labels
+// on the x-axis
+//
+//
 // -----------------------------------------------------------------
-svg_plot& svg_plot::set_title(const std::string& _title)
+
+svg_plot& svg_plot::set_axis(bool _cmd)
 {
- text_element title(x_size/2., 30, _title);
+ axis_on = _cmd;
+ return (svg_plot&)*this;
+}
 
- title.set_alignment(center_align);
+svg_plot& svg_plot::set_legend(bool _cmd)
+{
+ legend_on = _cmd;
 
- document.g_tag(SVG_PLOT_TITLE)
- .children.push_back(new text_element(title));
+ return (svg_plot&)*this;
+}
+
+svg_plot& svg_plot::set_plot_window(bool _cmd)
+{
+ plot_window_on = _cmd;
 
     return (svg_plot&)*this;
 }
 
-// -----------------------------------------------------------------
-// Setting the font size for the title before the text has been
-// written causes a runtime error
-// -----------------------------------------------------------------
-svg_plot& svg_plot::set_title_font_size(unsigned int _size)
+svg_plot& svg_plot::set_x_label(bool _cmd)
 {
- text_element* t_ptr = static_cast<text_element*>(&(document.
- g_tag(SVG_PLOT_TITLE).children[0]));
+ x_label_on = _cmd;
 
- t_ptr->set_font_size(_size);
+ return *this;
+}
 
- return (svg_plot&)*this;
+svg_plot& svg_plot::set_x_major_labels(bool _cmd)
+{
+ x_major_labels_on = _cmd;
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_title_color(svg_color_constant _col)
+{
+ set_title_color(constant_to_rgb(_col));
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_title_color(const svg_color& _col)
+{
+ image.get_g_element(PLOT_TITLE).set_stroke_color(_col);
+ image.get_g_element(PLOT_TITLE).set_fill_color(_col);
+
+ return *this;
 }
 
 // -----------------------------------------------------------------
-// Sets the background color in the area of the document. Specifically,
-// done by adding a rectangle to the background that hits the edges
-// of the image
+// Color settings: Customization of colors found in the plot
+//
+// set_title_color(): Sets the color of the plot title
+//
+// set_background_color(): Sets the color of the background. This is
+// not the same as the plot window background
+//
+// set_legend_background_color():
+// Sets the background color of the legend
+//
+// set_plot_background_color():
+// Sets the background color of the plot area.
+// If plot_window_on is not set true, this
+// does not show
+//
+// set_axis_color(): Color of the x axis + origin
+//
+// set_x_major_tick_color(): Sets the color of the major ticks on
+// the x-axis
+//
+// set_x_minor_tick_color(): As above, but for minor ticks
 // -----------------------------------------------------------------
 svg_plot& svg_plot::set_background_color(svg_color_constant _col)
 {
     set_background_color(constant_to_rgb(_col));
 
- return (svg_plot&)*this;
+ return *this;
 }
 
 svg_plot& svg_plot::set_background_color(const svg_color& _col)
 {
- document.g_tag(SVG_PLOT_BACKGROUND).set_fill_color(_col);
+ image.get_g_element(PLOT_BACKGROUND).set_fill_color(_col);
 
- document.g_tag(SVG_PLOT_BACKGROUND)
- .children.push_back(new rect_element(0, 0, x_size, y_size));
+ image.get_g_element(PLOT_BACKGROUND).clear();
+ image.get_g_element(PLOT_BACKGROUND).push_back(
+ new rect_element(0, 0, image.get_x_size(),
+ image.get_y_size()));
 
- return (svg_plot&)*this;
+ return *this;
 }
 
-// -----------------------------------------------------------------
-// Sets the background color in the area of the legend
-// -----------------------------------------------------------------
 svg_plot& svg_plot::set_legend_background_color(svg_color_constant _col)
 {
     set_legend_background_color(constant_to_rgb(_col));
@@ -352,132 +528,272 @@
 
 svg_plot& svg_plot::set_legend_background_color(const svg_color& _col)
 {
- document.g_tag(SVG_PLOT_LEGEND).g_tag(SVG_PLOT_LEGEND_BACKGROUND)
+ image.get_g_element(PLOT_LEGEND_BACKGROUND)
             .set_fill_color(_col);
 
- return (svg_plot&)*this;
+ return *this;
 }
 
-// -----------------------------------------------------------------
-// Currently sets the color of both axes
-// -----------------------------------------------------------------
-svg_plot& svg_plot::set_axis_color(svg_color_constant _col)
+svg_plot& svg_plot::set_plot_background_color(svg_color_constant _col)
+{
+ image.get_g_element(PLOT_PLOT_BACKGROUND).set_fill_color(_col);
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_plot_background_color(const svg_color& _col)
+{
+ image.get_g_element(PLOT_PLOT_BACKGROUND).set_fill_color(_col);
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_axis_color(svg_color_constant _col)
 {
- set_axis_color(constant_to_rgb(_col));
+ set_x_axis_color(constant_to_rgb(_col));
 
     return (svg_plot&)*this;
 }
 
-svg_plot& svg_plot::set_axis_color(const svg_color& _col)
+svg_plot& svg_plot::set_x_axis_color(const svg_color& _col)
 {
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS)
+ image.get_g_element(PLOT_PLOT_AXIS)
             .set_fill_color(_col);
 
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS)
+ image.get_g_element(PLOT_PLOT_AXIS)
             .set_stroke_color(_col);
 
- return (svg_plot&)*this;
+ return *this;
 }
 
-svg_plot& svg_plot::set_axis_thickness(unsigned int _width)
+svg_plot& svg_plot::set_x_major_tick_color(const svg_color& _col)
 {
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS)
- .set_stroke_width(_width);
+ image.get_g_element(PLOT_X_MAJOR_TICKS).set_stroke_color(_col);
+ image.get_g_element(PLOT_X_MAJOR_TICKS).set_fill_color(_col);
+ return *this;
+}
 
- return (svg_plot&)*this;
+svg_plot& svg_plot::set_x_major_tick_color(svg_color_constant _col)
+{
+ set_x_major_tick_color(constant_to_rgb(_col));
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_minor_tick_color(const svg_color& _col)
+{
+ image.get_g_element(PLOT_X_MINOR_TICKS).set_stroke_color(_col);
+ image.get_g_element(PLOT_X_MINOR_TICKS).set_fill_color(_col);
+ return *this;
+}
+
+
+svg_plot& svg_plot::set_x_minor_tick_color(svg_color_constant _col)
+{
+ set_x_minor_tick_color(constant_to_rgb(_col));
+ return *this;
 }
 
 // -----------------------------------------------------------------
-// This transforms a 1-D Cartesian point into a svg point. We don't
-// use the svg-defined coordinate transform because sizing is a harder
-// problem in the svg coordinate transforms, and text would be
-// flipped if were were to mimic the Cartesian system
+// Axis information: Settings for customization of axis information
+//
+// set_x_scale(): sets the left and right max values for the x axis
+//
+// set_x_axis_width(): The width of the x axis
+//
+// set_x_major_tick(): The distance between the ticks of the x_axis
+//
+// set_x_major_tick_length(): How long each tick will be
+//
+// set_x_minor_tick_length(): How long each tick will be
+//
+// set_x_num_minor_ticks(): The number of minor ticks between each
+// major tick
+//
+// set_x_label_text(): Labelling for the x-axis
+//
+// set_x_major_tick_width(): Stroke width for major ticks
+//
+// set_x_minor_tick_width(): Stroke width for minor ticks
 // -----------------------------------------------------------------
-void svg_plot::_transform_point(double &x)
+
+svg_plot& svg_plot::set_x_scale(double x1, double x2)
 {
- x = transform_matrix[0][0] * x + transform_matrix[0][2];
+ x_min = x1;
+ x_max = x2;
+
+ if(x2 <= x1)
+ {
+ throw "Illegal Argument: X scale: x2 < x1";
+ }
+
+ return (svg_plot&)*this;
 }
 
+svg_plot& svg_plot::set_x_axis_width(unsigned int _width)
+{
+ image.get_g_element(PLOT_PLOT_AXIS).set_stroke_width(_width);
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_major_tick(double _inter)
+{
+ x_major_tick = _inter;
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_major_tick_length(unsigned int _length)
+{
+ x_major_tick_length = _length;
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_minor_tick_length(unsigned int _length)
+{
+ x_minor_tick_length = _length;
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_num_minor_ticks(unsigned int _num)
+{
+ x_num_minor_ticks = _num;
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_label_text(const std::string& _str)
+{
+ x_label = _str;
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_major_tick_width(unsigned int _width)
+{
+ image.get_g_element(PLOT_X_MAJOR_TICKS).set_stroke_width(_width);
+
+ return *this;
+}
+
+svg_plot& svg_plot::set_x_minor_tick_width(unsigned int _width)
+{
+ image.get_g_element(PLOT_X_MINOR_TICKS).set_stroke_width(_width);
+
+ return *this;
+}
 
 // -----------------------------------------------------------------
-// TODO: Refactor
+// We don't use the SVG coordinate transform because then text would
+// be flipped. I'm considering using it to scale the image for resizes
 // -----------------------------------------------------------------
-svg_plot& svg_plot::draw_axis()
+void svg_plot::_transform_point(double &x)
 {
- // one major axis. We just need to draw a verticle line through
+ x = transform_matrix[0][0] * x + transform_matrix[0][2];
+}
+
+//refactor
+void svg_plot::_draw_axis()
+{
+ // one major axis. We just need to draw a vertical line through
     // the origin for now. We will make that an option later.
+ double x1, y1, y2;
 
- double x1, x2, y1, y2;
-
- x1 = x_min;
- x2 = x_max;
+ x_axis = (plot_window_y1 + plot_window_y2) / 2.;
+
+ image.line(plot_window_x1, x_axis, plot_window_x2, x_axis,
+ image.get_g_element(PLOT_PLOT_AXIS));
+
+ x1 = 0;
 
- _transform_point(x2);
     _transform_point(x1);
+
+ image.line(x1, plot_window_y1, x1, plot_window_y2,
+ image.get_g_element(PLOT_PLOT_AXIS));
 
- double y_mean = (y_window_min + y_window_max)/2.;
- double x_mean = (x1 + x2)/2.;
+ int major_tick_len = x_major_tick_length/2;
 
- line(x1, y_mean, x2, y_mean,
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS));
+ for(double i = 0; i < x_max; i += x_major_tick)
+ {
+ for(double j=i; j<i+x_major_tick; j+=x_major_tick / (x_num_minor_ticks+1))
+ {
+ y1 = x_axis + x_minor_tick_length/2.;
+ y2 = x_axis - x_minor_tick_length/2.;
 
- //origin
- line(x_mean, y_window_min, x_mean, y_window_max,
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS));
+ x1=j;
 
- y1 = y2 = 0;
- x1 = x_min;
- x2 = x_max;
+ _transform_point(x1);
 
- for(double i = 0; i <= x_max; i += 1)
- {
- y1 = y_mean+5;
- y2 = y_mean-5;
+ //make sure that we are drawing inside of the allowed window
+ if(x1 < plot_window_x2)
+ {
+ image.line(x1, y1, x1, y2,
+ image.get_g_element(PLOT_X_MINOR_TICKS));
+ }
+ }
+
+ y1 = x_axis + x_major_tick_length/2;
+ y2 = x_axis - x_major_tick_length/2;
     
         x1=i;
 
         _transform_point(x1);
- _transform_point(x2);
 
- line(x1, y1, x1, y2,
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS));
+ //make sure that we are drawing inside of the allowed window
+ if(x1 < plot_window_x2)
+ {
+ image.line(x1, y1, x1, y2,
+ image.get_g_element(PLOT_X_MAJOR_TICKS));
+
+
+ if(x_major_labels_on)
+ {
+ std::stringstream fmt;
+ fmt<<i;
+
+ image.text(x1, y1 + (2 + x_major_tick_length/2), fmt.str());
+ }
+ }
     }
 
- for(double i = 0; i >= x_min; i -= 1)
+ for(double i = 0; i > x_min; i -= x_major_tick)
     {
- y1 = y_mean+5;
- y2 = y_mean-5;
-
- x1=i;
+ for(double j=i; j>i-x_major_tick; j-=x_major_tick / (x_num_minor_ticks+1))
+ {
+ y1 = x_axis + x_minor_tick_length/2.;
+ y2 = x_axis - x_minor_tick_length/2.;
 
- _transform_point(x1);
+ x1=j;
 
- line(x1, y1, x1, y2,
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS));
- }
+ _transform_point(x1);
 
- return (svg_plot&)*this;
-}
+ //make sure that we are drawing inside of the allowed window
+ if(x1 > plot_window_x1)
+ {
+ image.line(x1, y1, x1, y2,
+ image.get_g_element(PLOT_X_MINOR_TICKS));
+ }
+ }
+ y1 = x_axis+major_tick_len;
+ y2 = x_axis-major_tick_len;
+
+ x1=i;
 
-svg_plot& svg_plot::show_legend()
-{
- legend_on = true;
+ _transform_point(x1);
 
- return (svg_plot&)*this;
-}
+ if(x1 > plot_window_x1)
+ {
+ image.line(x1, y1, x1, y2,
+ image.get_g_element(PLOT_X_MAJOR_TICKS));
 
-// -----------------------------------------------------------------
-// Set the line color. This currently gets overwritten by the
-// default for <g> in _plot_range, so this will be fixed, probably
-// by removing the default for <g> in the constructor (ran out of
-// time this week)
-// -----------------------------------------------------------------
-svg_plot& svg_plot::line_color(const svg_color& _col)
-{
- document.g_tag(SVG_PLOT_PLOT).g_tag(SVG_PLOT_PLOT_AXIS)
- .set_stroke_color(_col);
+ if(x_major_labels_on)
+ {
+ std::stringstream fmt;
+ fmt<<i;
 
- return (svg_plot&)*this;
+ image.text(x1, y1 + (2 + x_major_tick_length/2), fmt.str());
+ }
+ }
+ }
 }
 
 // -----------------------------------------------------------------
@@ -488,28 +804,29 @@
 // -----------------------------------------------------------------
 void svg_plot::_clear_legend()
 {
- g_element* g_ptr = &(document.g_tag(SVG_PLOT_LEGEND)
- .g_tag(SVG_PLOT_LEGEND_POINTS));
+ g_element* g_ptr = &(image.get_g_element(PLOT_LEGEND_POINTS));
 
- g_ptr->children.erase(g_ptr->children.begin(), g_ptr->children.end());
+ g_ptr->clear();
 
- g_ptr = &(document.g_tag(SVG_PLOT_LEGEND).g_tag(SVG_PLOT_LEGEND_TEXT));
- g_ptr->children.erase(g_ptr->children.begin(), g_ptr->children.end());
+ g_ptr = &(image.get_g_element(PLOT_LEGEND_TEXT));
+ g_ptr->clear();
 }
 
 // -----------------------------------------------------------------
 // Factored out to make _draw_legend() cleaner
+//
+// This function has some "magic" values that could be removed
+// or abstracted
 // -----------------------------------------------------------------
-void svg_plot::_draw_legend_header(int _x, int _y, int _width, int _height)
+void svg_plot::_draw_legend_header(int _x, int _y, int _width)
 {
- g_element* g_ptr = &(document.g_tag(SVG_PLOT_LEGEND)
- .g_tag(SVG_PLOT_LEGEND_TEXT));
-
- text_element legend_header(_x+(_width/2), _y + 20, "Legend");
+ // 2 added to y argument for padding.
+ text_element legend_header(_x+(_width/2), _y + legend_title_font_size + 2, "Legend");
 
     legend_header.set_alignment(center_align);
+ legend_header.set_font_size(legend_title_font_size);
 
- g_ptr->children.push_back(new text_element(legend_header));
+ image.get_g_element(PLOT_LEGEND_TEXT).push_back(new text_element(legend_header));
 }
 
 // -----------------------------------------------------------------
@@ -517,107 +834,116 @@
 // fill-ins for the time when the legend system is more configurable.
 // This will happen bit-by-bit, as I give the user options to change
 // these values
+//
+// The legend will soon be a percentage of the window, which will
+// remove some of the magic values
 // -----------------------------------------------------------------
 void svg_plot::_draw_legend()
 {
     _clear_legend();
 
- int num_points = (int)(legend.size());
+ int num_points = (int)(series.size());
 
- int legend_width(200);
+ int legend_width(150);
     int legend_height(25);
 
+ int x_size = image.get_x_size();
+
     // Figure out how wide the legend should be
     if(x_size < 200)
     {
- legend_width = x_size;
+ legend_width = (int)x_size;
     }
 
- int legend_x_start(x_size-legend_width-20);
- int legend_y_start(40);
+ int legend_x_start(plot_window_x2 + 5);
+ int legend_y_start(plot_window_y1);
 
     // legend_height = title_spacing + (space per element)(num_elements)
     // + (end spacing)
- legend_height = 25 + (25 * num_points) + 10;
+ legend_height = (int)(legend_title_font_size*1.5 + (25 * num_points) + 10);
 
     // TODO: Figure out how tall the legend should be
 
- g_element* g_ptr = &(document.g_tag(SVG_PLOT_LEGEND)
- .g_tag(SVG_PLOT_LEGEND_BACKGROUND));
+ image.get_g_element(PLOT_LEGEND_BACKGROUND).set_stroke_color(svg_color(102, 102, 84));
+ g_element* g_ptr = &(image.get_g_element(PLOT_LEGEND_BACKGROUND));
 
- g_ptr->children.push_back(new rect_element(legend_x_start, legend_y_start,
- legend_width, legend_height));
+ g_ptr->push_back(new rect_element(legend_x_start,
+ legend_y_start,
+ legend_width,
+ legend_height));
 
- _draw_legend_header(legend_x_start, legend_y_start, legend_width, legend_height);
+ _draw_legend_header(legend_x_start, legend_y_start, legend_width);
 
- g_ptr = &(document.g_tag(SVG_PLOT_LEGEND)
- .g_tag(SVG_PLOT_LEGEND_POINTS));
+ g_ptr = &(image.get_g_element(PLOT_LEGEND_POINTS));
 
- g_element* g_inner_ptr;
- int i=0;
+ g_element* g_inner_ptr = g_ptr;
 
- for(std::vector<legend_point>::iterator iter = legend.begin();
- iter!=legend.end(); ++iter, ++i)
+ for(unsigned int i=0; i<series.size(); ++i)
     {
- g_ptr -> children.push_back( new g_element() );
- g_inner_ptr = &(g_ptr->g_tag((int)(g_ptr->children.size())-1));
-
- g_inner_ptr->set_fill_color((*iter).fill_color);
- g_inner_ptr->set_stroke_color((*iter).stroke_color);
+ g_inner_ptr = &(g_ptr->add_g_element());
 
- g_inner_ptr->children.push_back(new point_element(legend_x_start + 25,
- legend_y_start + 36 + i*25));
+ g_inner_ptr->set_fill_color(series[i].style);
+ g_inner_ptr->set_stroke_color(series[i].style);
 
- g_inner_ptr->children.push_back(new text_element(legend_x_start + 40,
- legend_y_start + 42 + i*25, (*iter).text));
+ g_inner_ptr->push_back(new point_element(legend_x_start + 25,
+ legend_y_start + legend_title_font_size + 20 + i*25));
+
+ g_inner_ptr->push_back(new text_element(legend_x_start + 40,
+ legend_y_start + legend_title_font_size + 25 + i*25,
+ series[i].title));
     }
 }
 
-svg_plot& svg_plot::write(const std::string& _str)
+void svg_plot::_draw_x_label()
 {
- // Hold off drawing the legend until the very end.. it's
- // easier to draw the size that it needs at the end than
- // it is to
- // Don't bother with re-adding things if we don't need to
- if(legend_on)
- {
- _draw_legend();
- }
+ text_element to_use((plot_window_x2 + plot_window_x1) / 2., image.get_y_size() - 8, x_label);
 
- svg::write(_str);
+ to_use.set_font_size(12);
+ to_use.set_alignment(center_align);
 
- return (svg_plot&)*this;
+ image.get_g_element(PLOT_X_LABEL).set_stroke_color(white);
+ image.get_g_element(PLOT_X_LABEL).set_fill_color(white);
+
+
+ image.get_g_element(PLOT_X_LABEL).push_back(new text_element(to_use));
 }
 
-svg_plot& svg_plot::write(std::ostream& s_out)
+const std::string& svg_plot::get_title()
 {
- if(legend_on)
- {
- _draw_legend();
- }
-
- svg::write(s_out);
-
- return (svg_plot&)*this;
+ return title;
 }
 
-template <class iter>
-void plot_range(svg_plot& _cont, iter _begin, iter _end, std::string _str)
+unsigned int svg_plot::get_title_font_size()
 {
- vector<double> vect(_begin, _end);
+ return (static_cast<text_element*>(
+ &(image.get_g_element(PLOT_TITLE)[0])))->get_font_size();
+ return 0;
+}
 
- _cont.plot_range(vect.begin(), vect.end(), _str);
+svg_color svg_plot::get_background_color()
+{
+ return image.get_g_element(PLOT_BACKGROUND).get_fill_color();
+ return svg_color(0,0,0);
 }
 
-template <class iter>
-void plot_range(svg_plot& _cont, iter _begin, iter _end, std::string _str,
- svg_color_constant _col)
+svg_color svg_plot::get_legend_background_color()
 {
- vector<double> vect(_begin, _end);
+ return image.get_g_element(PLOT_LEGEND_BACKGROUND).get_fill_color();
+ return svg_color(0,0,0);
+}
 
- _cont.plot_range(vect.begin(), vect.end(), _str, _col);
+svg_color svg_plot::get_axis_color()
+{
+ return image.get_g_element(PLOT_PLOT_AXIS).get_stroke_color();
+ return svg_color(0,0,0);
 }
 
+unsigned int svg_plot::get_axis_width()
+{
+ return image.get_g_element(PLOT_PLOT_AXIS).get_stroke_width();
+}
+
+
 }
 }
 

Modified: sandbox/SOC/2007/visualization/boost/svg_plot/svg_test.cpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/svg_test.cpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/svg_test.cpp 2007-06-25 22:19:40 EDT (Mon, 25 Jun 2007)
@@ -1,6 +1,7 @@
 #include <vector>
 #include <deque>
 #include <cmath>
+#include <boost/array.hpp>
 
 #include "svg_plot.hpp"
 
@@ -17,36 +18,72 @@
     return -2 + x;
 }
 
+double h(double x)
+{
+ return 2*x;
+}
+
 int main()
 {
   double start = 0, finish = 10;
 
     vector<double> data1;
     deque<double> data2;
+ boost::array<double, 10> data3;
 
-
- double inter = 3.1415926535 / 4.;
+ double inter = 3.1415926535 / 1.;
     
- for(double i = start; i <= finish; i += inter)
+ int j=0;
+ for(double i = start; i <= finish; i += inter, ++j)
+ {
         data1.push_back(f(i));
-
- for(double i=start; i <= finish; i += inter)
         data2.push_back(g(i));
+ data3[j] = h(i);
+ }
 
- svg_plot my_plot("D:\\1D_legend_demo.svg");
+ svg_plot my_plot;
 
- my_plot.image_size(500, 350).x_scale(-2, 10);
-
- my_plot.draw_axis().show_legend();
-
- my_plot.set_background_color(lightgray)
- .set_legend_background_color(whitesmoke);
+ // size/scale settings
+ my_plot.set_image_size(500, 350)
+ .set_x_scale(-3, 10);
+
+ // Text settings
+ my_plot.set_title("Oh My!")
+ .set_title_font_size(29)
+ .set_x_label_text("Time in Months");
+
+ // command settings
+ my_plot.set_axis(true)
+ .set_legend(true)
+ .set_plot_window(true)
+ .set_x_label(true)
+ .set_x_major_labels(true);
+
+ // color settings
+ my_plot.set_background_color(svg_color(67, 111, 69))
+ .set_legend_background_color(svg_color(207, 202,167))
+ .set_plot_background_color(svg_color(136, 188, 126))
+ .set_title_color(white)
+ .set_x_axis_color(black)
+ .set_x_major_tick_color(black)
+ .set_x_minor_tick_color(black);
+
+ //axis settings
+ my_plot.set_x_major_tick(2)
+ .set_x_num_minor_ticks(3)
+ .set_x_major_tick_length(14)
+ .set_x_minor_tick_length(7)
+ .set_x_major_tick_width(1)
+ .set_x_minor_tick_width(1);
+
+ //legend settings
+ my_plot.set_legend_title_font_size(15);
+
+ plot_range(my_plot, data2.begin(), data2.end(), "Lions", blue);
+ plot_range(my_plot, data1.begin(), data1.end(), "Tigers", purple);
+ plot_range(my_plot, data3.begin(), data3.end(), "Bears", red);
 
-
- plot_range(my_plot, data2.begin(), data2.end(), "Lions", blue);
- plot_range(my_plot, data1.begin(), data1.end(), "Tigers", limegreen);
-
- my_plot.write();
+ my_plot.write("D:\\1D_legend_demo.svg");
 
     return 0;
 }


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