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

Last change on this file since 10 was 10, checked in by Sanahuja Guillaume, 6 years ago

lic

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