source: flair-src/trunk/tools/FlairGCS/src/DataPlot2D.cpp@ 9

Last change on this file since 9 was 9, checked in by Sanahuja Guillaume, 8 years ago

gcs

File size: 12.2 KB
Line 
1#include "DataPlot2D.h"
2#include "Layout.h"
3#include <qwt_plot.h>
4#include <qwt_plot_curve.h>
5#include <qwt_plot_grid.h>
6#include <qwt_plot_magnifier.h>
7#include <qwt_plot_canvas.h>
8#include <qwt_scale_widget.h>
9#include <qwt_legend_label.h>
10#include <qwt_legend.h>
11#include <qwt_plot_panner.h>
12#include <qwt_plot_rescaler.h>
13#include <QMouseEvent>
14#include <QMenu>
15#include <QInputDialog>
16#include <qendian.h>
17
18DataPlot2D::DataPlot2D(Layout* parent,int row, int col,QString plot_name,QString x_name,QString y_name,float xmin, float xmax,float ymin, float ymax,bool enabled,int period):
19 DataRemote(plot_name,"DataPlot2D",parent,enabled,period)
20{
21 plot=new QwtPlot(NULL);
22 plot->setEnabled(enabled);
23
24 parent->addWidget(plot,row,col);
25 visible_widget=plot;
26
27 view_size=20;//default 20s
28/*
29 // Disable polygon clipping
30 QwtPainter::setDeviceClipping(false);
31
32 // We don't need the cache here
33 plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
34 plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
35*/
36#if QT_VERSION >= 0x040000
37#ifdef Q_WS_X11
38 /*
39 Qt::WA_PaintOnScreen is only supported for X11, but leads
40 to substantial bugs with Qt 4.2.x/Windows
41 */
42 plot->canvas()->setAttribute(Qt::WA_PaintOnScreen, true);
43#endif
44#endif
45
46 alignScales();
47
48 //d_x=new QList<double*>;
49 //d_y=new QList<double*>;
50 datas=new QList<QwtPlotCurve*>;
51 datas_type=new QList<QString>;
52
53 // Assign a title
54 plot->setTitle(plot_name);
55
56 // Axis
57 plot->setAxisTitle(QwtPlot::xBottom, x_name);
58 setXAxisScale(xmin,xmax);
59
60 plot->setAxisTitle(QwtPlot::yLeft, y_name);
61 setYAxisScale(ymin,ymax);
62
63 QwtPlotRescaler* rescaler = new QwtPlotRescaler( plot->canvas() );
64 rescaler->setRescalePolicy( QwtPlotRescaler::Fixed );/*
65 rescaler->setReferenceAxis(QwtPlot::xBottom);
66 rescaler->setAspectRatio(QwtPlot::yLeft, 1.0);*/
67
68 // grid
69 QwtPlotGrid *grid = new QwtPlotGrid;
70 //grid->enableXMin(false);
71 grid->setPen(QPen(Qt::black, 0, Qt::DotLine));
72 //grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine));
73 grid->attach(plot);
74
75 //zoomer
76 QwtPlotMagnifier * zoomer = new QwtPlotMagnifier(plot->canvas());
77 zoomer->setMouseButton(Qt::RightButton,Qt::ControlModifier);
78
79 //scroller
80 QwtPlotPanner *scroller =new QwtPlotPanner(plot->canvas());
81
82 //legend
83 QwtLegend* new_legend=new QwtLegend();
84 new_legend->setDefaultItemMode(QwtLegendData::Checkable);
85 plot->insertLegend(new_legend, QwtPlot::BottomLegend);
86
87 connect( new_legend, SIGNAL( checked( const QVariant &, bool, int ) ), SLOT( legendChecked( const QVariant &, bool ) ) );
88
89 plot->canvas()->installEventFilter(this);
90}
91
92DataPlot2D::~DataPlot2D()
93{
94 for(int i=0;i<d_x.count();i++)
95 {
96 free(d_x.at(i));
97 free(d_y.at(i));
98 }
99
100 delete datas;
101 delete datas_type;
102}
103
104void DataPlot2D::XmlEvent(QDomElement dom)
105{
106 if(dom.attribute("curve")!="") {
107 QString type=dom.attribute("type");
108 int r=dom.attribute("r").toInt();
109 int g=dom.attribute("g").toInt();
110 int b=dom.attribute("b").toInt();
111 QString name=dom.attribute("curve");
112 addCurve(QPen(QColor(r,g,b,255)),name,type);
113 } else {
114 XmlSetup(dom);
115 }
116}
117
118bool DataPlot2D::eventFilter(QObject *o, QEvent *e)
119{
120 if ( o == plot->canvas() )
121 {
122 switch(e->type())
123 {
124 case QEvent::MouseButtonPress:
125 {
126 mousePressEvent((QMouseEvent*)e);
127 break;
128 }
129
130 default:
131 break;
132 }
133 }
134 return plot->eventFilter(o, e);
135}
136
137void DataPlot2D::legendChecked( const QVariant &itemInfo, bool on )
138{
139 QwtPlotItem *plotItem = plot->infoToItem( itemInfo );
140 if ( plotItem )
141 showCurve( plotItem, on );
142}
143
144void DataPlot2D::showCurve(QwtPlotItem *item, bool on)
145{
146 item->setVisible(on);
147
148 QwtLegend *lgd = qobject_cast<QwtLegend *>( plot->legend() );
149
150 QList<QWidget *> legendWidgets =
151 lgd->legendWidgets( plot->itemToInfo( item ) );
152
153 if ( legendWidgets.size() == 1 )
154 {
155 QwtLegendLabel *legendLabel =
156 qobject_cast<QwtLegendLabel *>( legendWidgets[0] );
157
158 if ( legendLabel )
159 legendLabel->setChecked( on );
160 }
161
162 plot->replot();
163}
164
165void DataPlot2D::addCurve(QPen pen,QString legend,QString type)
166{
167 double* new_dx;
168 new_dx=(double*)malloc(view_size/refresh_rate*sizeof(double));
169 d_x.append(new_dx);
170 double* new_dy;
171 new_dy=(double*)malloc(view_size/refresh_rate*sizeof(double));
172 d_y.append(new_dy);
173
174 // Initialize data
175 for (int i = 0; i< view_size/refresh_rate; i++) new_dx[i] = 0;
176 for (int i = 0; i< view_size/refresh_rate; i++) new_dy[i] = 0;
177
178 // Insert new curve
179 QwtPlotCurve* new_data;
180
181 new_data = new QwtPlotCurve(legend);
182 new_data->attach(plot);
183 new_data->setPen(pen);
184 datas->append(new_data);
185
186 showCurve(new_data, true);
187
188 datas_type->append(type);
189 bool tmp=true;
190 datas_first_update.append(tmp);
191
192 // Attach (don't copy) data. Both curves use the same x array.
193 new_data->setRawSamples(new_dx, new_dy, view_size/refresh_rate);
194
195 if(type=="float")
196 {
197 receivesize+=sizeof(float);
198 }
199 else if(type=="int8_t")
200 {
201 receivesize+=sizeof(int8_t);
202 }
203 else if(type=="int16_t")
204 {
205 receivesize+=sizeof(int16_t);
206 }
207 else
208 {
209 printf("DataPlot2D::addCurve unknown type %s\n",type.toLocal8Bit().constData());
210 }
211
212}
213
214void DataPlot2D::setXAxisScale(float xmin,float xmax)
215{
216 xmin_orig=xmin;
217 xmax_orig=xmax;
218 plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig);
219
220}
221
222void DataPlot2D::setYAxisScale(float ymin,float ymax)
223{
224 ymin_orig=ymin;
225 ymax_orig=ymax;
226 plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
227}
228
229//
230// Set a plain canvas frame and align the scales to it
231//
232void DataPlot2D::alignScales(void)
233{
234 // The code below shows how to align the scales to
235 // the canvas frame, but is also a good example demonstrating
236 // why the spreaded API needs polishing.
237/*
238 plot->canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
239 plot->canvas()->setLineWidth(1);
240*/
241 for ( int i = 0; i < QwtPlot::axisCnt; i++ )
242 {
243 QwtScaleWidget *scaleWidget = (QwtScaleWidget *)plot->axisWidget(i);
244 if ( scaleWidget )
245 scaleWidget->setMargin(0);
246
247 QwtScaleDraw *scaleDraw = (QwtScaleDraw *)plot->axisScaleDraw(i);
248 if ( scaleDraw )
249 scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
250 }
251}
252
253void DataPlot2D::BufEvent(char **buf,int *buf_size,uint16_t period,bool big_endian)
254{
255 plot->setEnabled(IsEnabled());
256 if(IsEnabled()==false || RefreshRate_ms()!=period) return;
257
258 for(int i=0;i<datas->count();i++)
259 {
260 if(datas_type->at(i)=="float")
261 {
262 uint32_t data1_raw;
263 float* data1=(float*)&data1_raw;
264 uint32_t data2_raw;
265 float* data2=(float*)&data2_raw;
266
267 memcpy((void*)&data1_raw,*buf,sizeof(uint32_t));
268 *buf+=sizeof(uint32_t);
269 memcpy((void*)&data2_raw,*buf,sizeof(uint32_t));
270 *buf+=sizeof(uint32_t);
271 if(big_endian==true) data1_raw=qFromBigEndian(data1_raw);
272 if(big_endian==true) data2_raw=qFromBigEndian(data2_raw);
273 plot_data(*data1,*data2,i);
274 }
275 else if(datas_type->at(i)=="int8_t")
276 {
277 int8_t data1,data2;
278 memcpy((void*)&data1,*buf,sizeof(data1));
279 *buf+=sizeof(data1);
280 memcpy((void*)&data2,*buf,sizeof(data2));
281 *buf+=sizeof(data2);
282 plot_data(data1,data2,i);
283 }
284 else if(datas_type->at(i)=="int16_t")
285 {
286 int16_t data1,data2;
287 memcpy((void*)&data1,*buf,sizeof(data1));
288 *buf+=sizeof(data1);
289 memcpy((void*)&data2,*buf,sizeof(data2));
290 *buf+=sizeof(data2);
291 plot_data(data1,data2,i);
292 }
293 else
294 {
295 printf("DataPlot1D::DrawDatas type non connu\n");
296 }
297 }
298
299 plot->replot();
300}
301
302void DataPlot2D::plot_data(double data_x,double data_y,int index)
303{
304 if(index<d_y.count())
305 {
306 if(datas_first_update.at(index)==false)
307 {
308 // Shift y array left and assign new value to y[view_size/refresh_rate - 1].
309 for ( int j = 0; j < view_size/refresh_rate - 1; j++ ) d_y.at(index)[j] = d_y.at(index)[j+1] ;
310 for ( int j = 0; j < view_size/refresh_rate - 1; j++ ) d_x.at(index)[j] = d_x.at(index)[j+1] ;
311 d_y.at(index)[(int)(view_size/refresh_rate) - 1] = data_y;
312 d_x.at(index)[(int)(view_size/refresh_rate) - 1] = data_x;
313 }
314 else
315 {
316 for ( int j = 0; j <= view_size/refresh_rate - 1; j++ ) d_y.at(index)[j] = data_y;
317 for ( int j = 0; j <= view_size/refresh_rate - 1; j++ ) d_x.at(index)[j] = data_x;
318 datas_first_update[index]=false;
319 }
320 }
321}
322
323
324//context menu
325void DataPlot2D::mousePressEvent(QMouseEvent *event)
326{
327 if (event->button() == Qt::RightButton)
328 {
329
330 QMenu * menu = new QMenu("nom", plot);
331 // ajout des actions
332 QAction *a,*z,*d;
333
334 a=menu->addAction("reset zoom");
335 menu->addSeparator();
336
337 d=menu->addAction(QString("set view size (%1s)").arg(view_size));
338
339 appendmenu(menu);
340 z=execmenu(plot,menu,event->globalPos());
341 delete menu;
342
343 if(z==a)
344 {
345 //zoom to original size
346 plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
347 plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig);
348 }
349
350 if(z==d)
351 {
352 bool ok;
353 float time = QInputDialog::getInt(plot, QString("Set view size (%1)").arg(plot->title().text()),tr("Value (s):"), view_size, 1, 65535, 10, &ok);
354 if(ok==true)
355 {
356 for(int i=0;i<datas->count();i++)
357 {
358 if(time>view_size)
359 {
360 double* buf=(double*)malloc(time/refresh_rate*sizeof(double));
361 d_x[i]=(double*)realloc(d_x.at(i),time/refresh_rate*sizeof(double));
362 memcpy(buf,d_x[i],(view_size/refresh_rate)*sizeof(double));
363 memcpy(&d_x[i][(int)(time/refresh_rate)-(int)(view_size/refresh_rate)],buf,(view_size/refresh_rate)*sizeof(double));
364 d_y[i]=(double*)realloc(d_y.at(i),time/refresh_rate*sizeof(double));
365 memcpy(buf,d_y[i],(view_size/refresh_rate)*sizeof(double));
366 memcpy(&d_y[i][(int)(time/refresh_rate)-(int)(view_size/refresh_rate)],buf,(view_size/refresh_rate)*sizeof(double));
367 free(buf);
368 for(int j=0;j<(int)(time/refresh_rate)-(int)(view_size/refresh_rate);j++)
369 {
370 d_x.at(i)[j]=d_x.at(i)[(int)(time/refresh_rate)-(int)(view_size/refresh_rate)+1];
371 d_y.at(i)[j]=d_y.at(i)[(int)(time/refresh_rate)-(int)(view_size/refresh_rate)+1];
372 }
373 }
374 else
375 {
376 double* buf=(double*)malloc(time/refresh_rate*sizeof(double));
377 memcpy(buf,&d_x[i][(int)(view_size/refresh_rate)-(int)(time/refresh_rate)],(time/refresh_rate)*sizeof(double));
378 d_x[i]=(double*)realloc(d_x.at(i),time/refresh_rate*sizeof(double));
379 memcpy(d_x[i],buf,(time/refresh_rate)*sizeof(double));
380 memcpy(buf,&d_y[i][(int)(view_size/refresh_rate)-(int)(time/refresh_rate)],(time/refresh_rate)*sizeof(double));
381 d_y[i]=(double*)realloc(d_y.at(i),time/refresh_rate*sizeof(double));
382 memcpy(d_y[i],buf,(time/refresh_rate)*sizeof(double));
383 free(buf);
384 }
385 datas->at(i)->setRawSamples(d_x.at(i), d_y.at(i), time/refresh_rate);
386
387 }
388 view_size=time;
389
390 }
391 }
392 }
393}
Note: See TracBrowser for help on using the repository browser.