Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
GraphPlotter.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include <Base/Common/W32Compat.hh>
26 #include <Base/ImageUtils/ImageDraw.hh>
27 #include "GraphPlotter.hh"
28 
29 using namespace BIAS;
30 using namespace std;
31 
32 
33 // constructor
36 {
37  width_ = 1024;
38  height_ = 768;
39  xOffset_ = 0;
40  yOffset_ = 0;
41  xTics_ = yTics_ = 10;
42  xMin_=yMin_=DBL_MAX;
43  xMax_=yMax_=DBL_MIN;
44  xLabel_="x";
45  yLabel_="y";
46  bDrawGrid_ = false;
47  bAutoDetectBordersX_=true;
48  bAutoDetectBordersY_=true;
49  bPrepared_ = false;
50  bFixXAxisToBottom_=true;
51  bFixYAxisToLeft_=true;
52  dLineThickness_ = 1;
53  dTextThickness_ = 1;
54 }
55 
56 // destructor
59 {
60  if(!image_.IsEmpty())
61  image_.Release();
62 }
63 
64 
67  return &image_;
68 }
69 
72  return image_;
73 }
74 
75 
76 void GraphPlotter::
77 SetXRange(double minX, double maxX){
78  if(minX > maxX){
79  xMin_ = maxX;
80  xMax_ = minX;
81  }else{
82  xMin_ = minX;
83  xMax_ = maxX;
84  }
85  bAutoDetectBordersX_=false;
86 }
87 
88 void GraphPlotter::
89 SetYRange(double minY, double maxY){
90  if(minY > maxY){
91  yMin_ = maxY;
92  yMax_ = minY;
93  }else{
94  yMin_ = minY;
95  yMax_ = maxY;
96  }
97  bAutoDetectBordersY_=false;
98 }
99 
100 void GraphPlotter::
101 SetXTics(unsigned xtics){
102  xTics_ = xtics;
103 }
104 
105 void GraphPlotter::
106 SetYTics(unsigned ytics){
107  yTics_ = ytics;
108 }
109 
110 void GraphPlotter::
111 SetXLabel(std::string label){
112  xLabel_=label;
113 }
114 
115 void GraphPlotter::
116 SetYLabel(std::string label){
117  yLabel_=label;
118 }
119 
120 void GraphPlotter::
121 SetImageSize(unsigned width, unsigned height){
122  width_ = width;
123  height_ = height;
124 }
125 
126 void GraphPlotter::
127 SetDrawGrid(bool drawGrid){
128  bDrawGrid_=drawGrid;
129 }
130 
131 
132 void GraphPlotter::
134  bFixXAxisToBottom_=fixAxes;
135  bFixYAxisToLeft_=fixAxes;
136 }
137 
138 void GraphPlotter::
139 SetLineThickness(unsigned thickness){
140  dLineThickness_ = thickness;
141 }
142 
143 void GraphPlotter::
144 SetTextThickness(unsigned thickness){
145  dTextThickness_ = thickness;
146 }
147 
148 void GraphPlotter::
150  width_ = 1024;
151  height_ = 768;
152  xOffset_ = 0;
153  yOffset_ = 0;
154  xTics_ = yTics_ = 10;
155  xMin_=yMin_=0.0;
156  xMax_=yMax_=1000.0;
157  xLabel_="x";
158  yLabel_="y";
159  bDrawGrid_ = false;
160  bAutoDetectBordersX_=true;
161  bAutoDetectBordersY_=true;
162  bPrepared_ = false;
163  bFixXAxisToBottom_=true;
164  bFixYAxisToLeft_=true;
165  dLineThickness_ = 1;
166  dTextThickness_ = 1;
167 }
168 
169 void GraphPlotter::
171 
172  BIAS::ColourRGB<unsigned char> black(0,0,0);
173  BIAS::ColourRGB<unsigned char> white(255,255,255);
174  BIAS::ColourRGB<unsigned char> red(255,0,0);
175 
176  xCoeff_ = width_/(xMax_-xMin_);
177  yCoeff_ = height_/(yMax_-yMin_);
178 
179  // cout<<"xCoeff_:"<<xCoeff_<<" xMax:"<<xMax_<<endl;
180  // cout<<"yCoeff_:"<<yCoeff_<<" yMax:"<<yMax_<<endl;
181 
182  //TODO calc offsets correctly
183  xOffset_ = int(-rint(xMin_*xCoeff_))+10;
184  yOffset_ = int(rint(yMin_*yCoeff_))+height_-20;
185 
186  // cout<<"xOffset:"<<xOffset_<<endl;
187  // cout<<"yOffset:"<<yOffset_<<endl;
188 
189  if(!image_.IsEmpty()) image_.Release();
190 
191  image_.Init(width_,height_,3);
192  unsigned char color[] ={255,255,255};
193  image_.FillImageWithConstValue(color);
194 
195  int xAxisInc = abs(int(rint((xMax_-xMin_)/double(xTics_))));
196  int yAxisInc = abs(int(rint((yMax_-yMin_)/double(yTics_))));
197 
198  //check if axis is in image, if not set to 10 pixels from left
199  unsigned int xTicsPos = 0;
200  if(yOffset_>=10 && yOffset_ < (int)height_-20)
201  xTicsPos = yOffset_;
202  else
203  xTicsPos = height_-20;
204 
205  if(bFixXAxisToBottom_)
206  xTicsPos = height_-20;
207 
208  //draw 0-x line
210  0,//x
211  yOffset_,//y
212  width_, //x end
213  yOffset_, //y end
214  black,dLineThickness_);
215 
216  //x-axis line
218  0,//x
219  xTicsPos,//y
220  width_, //x end
221  xTicsPos, //y end
222  black,dLineThickness_);
223 
224  // x direction text and tics 0->xMax
225  int i=0;
226  if(xMin_>=0) i = int(xMin_);
227  else i=0;
228  for(; i<=xMax_;i+=xAxisInc){
229  stringstream message; message<<i;
231  Text (image_,message.str(),int(rint(i*xCoeff_))+xOffset_+5,xTicsPos+15,
232  black,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,dTextThickness_);
234  Line(image_,
235  int(rint(i*xCoeff_))+xOffset_,
236  xTicsPos,
237  int(rint(i*xCoeff_))+xOffset_,
238  xTicsPos+15,black,dLineThickness_);
239 
240  if(bDrawGrid_){
242  Line(image_,
243  int(rint(i*xCoeff_))+xOffset_,
244  0,
245  int(rint(i*xCoeff_))+xOffset_,
246  height_,black);
247  }
248  }
249 
250  if(xMin_ < 0){
251  //x direction text and tics 0->xMin
252  for(i=0;i>=xMin_;i-=xAxisInc){
253  stringstream message; message<<i;
255  Text (image_,message.str(),int(rint(i*xCoeff_))+xOffset_+5,xTicsPos+15,
256  black,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,dTextThickness_);
258  Line(image_,
259  int(rint(i*xCoeff_))+xOffset_,
260  xTicsPos,
261  int(rint(i*xCoeff_))+xOffset_,
262  xTicsPos+15,black,dLineThickness_);
263 
264  if(bDrawGrid_){
266  Line(image_,
267  int(rint(i*xCoeff_))+xOffset_,
268  0,
269  int(rint(i*xCoeff_))+xOffset_,
270  height_,black);
271  }
272  }
273  }
274  //x axis text
276  Text(image_,xLabel_,width_-250,xTicsPos-15, black,
277  CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,dTextThickness_);
278 
279 
280  //check if axis is in image, if not set to 10 pixels from left
281  unsigned int yTicsPos = 0;
282  if(xOffset_>=10 && xOffset_ < (int)width_-10)
283  yTicsPos = xOffset_;
284  else
285  yTicsPos = 10;
286 
287  if(bFixYAxisToLeft_)
288  yTicsPos = 10;
289  //y-axis line
291  yTicsPos,0,yTicsPos,
292  height_,black,dLineThickness_);
293  if(yMin_>=0) i = int(yMin_);
294  else i=0;
295  //y direction text and tics
296  for(; i<=yMax_;i+=yAxisInc){
297  stringstream message; message<<i;
299  Text (image_,message.str(),
300  yTicsPos+5,
301  yOffset_-int(rint(i*yCoeff_))-5,black,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,dTextThickness_);
303  Line(image_,
304  yTicsPos,
305  yOffset_-int(rint(i*yCoeff_)),
306  yTicsPos+15,
307  yOffset_-int(rint(i*yCoeff_)), black,dLineThickness_);
308 
309  if(bDrawGrid_){
311  Line(image_,
312  0,
313  yOffset_-int(rint(i*yCoeff_)),
314  width_,
315  yOffset_-int(rint(i*yCoeff_)), black);
316  }
317  }
318 
319  if(yMin_ < 0){
320  for(i=0; i>=yMin_;i-=yAxisInc){
321  stringstream message; message<<i;
323  Text (image_,message.str(),
324  yTicsPos+5,
325  yOffset_-int(rint(i*yCoeff_))-5,black,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,dTextThickness_);
327  Line(image_,
328  yTicsPos,
329  yOffset_-int(rint(i*yCoeff_)),
330  yTicsPos+15,
331  yOffset_-int(rint(i*yCoeff_)), black,dLineThickness_);
332 
333  if(bDrawGrid_){
335  Line(image_,
336  0,
337  yOffset_-int(rint(i*yCoeff_)),
338  width_,
339  yOffset_-int(rint(i*yCoeff_)), black);
340  }
341  }
342  }
343 
344 
345  //y axis text
347  Text(image_,yLabel_,yTicsPos+50,20,black,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,dTextThickness_);
348 
349  //signal that the graph is inited
350  bPrepared_=true;
351 }
352 
353 void GraphPlotter::
354 Draw(std::vector<double>& xValues,
355  std::vector<double>& yValues,
358 
359  if(!bPrepared_){
360  if(bAutoDetectBordersX_){
361  for(unsigned int i=0;i<xValues.size();i++){
362  if(xValues[i] < xMin_) xMin_ = xValues[i];
363  if(xValues[i] > xMax_) xMax_ = xValues[i];
364  }
365  xMin_ -= 10;
366  xMax_ += 10;
367  }
368  if(bAutoDetectBordersY_){
369  for(unsigned int i=0;i<yValues.size();i++){
370  if(yValues[i] < yMin_) yMin_ = yValues[i];
371  if(yValues[i] > yMax_) yMax_ = yValues[i];
372  }
373  yMin_ -= 10;
374  yMax_ += 10;
375  }
376  Prepare_();
377  }
378  switch(ds){
379  case DS_POINT_1:
380  case DS_POINT_2:
381  case DS_POINT_3:
382  case DS_POINT_4:
383  case DS_POINT_5:
384  unsigned char tmpColor[3];
385  tmpColor[0] = color[0];
386  tmpColor[1] = color[1];
387  tmpColor[2] = color[2];
388  for(unsigned i=0;i<xValues.size();i++){
390  CircleCenterFilled(image_,
391  int(rint(xValues[i]*xCoeff_))+xOffset_,
392  yOffset_-int(rint(yValues[i]*yCoeff_)),
393  ds,tmpColor);
394 
395  }
396  break;
397  case DS_LINE:
398  double oldx = 0.0;
399  double oldy = 0.0;
400 
401  for(unsigned i=0;i<xValues.size();i++){
402  if(oldx != 0.0){
404  Line(image_,
405  int(rint(oldx*xCoeff_))+xOffset_,//startx
406  yOffset_-int(rint(oldy*yCoeff_)),
407  int(rint(xValues[i]*xCoeff_))+xOffset_,//stopx
408  yOffset_-int(rint(yValues[i]*yCoeff_)),color,dLineThickness_);
409 
410  // cout<<int(rint(oldx*xCoeff_))+xOffset_<<","<<
411  // yOffset_-int(rint(oldy*yCoeff_))<<" \t-> "<<
412  // int(rint(xValues[i]*xCoeff_))+xOffset_<<","<<//stopx
413  // yOffset_-int(rint(yValues[i]*yCoeff_))<<endl;
414  }
415  oldx = xValues[i];
416  oldy = yValues[i];
417  }
418 
419  // cout<<"\n\n\n"<<endl;
420  break;
421  }
422 }
423 
424 void GraphPlotter::
425 Draw(std::vector<double>& xValues,
426  std::vector<double>& yValues,
427  std::vector<double>& yStdDeviation,
431  std::vector<string> *labels) {
432 
433  if(!bPrepared_){
434  if(bAutoDetectBordersX_){
435  for(unsigned int i=0;i<xValues.size();i++){
436  if(xValues[i] < xMin_) xMin_ = xValues[i];
437  if(xValues[i] > xMax_) xMax_ = xValues[i];
438  }
439  xMin_ -= 10;
440  xMax_ += 10;
441  }
442  if(bAutoDetectBordersY_){
443  for(unsigned int i=0;i<yStdDeviation.size();i++){
444  if(-(yStdDeviation[i]+yValues[i]) < yMin_) yMin_ = -(yStdDeviation[i]+yValues[i]);
445  if(yStdDeviation[i]+yValues[i] > yMax_) yMax_ = yStdDeviation[i]+yValues[i];
446  }
447  yMin_ -= 20;
448  yMax_ += 20;
449  }
450  Prepare_();
451  }
452 
453  //draw standard deviations
454  for(unsigned i=0;i<yStdDeviation.size();i++){
455  //vertical line
457  Line(image_,
458  int(rint(xValues[i]*xCoeff_))+xOffset_,//startx
459  yOffset_-int(rint(yValues[i]*yCoeff_))-
460  int(rint(yStdDeviation[i]*yCoeff_)),//startY
461  int(rint(xValues[i]*xCoeff_))+xOffset_,//stopx
462  yOffset_-int(rint(yValues[i]*yCoeff_))+
463  int(rint(yStdDeviation[i]*yCoeff_)),//stopy
464  colorSTD,dLineThickness_);
465  //upper horizontal line
467  Line(image_,
468  int(rint(xValues[i]*xCoeff_))-5+xOffset_,//startx
469  yOffset_-int(rint(yValues[i]*yCoeff_))-
470  int(rint(yStdDeviation[i]*yCoeff_)),//startY
471  int(rint(xValues[i]*xCoeff_))+5+xOffset_,//stopx
472  yOffset_-int(rint(yValues[i]*yCoeff_))-
473  int(rint(yStdDeviation[i]*yCoeff_)),//stopy
474  colorSTD,dLineThickness_);
475 
476  //lower horizontal line
478  Line(image_,
479  int(rint(xValues[i]*xCoeff_))-5+xOffset_,//startx
480  yOffset_-int(rint(yValues[i]*yCoeff_))+
481  int(rint(yStdDeviation[i]*yCoeff_)),//startY
482  int(rint(xValues[i]*xCoeff_))+5+xOffset_,//stopx
483  yOffset_-int(rint(yValues[i]*yCoeff_))+
484  int(rint(yStdDeviation[i]*yCoeff_)),//stopy
485  colorSTD,dLineThickness_);
486  if (labels != NULL) {
487  if (labels->size() <= i) {
488  BIASWARN("label names not complete");
489  }
490  BIAS::ImageDraw<unsigned char>::Text(image_, (*labels)[i], int(rint(xValues[i]*xCoeff_))+5+xOffset_,yOffset_-int(rint(yValues[i]*yCoeff_))+int(rint(yStdDeviation[i]*yCoeff_)),colorSTD);
491  }
492  }
493  Draw(xValues,yValues,color,ds);
494 }
495 
496 void GraphPlotter::
498 
499  for(unsigned i=0;i<labels_.size();i++){
500  BIAS::ImageDraw<unsigned char>::Text(image_, labels_[i].first, width_-350,height_-50-(i+1)*20,labels_[i].second);
501  }
502 
503 }
void SetLineThickness(unsigned thickness)
void SetYTics(unsigned ytics)
void SetAxesToYLeftAndXBottom(bool fixAxes)
void SetYLabel(std::string label)
BIAS::Image< unsigned char > * GetImage()
~GraphPlotter()
destructor
void SetYRange(double minY, double maxY)
static int CircleCenterFilled(Image< StorageType > &im, unsigned int CenterX, unsigned int CenterY, unsigned int Radius, const StorageType Value[])
draws a filled circle using Value
Definition: ImageDraw.cpp:1023
void SetImageSize(unsigned width, unsigned height)
GraphPlotter_DrawStyle
Definition: GraphPlotter.hh:37
void SetDrawGrid(bool drawGrid)
void SetXRange(double minX, double maxX)
BIAS::Image< unsigned char > GetCopyOfImage()
void SetTextThickness(unsigned thickness)
void Draw(std::vector< double > &xValues, std::vector< double > &yValues, BIAS::ColourRGB< unsigned char > color, BIAS::GraphPlotter_DrawStyle=DS_POINT_1)
draws xvalues against yvalues
static int Line(Image< StorageType > &im, const unsigned int start[2], const unsigned int end[2], const StorageType value[])
lines
Definition: ImageDraw.cpp:404
void SetXTics(unsigned xtics)
GraphPlotter()
constructor
void SetXLabel(std::string label)
static void Text(BIAS::Image< StorageType > &dstImg, const std::string &message, const int &posX=0, const int &posY=20, const ColourRGB< StorageType > &colorRGB=ColourRGB< StorageType >(255, 255, 255), const int fontface=1, const double hscale=1.0, const double vscale=1.0, const double shear=0, const int thickness=1, const int linetype=8)
OpenCV: Draw Text into image.
Definition: ImageDraw.cpp:1384