Browse files

Layout sketched.

Still not tested.
  • Loading branch information...
1 parent 31fdf9e commit d5073bec9083c7f67e94756a6d12e475a8fc1b42 @dacav committed Jun 20, 2010
Showing with 375 additions and 278 deletions.
  1. +22 −0 README
  2. +13 −0 src/drawable.cpp
  3. +11 −172 src/gnuplot.cpp
  4. +1 −0 src/gnupplus.hpp
  5. +21 −0 src/gnupplus/drawable.hpp
  6. +6 −9 src/gnupplus/gnuplot.hpp
  7. +48 −13 src/gnupplus/layout.hpp
  8. +36 −39 src/gnupplus/plots.hpp
  9. +112 −37 src/layout.cpp
  10. +105 −8 src/plots.cpp
View
22 README
@@ -0,0 +1,22 @@
+
+
+
+** -------------------------------------------------------------------- **
+** Technical Reference **
+** -------------------------------------------------------------------- **
+
+ (1) Every instance of a GnuPlot class corresponds to the spawn of a
+ gnuplot process which takes commands through a unix pipe.
+
+ (2) The GnuPlot class defines by default a Layout internal instance
+ which can be replaced by the setLayout() method.
+ The default Layout provides a simple 1×1 subdivision of the canvas.
+
+ (3) Any element which is able to modify somehow the canvas must be a
+ subclass of the Drawable abstract class. This forces to implement
+ three methods: init(), display() and reset(), which respectively
+ prepare the canvas, display what must be displayed and reset the
+ canvas to the previous settings. The Drawable class also implements a
+ run() method which executes sequentially init(), display() and
+ reset(). The use of run() is not mandatory.
+
View
13 src/drawable.cpp
@@ -0,0 +1,13 @@
+#include <gnupplus/drawable.hpp>
+
+namespace gnup {
+
+ void Drawable::run (Comm *c)
+ {
+ init(c);
+ display(c);
+ reset(c);
+ }
+
+}
+
View
183 src/gnuplot.cpp
@@ -24,193 +24,32 @@
namespace gnup {
- Plot::Plot (const char *tit)
- {
- trigger = NULL;
- title = tit;
- style = LINES;
- auto_update = true;
- max_size = -1;
- }
-
- Plot::~Plot ()
- {
- DataSet::iterator i, end;
-
- end = data.end();
- for (i = data.begin(); i != end; i ++) {
- delete[] *i;
- }
- }
-
- void Plot::addVector (float *vals)
- {
- size_t n = getDimension();
- float *v = new float[n];
-
- memcpy((void *)v, (void *)vals, n * sizeof(float));
-
- data.push_back(v);
- if (max_size && data.size() > max_size) {
- data.pop_front();
- }
- if (auto_update && trigger) {
- trigger->trig();
- }
- }
-
- void Plot::setTrigger (Trigger *t)
- {
- trigger = t;
- }
-
- void Plot::writePlotting (Comm *c)
- {
- writePlotting(c, data.begin(), data.end());
- }
-
- const char * Plot::getTitle ()
- {
- return title;
- }
-
- void Plot::setStyle (style_t s)
- {
- style = s;
- }
-
- void Plot::writeStyle (Comm *c)
- {
- const char *sn;
-
- switch (style) {
- case POINTS:
- sn = "points";
- break;
- case LINESPOINTS:
- sn = "linespoints";
- break;
- case IMPULSES:
- sn = "impulses";
- break;
- case DOTS:
- sn = "dots";
- break;
- case STEPS:
- sn = "steps";
- break;
- case ERRORBARS:
- sn = "errorbars";
- break;
- case BOXES:
- sn = "boxes";
- break;
- case BOXERRORBARS:
- sn = "boxerrorbars";
- break;
- case LINES:
- default:
- sn = "lines";
- break;
- }
- c->command("with %s ", sn);
- }
-
- void Plot::setAutoUpdate (bool au)
- {
- auto_update = au;
- }
-
- void Plot::setOverflow (size_t max)
- {
- max_size = max;
- }
-
- GnuPlot::GnuPlot (size_t dims, const char *prog) throw (CommError)
+ GnuPlot::GnuPlot (const char *prog) throw (CommError)
: Comm(prog, true)
{
- dimensions = dims;
+ layout = new Layout(1, 1);
}
- void GnuPlot::addSource (Plot &src) throw (PlotError)
+ GnuPlot::~GnuPlot ()
{
- if (src.getDimension() > dimensions) {
- PlotError err("Too many dimensions");
- throw err;
- } else {
- sources.push_back(&src);
- src.setTrigger(this);
- }
- }
-
- void GnuPlot::initPlotting ()
- {
- size_t size;
- std::list<Plot *>::iterator i, end;
-
- // Format initialization phase: gnuplot must know in advance which
- // plots must be achieved.
- switch (dimensions) {
- case 0:
- // Nothing to plot (it should never be the case)
- return;
- case 1:
- case 2:
- command("plot ");
- break;
- default:
- command("splot ");
- }
-
- i = sources.begin();
- end = sources.end();
- size = sources.size();
- // We know that this operation will be achieved at least once,
- // since size > 0
- do {
- Plot *src = *i;
- const char *title = src->getTitle();
-
- command("\"-\" ");
- if (title != NULL) command("title \"%s\" ", title);
- else command("notitle");
-
- // Plot specific data settings:
- src->writeFormat(this);
- src->writeStyle(this);
-
- if (--size) {
- // This puts the comma between two plotting indications.
- command(", ");
- }
- } while ((++ i) != end);
- command("\n");
+ delete layout;
}
void GnuPlot::trig ()
{
- std::list<Plot *>::iterator i, end;
-
- if (sources.size() == 0) {
- // Nothing to plot...
- return;
- }
-
- initPlotting();
-
- // Actual plotting phase
- for (i = sources.begin(); i != sources.end(); i ++) {
- Plot *src = *i;
- src->writePlotting(this);
- // Terminate data set
- command("e\n");
- }
+ // TODO
}
void GnuPlot::clear ()
{
command("clear");
}
+ void GnuPlot::setLayout (Layout *l)
+ {
+ delete layout;
+ layout = l;
+ }
+
}
View
1 src/gnupplus.hpp
@@ -18,6 +18,7 @@
*
*/
+#include <gnupplus/drawable.hpp>
#include <gnupplus/layout.hpp>
#include <gnupplus/pipe.hpp>
#include <gnupplus/except.hpp>
View
21 src/gnupplus/drawable.hpp
@@ -0,0 +1,21 @@
+#ifndef __defined_gnupplus_drawable_hpp
+#define __defined_gnupplus_drawable_hpp
+
+#include <gnupplus/pipe.hpp>
+
+namespace gnup {
+
+ class Drawable {
+ public:
+ void run (Comm *c);
+
+ protected:
+ virtual void init (Comm *c) = 0;
+ virtual void display (Comm *c) = 0;
+ virtual void reset (Comm *c) = 0;
+ };
+
+}
+
+#endif // __defined_gnupplus_drawable_hpp
+
View
15 src/gnupplus/gnuplot.hpp
@@ -22,7 +22,7 @@
#define __defined_gnup_gp_base_hpp
#include <gnupplus/pipe.hpp>
-#include <gnupplus/plots.hpp>
+#include <gnupplus/layout.hpp>
#include <list>
#include <stdint.h>
@@ -31,20 +31,17 @@ namespace gnup {
class GnuPlot : public Comm, Trigger {
public:
- GnuPlot (size_t dimensions,
- const char *prog = "gnuplot") throw (CommError);
- void trig ();
- void addSource (Plot &src) throw (PlotError);
+ GnuPlot (const char *prog = "gnuplot") throw (CommError);
+ ~GnuPlot ();
+ void trig ();
void clear ();
+ void setLayout (Layout *l);
private:
- std::list<Plot *> sources;
- size_t dimensions;
-
- void initPlotting ();
+ Layout *layout;
};
}
View
61 src/gnupplus/layout.hpp
@@ -7,11 +7,15 @@
#include <stdint.h>
+#include <gnupplus/drawable.hpp>
#include <gnupplus/plots.hpp>
#include <gnupplus/pipe.hpp>
+#include <gnupplus/except.hpp>
namespace gnup {
+ typedef std::pair<unsigned, unsigned> Coords;
+
/** Layout cell
*
* The graph will be subdivided into cells basing on the layout
@@ -23,10 +27,11 @@ namespace gnup {
* Basically this is a list of plots of a single cell, but it's
* characterized by some graph-related characteistics.
*/
- class Cell : public std::list<Plot *> {
+ class Cell : public std::list<Plot *>, public Drawable {
public:
- Cell (const char *title = NULL);
+
+ Cell ();
void setXLabel (const char *label);
void setYLabel (const char *label);
@@ -38,8 +43,15 @@ namespace gnup {
void writeSettings (Comm *c);
void resetSettings (Comm *c);
+ void draw (Comm *c);
+
+ void addPlot (Plot &p);
+ void setTitle (const char *title);
private:
+
+ size_t dimensions;
+
const char *title;
struct {
const char *x, *y, *z;
@@ -58,39 +70,62 @@ namespace gnup {
static const uint8_t LABEL_Y = 1 << 4;
static const uint8_t LABEL_Z = 1 << 5;
+ std::list<Plot *> plots;
+
+ void init (Comm *c);
+ void display (Comm *c);
+ void reset (Comm *c);
+
};
/** From cell coordinate to plot.
*
* Like an umbounded matrix.
*/
- typedef std::map<std::pair<unsigned, unsigned>, Cell *> CellMap;
+ typedef std::map<Coords, Cell *> CellMap;
+
+ /** Exception for layout */
+ class LayoutError : public Error {
+ public:
+ /** Constructor.
+ *
+ * @param msg The error message.
+ */
+ LayoutError (const char *msg) throw() : Error(msg) {}
+ };
- class Layout {
+ class Layout : public Drawable {
public:
- Layout ();
+ Layout (size_t nrows, size_t ncols);
virtual ~Layout ();
+ void draw (Comm *c);
- void setColumns (size_t nc);
- void setRows (size_t nr);
+ void setTrigger (Trigger *trig);
+ Trigger *getTrigger ();
- void draw (Comm *c);
+ void addPlot (Plot &p, unsigned row, unsigned col)
+ throw (LayoutError);
+
+ Cell * getCell (unsigned row, unsigned col)
+ throw (LayoutError);
private:
+
+ void init (Comm *c);
+ void display (Comm *c);
+ void reset (Comm *c);
+
size_t ncols;
size_t nrows;
CellMap cells;
void drawCell (Comm *c, Cell *cell, unsigned row,
unsigned col);
- };
-
- // void setLabel (char which, const char *label);
- // void setRange (char which, float min, float max);
-
+ Trigger *trig;
+ };
}
View
75 src/gnupplus/plots.hpp
@@ -23,6 +23,7 @@
#include <gnupplus/except.hpp>
#include <gnupplus/pipe.hpp>
+#include <gnupplus/drawable.hpp>
#include <list>
#include <stdint.h>
@@ -66,7 +67,7 @@ namespace gnup {
* GnuPlot class. The ones which are meant for external access will be
* marked in the comment.
*/
- class Plot {
+ class Plot : public Drawable {
public:
@@ -87,23 +88,6 @@ namespace gnup {
BOXERRORBARS /**< Plot boxes and error bars */
};
- /** Writer for the plotting sequence.
- *
- * Used by a gnup::GnuPlot instance in order to get the
- * plotting data sequence for the 'plot' command.
- *
- * This method must be implemented by the extending class
- * depending on the specific plotting semantics.
- *
- * @see gnup::2DPlot and gnup::3DPlot.
- *
- * @param c The communication channel;
- * @param begin The stdlib iterator for start of the list;
- * @param end The stdlib iterator for end of the list.
- */
- virtual void writePlotting (Comm *c, DataSet::iterator begin,
- DataSet::iterator end) = 0;
-
/** Returns the title of the plotting.
*
* This method will be used by the gnup::GnuPlot class in
@@ -121,16 +105,7 @@ namespace gnup {
* The trigger allows to signal new data. This method is used
* by a GnuPlot instance in order to link the Plot.
*/
- void setTrigger (Trigger *t);
-
- /** Writer for the plotting sequence.
- *
- * This method simply calls the other overrided writePlotting
- * with gnup::Plot::data begin and end iterators.
- *
- * @param c The communication channel;
- */
- void writePlotting (Comm *c);
+ void setTriggerPtr (Trigger **t);
/** Dimension of the plot.
*
@@ -158,18 +133,17 @@ namespace gnup {
*/
void setAutoUpdate (bool au);
- /** Used by a GnuPlot instance in order to get the plotting
- * format for the 'plot' command.
- */
- virtual void writeFormat (Comm *c) = 0;
-
/** Set the maximum length of the internal data list.
*
* @param max The max length. Set it to 0 in order to keep all
* data.
*/
void setOverflow (size_t max);
+ void init (Comm *c);
+ void display (Comm *c);
+ void reset (Comm *c);
+
protected:
Plot (const char *title);
@@ -186,26 +160,49 @@ namespace gnup {
DataSet data;
+ /** Writer for the plotting sequence.
+ *
+ * Used by a gnup::GnuPlot instance in order to get the
+ * plotting data sequence for the 'plot' command.
+ *
+ * This method must be implemented by the extending class
+ * depending on the specific plotting semantics.
+ *
+ * @see gnup::2DPlot and gnup::3DPlot.
+ *
+ * @param c The communication channel;
+ * @param begin The stdlib iterator for start of the list;
+ * @param end The stdlib iterator for end of the list.
+ */
+ virtual void display (Comm *c, DataSet::iterator begin,
+ DataSet::iterator end) = 0;
+
private:
const char *title;
- Trigger *trigger;
+
+ /** A double-pointer to the gnup::Trigger
+ *
+ * This allows the gnup::Layout class to change its trigger
+ * without caring about all internal plots, which will be
+ * automatically updated.
+ */
+ Trigger **trigger;
style_t style;
bool auto_update;
size_t max_size;
};
-
enum axis_t { DATA, AUTO };
class Plot2D : public Plot {
public:
Plot2D (const char *title, axis_t x, axis_t y);
- void writePlotting (Comm *c, DataSet::iterator begin,
- DataSet::iterator end);
+ void display (Comm *c, DataSet::iterator begin,
+ DataSet::iterator end);
size_t getDimension ();
@@ -224,8 +221,8 @@ namespace gnup {
public:
Plot3D (const char *title, axis_t x, axis_t y, axis_t z);
- void writePlotting (Comm *c, DataSet::iterator begin,
- DataSet::iterator end);
+ void display (Comm *c, DataSet::iterator begin,
+ DataSet::iterator end);
size_t getDimension ();
View
149 src/layout.cpp
@@ -1,12 +1,19 @@
#include <gnupplus/layout.hpp>
+using std::make_pair;
+
namespace gnup {
- Cell::Cell (const char *t)
+ Cell::Cell ()
: std::list<Plot *>()
{
- title = t;
flags = 0;
+ dimensions = 0;
+ }
+
+ void Cell::setTitle (const char *t)
+ {
+ title = t;
}
void Cell::setXLabel (const char *label)
@@ -48,87 +55,155 @@ namespace gnup {
flags |= RANGE_Z;
}
- void Cell::writeSettings (Comm *c)
+ void Cell::init (Comm *c)
{
const char * set = "set %crange [%f:%f]\n";
- if (flags & RANGE_X)
+ if (flags & RANGE_X) {
c->command(set, 'x', ranges.x.min, ranges.x.max);
- if (flags & RANGE_Y)
+ }
+ if (flags & RANGE_Y) {
c->command(set, 'y', ranges.y.min, ranges.y.max);
- if (flags & RANGE_Z)
+ }
+ if (flags & RANGE_Z) {
c->command(set, 'z', ranges.z.min, ranges.z.max);
+ }
- if (title)
+ if (title != NULL) {
c->command("set title \"%s\"\n", title);
+ }
}
- void Cell::resetSettings (Comm *c)
+ void Cell::display (Comm *c)
+ {
+ std::list<Plot *>::iterator i,
+ end = plots.end();
+
+ if (plots.size() == 0) {
+ return;
+ }
+
+ c->command(dimensions > 2 ? "splot " : "plot ");
+ for (i = plots.begin(); i != end; i ++) {
+ (*i)->init(c);
+ }
+ c->command("\n");
+ for (i = plots.begin(); i != end; i ++) {
+ (*i)->display(c);
+ (*i)->reset(c);
+ }
+ }
+
+ void Cell::reset (Comm *c)
{
const char * restore = "set %crange restore\n";
if (flags & RANGE_X) c->command(restore, 'x');
if (flags & RANGE_Y) c->command(restore, 'y');
if (flags & RANGE_Z) c->command(restore, 'z');
- }
- Layout::Layout ()
- {
- ncols = nrows = 1;
+ if (title != NULL) {
+ c->command("set title\n");
+ }
}
- Layout::~Layout ()
+ void Cell::addPlot (Plot &p)
{
+ size_t dim = p.getDimension();
+ if (dimensions == 0) {
+ dimensions = dim;
+ } else if (dim != dimensions) {
+ PlotError err ("Inconsistent dimension for cell");
+ throw err;
+ }
+ plots.push_back(&p);
}
- void Layout::setColumns (size_t nc)
+ Layout::Layout (size_t nr, size_t nc)
{
+ nrows = nr;
ncols = nc;
}
- void Layout::setRows (size_t nr)
+ Layout::~Layout ()
{
- nrows = nr;
+ CellMap::iterator i, end;
+
+ end = cells.end();
+ for (i = cells.begin(); i != end; i ++) {
+ delete i->second;
+ }
}
- void Layout::draw (Comm *c)
+ void Layout::init (Comm *c)
{
- unsigned row, col;
- bool multiplot = nrows + ncols > 2;
-
- if (multiplot) {
+ if (nrows + ncols > 2) {
c->command("set multiplot\n");
c->command("set size %f,%f\n", 1.0 / ncols, 1.0 / nrows);
}
+ }
+
+ void Layout::display (Comm *c)
+ {
+ unsigned row, col;
for (row = 0; row < nrows; row ++) {
for (col = 0; col < ncols; col ++) {
- std::pair<unsigned, unsigned> coords;
Cell *cell;
-
- coords.first = row;
- coords.second = col;
-
- if ((cell = cells[coords]) != NULL) {
- drawCell(c, cell, row, col);
+ if ((cell = cells[make_pair(row, col)]) != NULL) {
+ c->command("set origin %f,%f\n", (float)col / ncols,
+ (float)row / nrows);
+ cell->run(c);
}
}
}
- if (!multiplot) {
- c->command("unset multiplot\n");
+ }
+
+ void Layout::reset (Comm *c)
+ {
+ if (nrows + ncols > 2) {
c->command("set size 1,1");
+ c->command("unset multiplot\n");
}
}
- void Layout::drawCell (Comm *c, Cell *cell, unsigned row,
- unsigned col)
+ void Layout::setTrigger (Trigger *t)
+ {
+ trig = t;
+ }
+
+ Cell * Layout::getCell (unsigned row, unsigned col)
+ throw (LayoutError)
+ {
+ if (row < nrows && col < ncols) {
+ Coords coords = make_pair(row, col);
+ Cell *ret;
+
+ ret = cells[coords];
+ if (ret == NULL) {
+ ret = new Cell();
+ cells[coords] = ret;
+ }
+ return ret;
+
+ } else {
+ LayoutError err ("Trying to plot outside the boundary");
+ throw err;
+ }
+ }
+
+ void Layout::addPlot (Plot &p, unsigned row, unsigned col)
+ throw (LayoutError)
+ {
+ Cell *c = getCell(row, col);
+ p.setTriggerPtr(&trig);
+ c->addPlot(p);
+ }
+
+ Trigger * Layout::getTrigger ()
{
- c->command("set origin %f,%f\n", (float)col / ncols,
- (float)row / nrows);
- cell->writeSettings(c);
- // TODO plot
- cell->resetSettings(c);
+ return trig;
}
}
View
113 src/plots.cpp
@@ -20,9 +20,110 @@
#include <gnupplus/plots.hpp>
#include <gnupplus/gnuplot.hpp>
+#include <cstring>
namespace gnup {
+ Plot::Plot (const char *tit)
+ {
+ trigger = NULL;
+ title = tit;
+ style = LINES;
+ auto_update = true;
+ max_size = -1;
+ }
+
+ Plot::~Plot ()
+ {
+ DataSet::iterator i, end;
+
+ end = data.end();
+ for (i = data.begin(); i != end; i ++) {
+ delete[] *i;
+ }
+ }
+
+ void Plot::addVector (float *vals)
+ {
+ size_t n = getDimension();
+ float *v = new float[n];
+
+ memcpy((void *)v, (void *)vals, n * sizeof(float));
+
+ data.push_back(v);
+ if (max_size && data.size() > max_size) {
+ data.pop_front();
+ }
+ if (auto_update && trigger) {
+ (*trigger)->trig();
+ }
+ }
+
+ void Plot::init (Comm *c)
+ {
+ const char *sn;
+ switch (style) {
+ case POINTS:
+ sn = "points";
+ break;
+ case LINESPOINTS:
+ sn = "linespoints";
+ break;
+ case IMPULSES:
+ sn = "impulses";
+ break;
+ case DOTS:
+ sn = "dots";
+ break;
+ case STEPS:
+ sn = "steps";
+ break;
+ case ERRORBARS:
+ sn = "errorbars";
+ break;
+ case BOXES:
+ sn = "boxes";
+ break;
+ case BOXERRORBARS:
+ sn = "boxerrorbars";
+ break;
+ case LINES:
+ default:
+ sn = "lines";
+ break;
+ }
+ c->command("\"-\" with %s ", sn);
+ }
+
+ void Plot::reset (Comm *c)
+ {
+ }
+
+ void Plot::setTriggerPtr (Trigger **t)
+ {
+ trigger = t;
+ }
+
+ void Plot::display (Comm *c)
+ {
+ display(c, data.begin(), data.end());
+ }
+
+ void Plot::setStyle (style_t s)
+ {
+ style = s;
+ }
+
+ void Plot::setAutoUpdate (bool au)
+ {
+ auto_update = au;
+ }
+
+ void Plot::setOverflow (size_t max)
+ {
+ max_size = max;
+ }
+
Plot2D::Plot2D (const char *title, axis_t x, axis_t y)
: Plot(title)
{
@@ -34,8 +135,8 @@ namespace gnup {
if (y == DATA) realsize ++;
}
- void Plot2D::writePlotting (Comm *c, DataSet::iterator b,
- DataSet::iterator e)
+ void Plot2D::display (Comm *c, DataSet::iterator b,
+ DataSet::iterator e)
{
// Alternative (incremental) value for the y axis (if not
// specified).
@@ -94,8 +195,8 @@ namespace gnup {
Plot::addVector(v);
}
- void Plot3D::writePlotting (Comm *c, DataSet::iterator b,
- DataSet::iterator e)
+ void Plot3D::display (Comm *c, DataSet::iterator b,
+ DataSet::iterator e)
{
// Alternative (incremental) values for the x and y axis (if not
// specified).
@@ -112,9 +213,5 @@ namespace gnup {
}
}
- void Plot3D::writeFormat (Comm *c)
- {
- }
-
}

0 comments on commit d5073be

Please sign in to comment.