plot.h
1 /*
2  @copyright Russell Standish 2000-2013
3  @author Russell Standish
4  This file is part of EcoLab
5 
6  Open source licensed under the MIT license. See LICENSE for details.
7 */
8 
9 #ifndef PLOT_H
10 #define PLOT_H
11 
12 #include "classdesc.h"
13 #include "classdesc_access.h"
14 #include "TCL_obj_base.h"
15 #include "arrays.h"
16 
17 #include <string>
18 #include <vector>
19 #include <cairo_base.h>
20 
21 namespace ecolab
22 {
23  namespace cairo
24  {
25  struct Colour
26  {
27  double r, g, b, a;
28  };
29 
30  }
31 
32  extern cairo::Colour palette[];
33  extern const int paletteSz;
34 
35  class Plot
36  {
37  public:
38  // transform y coordinates (handles RHS being a different scale, as
39  // well as manual scaling for minsky ticket #693)
40  struct XFY
41  {
42  bool logy;
43  double scale, o, o1;
44  XFY():logy(false), scale(1), o(0), o1(0) {}
45  XFY(bool logy, double scale, double o, double o1):
46  logy(logy), scale(scale), o(logy? log10(o): o), o1(o1) {
47  }
48  double operator()(double y) const {
49  return scale*((logy? log10(y): y)-o)+o1;
50  }
51  };
52  private:
53  string m_image;
54  std::vector<std::vector<double> > x;
55  std::vector<std::vector<double> > y;
56  //classdesc::shared_ptr<cairo::TkPhotoSurface> surface;
57  cairo::SurfacePtr surface;
58 
59 
60 
62 
63  // internal common routine for add()
64  void addNew(cairo::Surface& surf, bool doRedraw,
65  const unsigned *startPen, const unsigned *finishPen, int numPt);
66 
67  double iflogx(double x) const {return logx? log10(x): x;}
68  double iflogy(double y) const {return logy? log10(y): y;}
69 
73  void drawGrid(cairo_t* cairo, double tick, double increment, bool vertical, const XFY&) const;
74 
75  void drawLegend(cairo_t*, double width, double height) const;
76 
77  void labelAxes(cairo_t*, double width, double height) const;
78 
79  bool inBounds(float x, float y) const {
80  return x>=minx && x<=maxx && y>=miny && y<=maxy;
81  }
82 
83  bool displayRHSscale() const {
84  return !penSide.empty() && miny1<maxy1;
85  }
86  public:
87  enum Side {left, right};
88  enum PlotType {line, bar};
89 
90  Plot(): nxTicks(30), nyTicks(30), fontScale(1),
91  offx(0), offy(0), logx(false), logy(false),
92  grid(false), subgrid(false),
93  leadingMarker(false), autoscale(true),
94  legend(false), legendSide(right), plotType(line),
95  minx(-1), maxx(1), miny(-1), maxy(1), miny1(1), maxy1(-1)
96  {}
97  virtual ~Plot() {}
98 
99  int nxTicks, nyTicks;
100  double fontScale;
101  double offx, offy;
102  bool logx, logy;
103  bool grid, subgrid;
105  bool autoscale;
106  bool legend;
107  Side legendSide;
108  PlotType plotType;
110  string xlabel, ylabel, y1label;
111 
113  double labelheight() const {return lh(width(), height());}
114  double lh(double width, double height) const;
115 
116  cairo_surface_t* cairoSurface() const;
117  int width() const;
118  int height() const;
120  double minx, maxx, miny, maxy, miny1, maxy1;
121 
123  void setMinMax();
124 
126  string Image() const {return m_image;}
127  string Image(const string& im, bool transparency=true);
128  string image(TCL_args args) {
129  if (args.count>0)
130  {
131  string imgName=args.str();
132  bool transparency=true;
133  if (args.count) transparency=args;
134  return Image(imgName,transparency);
135  }
136  else
137  return Image();
138  }
139 
141  void redraw();
143  virtual void draw(cairo::Surface&);
144  void draw(cairo_t*, double width, double height) const;
146  void clear();
147 
149  void add(unsigned pen, double x, double y)
150  {if (surface) add(*surface,pen,x,y);}
151  void add(cairo::Surface&, unsigned pen, double x, double y);
153  template <class C>
154  void add(unsigned pen, const C& x, const C& y)
155  {if (surface) add(*surface,pen,x,y);}
156  template <class C>
157  void add(cairo::Surface& surf, unsigned pen, const C& x1, const C& y1)
158  {
159  assert(x1.size()==y1.size());
160  bool doRedraw=false;
161  if (pen>=x.size())
162  {
163  x.resize(pen+1);
164  y.resize(pen+1);
165  }
166  for (size_t i=0; i<x1.size(); ++i)
167  {
168  doRedraw|=x1[i]<minx||x1[i]>maxx || y1[i]<miny||y1[i]>maxy;
169  x[pen].push_back(x1[i]);
170  y[pen].push_back(y1[i]);
171  }
172  addNew(surf,doRedraw,&pen,&pen+1,x1.size());
173  }
174 
176  void add(const array_ns::array<unsigned>& pens, double x,
177  const array_ns::array<double>& y)
178  {if (surface) add(*surface,pens,x,y);}
179  void add(cairo::Surface& surf,
180  const array_ns::array<unsigned>& pens,
181  double x1, const array_ns::array<double>& y1);
182 
185  void labelPen(unsigned pen, const string& label);
187  void LabelPen(unsigned pen, const cairo::SurfacePtr& label);
188 
190  void AssignSide(unsigned pen, Side);
191 
192  // void labelPen(TCL_args args) {LabelPen(int(args[0]), (char*)args[1]);}
193  void assignSide(TCL_args args) {
194  AssignSide(args[0], args[1].get<Side>());
195  }
196 
199  penLabel.clear(); penTextLabel.clear(); penSide.clear();
200  }
201 
203  void plot(TCL_args args);
204 
205  //serialisation support (surface is not auto-serialisable)
206  void pack(classdesc::pack_t& p) const {p<<m_image<<x<<y<<minx<<maxx<<miny<<maxy;}
207 
208  void unpack(classdesc::pack_t& p) {
209  p>>m_image>>x>>y>>minx>>maxx>>miny>>maxy;
210  Image(m_image);
211  }
212 
213  // add a point to the graph withour redrwaing anything
214  void addPt(unsigned pen, double x, double y);
215 
216  private:
217  std::vector<cairo::SurfacePtr> penLabel;
218  std::vector<string> penTextLabel;
219  // if this is empty, all pens are on the left, and no RHS scale is drawn
220  std::vector<Side> penSide;
221  };
222 }
223 
224 namespace classdesc_access
225 {
226  template <> struct access_pack<ecolab::Plot>
227  {
228  template <class U>
229  void operator()(classdesc::pack_t& p, const classdesc::string& d, U& a)
230  {a.pack(p);}
231  };
232 
233  template <> struct access_unpack<ecolab::Plot>
234  {
235  template <class U>
236  void operator()(classdesc::pack_t& p, const classdesc::string& d, U& a)
237  {a.unpack(p);}
238  };
239 }
240 
241 #include "plot.cd"
242 #ifdef _CLASSDESC
243 #pragma omit pack ecolab::Plot
244 #pragma omit unpack ecolab::Plot
245 #endif
246 #endif
Definition: plot.h:40
descriptor access to a class&#39;s privates
void add(unsigned pen, const C &x, const C &y)
add multiple points (C=container - eg vector/array)
Definition: plot.h:154
double minx
plot bounding box. y1 refers to the right hand scale
Definition: plot.h:120
bool legend
add a legend to the plot
Definition: plot.h:106
Definition: plot.h:35
double offy
origin of plot within image
Definition: plot.h:101
bool subgrid
draw grid options
Definition: plot.h:103
string xlabel
axis labels
Definition: plot.h:110
class to allow access to private members
Definition: classdesc_access.h:21
dynamic array class
void add(unsigned pen, double x, double y)
add a datapoint
Definition: plot.h:149
double labelheight() const
height (or width) of an axis label in pixels
Definition: plot.h:113
Definition: plot.h:25
class to allow access to private members
Definition: classdesc_access.h:22
#define CLASSDESC_ACCESS(type)
add friend statements for each accessor function
Definition: classdesc_access.h:36
void clearPenAttributes()
remove all pen labels and side associations
Definition: plot.h:198
Represent arguments to TCL commands.
Definition: TCL_obj_base.h:138
TCL access descriptor.
bool autoscale
autoscale plot to data
Definition: plot.h:105
Side legendSide
legend drawn towards the left or right
Definition: plot.h:107
string Image() const
set/get the Tk image that this class writes to.
Definition: plot.h:126
Definition: pack_base.h:124
Definition: TCL_obj_base.h:124
void add(const array_ns::array< unsigned > &pens, double x, const array_ns::array< double > &y)
add multiple pens worth of data in one hit
Definition: plot.h:176
_OPENMP
Definition: accessor.h:16
bool leadingMarker
draw a leading marker on the curve (full draw only)
Definition: plot.h:104
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition: accessor.h:55
bool logy
logarithmic plots (x/y axes)
Definition: plot.h:102
int nyTicks
number of x/y-axis ticks
Definition: plot.h:99
double fontScale
scale tick labels
Definition: plot.h:100