MNE-CPP  beta 1.0
plotter.cpp
1 #include "plotter.h"
2 
3 #include <cmath>
4 
5 
6 plotter::plotter(QWidget *parent)
7  : QWidget(parent)
8 {
9  setBackgroundRole(QPalette::Dark);
10  setAutoFillBackground(true);
11  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
12  setFocusPolicy(Qt::StrongFocus);
13  rubberBandIsShown = false;
14 
15 // zoomInButton = new QToolButton(this);
16 // zoomInButton->adjustSize();
17 // connect(zoomInButton,SIGNAL(clicked()), this, SLOT(zoomIn()));
18 
19 // zoomOutButton = new QToolButton(this);
20 // zoomOutButton->adjustSize();
21 // connect(zoomOutButton,SIGNAL(clicked()), this, SLOT(zoomOut()));
22 
23  setPlotSettings(PlotSettings());
24 
25 }
26 
27 void plotter::setPlotSettings(const PlotSettings &settings)
28 {
29  zoomStack.clear();
30  zoomStack.append(settings);
31  curZoom = 0;
32 // zoomInButton->hide();
33 // zoomOutButton->hide();
34  refreshPixmap();
35 }
36 
37 
38 //void plotter::zoomOut()
39 //{
40 // if(curZoom > 0){
41 // --curZoom;
42 // zoomOutButton->setEnabled(curZoom > 0);
43 // zoomInButton->setEnabled(true);
44 // zoomInButton->show();
45 // refreshPixmap();
46 // }
47 //}
48 
49 //void plotter::zoomIn()
50 //{
51 // if(curZoom < zoomStack.count() - 1){
52 // ++curZoom;
53 // zoomInButton->setEnabled(curZoom < zoomStack.count() - 1);
54 // zoomOutButton->setEnabled(true);
55 // zoomOutButton->show();
56 // refreshPixmap();
57 // }
58 //}
59 
60 void plotter::setCurveData(int id, const QVector<QPointF> &data)
61 {
62  curveMap[id] = data;
63  refreshPixmap();
64 }
65 
66 void plotter::clearCurve(int id)
67 {
68  curveMap.remove(id);
69  refreshPixmap();
70 }
71 
72 QSize plotter::minimumSizeHint() const
73 {
74  return QSize(6*Margin,4*Margin);
75 }
76 
77 QSize plotter::sizeHint() const
78 {
79  return QSize(12*Margin, 8*Margin);
80 }
81 
82 void plotter::paintEvent(QPaintEvent * /*event*/)
83 {
84  QStylePainter painter(this);
85  painter.drawPixmap(0,0,pixmap);
86 
87 // if(rubberBandIsShown){
88 // painter.setPen(palette().light().color());
89 // painter.drawRect(rubberBandRect.normalized().adjusted(0,0,-1,-1));
90 // }
91 
92 // if(hasFocus())
93 // {
94 // QStyleOptionFocusRect option;
95 // option.initFrom(this);
96 // option.backgroundColor = palette().dark().color();
97 // painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);
98 // }
99 }
100 
101 void plotter::resizeEvent(QResizeEvent * /*event*/)
102 {
103 // int x = width() - (zoomInButton->width() + zoomOutButton->width() + 10);
104 
105 // zoomInButton->move(x,5);
106 // zoomOutButton->move(x + zoomInButton->width() +5, 5);
107  refreshPixmap();
108 }
109 
110 void plotter::refreshPixmap()
111 {
112  pixmap = QPixmap(size());
113  //pixmap.fill(this, 0, 0);
114 
115 
116  QPainter painter(&pixmap);
117  painter.initFrom(this);
118  drawGrid(&painter);
119  drawCurve(&painter);
120  update();
121 }
122 
123 void plotter::drawGrid(QPainter *painter)
124 {
125  QRect rect(xMargin+20, Margin-10, width()-2*xMargin, height() -2*Margin);
126  if(!rect.isValid()) return;
127 
128  PlotSettings settings = zoomStack[curZoom];
129  QPen quiteDark = palette().dark().color().light();
130  QPen light = palette().light().color();
131 
132  for(int i=0; i<=settings.numXTicks;++i)
133  {
134  int x = rect.left() + (i*(rect.width()-1)/settings.numXTicks);
135  double label = settings.minX + (i*settings.spanX()/settings.numXTicks);
136  painter->setPen(quiteDark);
137  painter->drawLine(x,rect.top(),x,rect.bottom());
138  painter->setPen(light);
139  painter->drawLine(x,rect.bottom(),x,rect.bottom()-5);
140  painter->drawText(x,rect.bottom()+5,100,20,Qt::AlignLeft, QString::number(label));
141  }
142 
143  painter->drawText(rect.left(),rect.bottom()+20,rect.width(),20,Qt::AlignCenter, settings.xlabel);
144 
145 
146  for(int j=0; j<=settings.numYTicks;++j)
147  {
148  int y = rect.bottom() - (j*(rect.height()-1)/settings.numYTicks);
149  double label = settings.minY + (j*settings.spanY()/settings.numYTicks);
150  painter->setPen(quiteDark);
151  painter->drawLine(rect.left(),y,rect.right(),y);
152  painter->setPen(light);
153  painter->drawLine(rect.left()+5 ,y, rect.left(),y);
154  painter->drawText(rect.left()- xMargin -30, y-10, 100,20,
155  Qt::AlignVCenter|Qt::AlignRight, QString::number(label));
156  }
157 
158  //painter->drawText(rect.left()-10, rect.bottom(), rect.height(),20,Qt::AlignVCenter|Qt::AlignCenter, settings.ylabel);
159 
160  drawRotatedText(painter, rect.left()-80, rect.bottom()-40, settings.ylabel);
161  painter->drawRect(rect.adjusted(0,0,-1,-1));
162 
163 }
164 
165 
166 void plotter::drawRotatedText(QPainter *painter, int x, int y, const QString &text)
167 {
168  painter->save();
169  painter->translate(x, y);
170  painter->rotate(270); // or 90
171  painter->drawText(0, 0, text);
172  painter->restore();
173 }
174 
175 
176 void plotter::drawCurve(QPainter *painter)
177 {
178  static const QColor colorForIds[6] = {Qt::red,Qt::green,Qt::blue,Qt::cyan,Qt::magenta,Qt::yellow};
179 
180  PlotSettings settings = zoomStack[curZoom];
181  QRect rect(xMargin+20, Margin-10, width()-2*xMargin, height()-2*Margin);
182  if(!rect.isValid()) return;
183 
184  painter->setClipRect(rect.adjusted(+1,+1,-1,-1));
185  QMapIterator <int, QVector<QPointF> > i(curveMap);
186  while (i.hasNext()) {
187  i.next();
188  int id = i.key();
189  QVector<QPointF> data = i.value();
190  QPolygonF polyline(data.count());
191  for(int j=0; j<data.count(); ++j){
192  double dx = data[j].x() - settings.minX;
193  double dy = data[j].y() - settings.minY;
194  double x = rect.left() + (dx*(rect.width()-1)/settings.spanX());
195  double y = rect.bottom() - (dy *(rect.height()-1)/settings.spanY());
196  polyline[j] = QPointF(x,y);
197  }
198  painter->setPen(colorForIds[uint(id) % 6]);
199  painter->drawPolyline(polyline);
200  }
201 }
202 
203 PlotSettings::PlotSettings()
204 {
205  minX = 0.0;
206  maxX = 10.0;
207  numXTicks = 5;
208 
209  minY = -10.0;
210  maxY = 10.0;
211  numYTicks = 5;
212 }
213 
214 void PlotSettings::adjustAxis(double &min, double &max, int &numTicks)
215 {
216  const int MinTicks = 4;
217  double grossStep = (max-min)/ MinTicks;
218  double step = std::pow(10.0, std::floor(std::log10(grossStep)));
219 
220  if(5*step<grossStep){
221  step *= 5;
222  }
223  else if(2*step < grossStep){
224  step *= 2;
225  }
226 
227  numTicks = int(std::ceil(max/step) - std::floor(min/step));
228  if(numTicks < MinTicks)
229  numTicks = MinTicks;
230  min = std::floor(min/step)*step;
231  max = std::ceil(max/step)*step;
232 }
233