1 /*
2  ----------------------------------------------------------------------------
3  "THE BEER-WARE LICENSE" (Revision 42):
4  <daniel.kratzert@ac.uni-freiburg.de> wrote this file. As long as you retain
5  this notice you can do whatever you want with this stuff. If we meet some day,
6  and you think this stuff is worth it, you can buy me a beer in return.
7  Daniel Kratzert
8  ----------------------------------------------------------------------------
9 */
10 
11 #include "plotgraph.h"
12 #include <QtGui>
13 
14 
RenderPlot(int cycles,QWidget * parent)15 RenderPlot::RenderPlot(int cycles, QWidget *parent)
16     : QWidget(parent)
17 {
18   dataPointShape = Ellipse;
19   setBackgroundRole(QPalette::Base);
20   setAutoFillBackground(true);
21   originshift = 27;
22   pen.setCapStyle(Qt::RoundCap);
23   pen.setStyle(Qt::SolidLine);
24   pen.setWidth(2);
25   pen.setBrush(Qt::black);
26   pen.setJoinStyle(Qt::RoundJoin);
27   sclinespen.setCapStyle(Qt::RoundCap);
28   sclinespen.setStyle(Qt::DotLine);
29   sclinespen.setWidth(1);
30   sclinespen.setBrush(QColor(80, 80, 80, 50));
31   datapoints.clear();
32   mcycles = cycles;
33   startcycles = cycles;
34   pointcolor = QBrush(Qt::green); //! color of the plot points
35 }
36 
clearPlot()37 void RenderPlot::clearPlot() {
38   datapoints.clear();
39   this->update();
40   mcycles = startcycles;
41 }
42 
minimumSizeHint() const43 QSize RenderPlot::minimumSizeHint() const
44 {
45   return QSize(150, 130);
46 }
47 
sizeHint() const48 QSize RenderPlot::sizeHint() const
49 {
50   return QSize(250, 130);
51 }
52 
53 
setPen(const QPen & pen)54 void RenderPlot::setPen(const QPen &pen)
55 {
56   this->pen = pen;
57   update();
58 }
59 
setBrush(const QBrush & brush)60 void RenderPlot::setBrush(const QBrush &brush)
61 {
62   this->brush = brush;
63   update();
64 }
65 
setCycle(int numcycle)66 void RenderPlot::setCycle(int numcycle) {
67   this->mcycles = numcycle;
68 }
69 
addPoint(qreal percent,int cycle)70 void RenderPlot::addPoint(qreal percent, int cycle){
71   //! Add a point to the list of points.
72   mypoint p;
73   p.x = cycle;
74   p.y = percent;
75   bool found = false;
76   if (datapoints.size() > 0) {
77     foreach (mypoint p, datapoints) {
78       if (p.x == cycle) {
79         found = true;
80       }
81     }
82   }
83   // make sure only unique data points go into list:
84   if (found){
85     return;
86   } else {
87     datapoints.append(p);
88   }
89   // extends the x axis if more cycles are coming
90   if ((cycle-mcycles) == 1) {
91     mcycles += 1;
92   }
93   this->update();
94 }
95 
96 
drawScale()97 void RenderPlot::drawScale() {
98   //! Draws the axis scales. The origin ist shefted by "origignshift".
99   //! The scale ticks are in the distances distx and disty.
100   QPainter painter(this);
101   painter.setPen(pen);
102   painter.setBrush(brush);
103   painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
104   QFont font;
105   font.setPointSize(11);
106   painter.setFont(font);
107   // The X axis line:
108   painter.save();
109   painter.translate(originshift, height()-originshift);
110   painter.drawLine(0, 0, width(), 0);
111   painter.translate(width()-40-originshift, -27);
112   // The X axis label:
113   QTextDocument tdx;
114   tdx.setHtml("<font style=font-size:11pt> cycle </font>");
115   tdx.drawContents(&painter);
116   painter.restore();
117 
118   // The Y axis line:
119   painter.save();
120   painter.translate(originshift, height()-originshift);
121   painter.drawLine(0, 0, 0, -height());
122   painter.translate(5, -height()+originshift);
123   QTextDocument tdy;
124   // The Y axis label:
125   tdy.setHtml("<font style=font-size:11pt>% <i>wR</i><sub>2</sub></font>");
126   tdy.drawContents(&painter);
127   painter.restore();
128   // need highest y value to get scale right:
129   QList<qreal> ylist;
130   foreach (mypoint p, datapoints) {
131     ylist.append(p.y);
132   }
133   qSort(ylist.begin(), ylist.end());
134   distx = width() / (mcycles+1);
135   // 14 is an empirical number and defines extra space on the y scale:
136   if (ylist.length() > 1) {
137     disty = height() / ((14*ylist.last()));
138   } else { // default scale:
139     disty = height() / 10;
140   }
141 
142   // draw X scales
143   qreal cycle = 0;
144   for (qreal x = 0; x <= width(); x += distx) {
145     painter.save();
146     font.setPointSize(10);
147     painter.setFont(font);
148     // translate to left bottom corner+originshift:
149     painter.translate(x+originshift, height()-originshift);
150     // draw scale:
151     painter.drawLine(0, 0, 0, 5);
152     // draw intersetioon lines:
153     if (x > 0 ) {
154       painter.setPen(sclinespen);
155       painter.drawLine(0, 0, 0, -height());
156       painter.setPen(pen);
157     }
158     painter.drawText(-4, 19, QString("%1").arg(cycle));
159     painter.restore();
160     cycle += 1;
161   }
162 
163   // draw Y scales
164   // percent and stepsize could be defined outside to make the plotting more versatile:
165   int percent = 0;
166   int stepsize = 10;
167   for (qreal y = 0; y <= (height() - (height()/stepsize)); y += disty) {
168     painter.save();
169     // translate to left bottom corner+originshift:
170     painter.translate(originshift, height()-y-originshift);
171     // draw scale:
172     font.setPointSize(10);
173     painter.setFont(font);
174     painter.drawLine(-5, 0, 0, 0);
175     painter.drawText(-24, 4, QString("%1").arg(percent));
176     // draw intersection lines:
177     if (y > 0) {
178       painter.setPen(sclinespen);
179       painter.drawLine(width(), 0, 0, 0);
180       painter.setPen(pen);
181     }
182     painter.restore();
183     percent += stepsize;
184   }
185 }
186 
drawPoints(const QList<mypoint> points,int pointsize)187 void RenderPlot::drawPoints(const QList<mypoint> points, int pointsize) {
188   //! Draws pre-defined points on the graph relative to the originshift.
189   QPainter painter(this);
190   QFont font;
191   font.setPointSize(10);
192   painter.setFont(font);
193   painter.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
194   painter.setBrush(pointcolor);
195   painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
196   qreal x = 0;
197   qreal y = 0;
198   foreach (mypoint p, points) {
199     painter.save();
200     x = p.x*distx;
201     y = -p.y*disty*10; // factor 10 could be defined outside to make plotting more versatile
202     painter.translate(originshift, height()-originshift);
203     // translate from 0, 0 of plot coordinate system,
204     // therefore p.x*..., -p.y*...:
205     painter.translate(x, y);
206     // draw the y value as text:
207     painter.drawText(-23, -8, QString("%1").arg(p.y*100, 10, 'f', 2));
208     painter.drawEllipse(QPointF(0, 0), pointsize, pointsize);
209     painter.restore();
210   }
211   painter.setPen(palette().dark().color());
212   painter.setBrush(Qt::NoBrush);
213   painter.drawRect(QRect(0, 0, width() - 1, height() - 1));
214 }
215 
drawLines(const QList<mypoint> points)216 void RenderPlot::drawLines(const QList<mypoint> points) {
217   //! Draws lines between data points.
218   if (points.size() < 2) return;
219   QPainter painter(this);
220   painter.setPen(QPen(Qt::darkGray, 1, Qt::DotLine, Qt::RoundCap, Qt::RoundJoin));
221   painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
222   qreal lastx = 0.0;
223   qreal lasty = 0.0;
224   qreal x = 0;
225   qreal y = 0;
226   foreach (mypoint p, points) {
227     x = p.x*distx;
228     y = -p.y*disty*10;
229     painter.save();
230     painter.translate(originshift, height()-originshift);
231     if (x > distx) { //
232       painter.drawLine(int(lastx), int(lasty), int(x), int(y));
233     }
234     lastx=x;
235     lasty=y;
236     painter.restore();
237   }
238   printf("\n");
239 }
240 
paintEvent(QPaintEvent *)241 void RenderPlot::paintEvent(QPaintEvent *)
242 //! This runs every time the widget changes.
243 {
244   drawScale();
245   drawLines(datapoints);
246   drawPoints(datapoints, 3);
247 }
248 
249 
250