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
RevLine 
[10]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}
[9]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.