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