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

Last change on this file since 9 was 9, checked in by Sanahuja Guillaume, 5 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.