// %flair:license{ // This file is part of the Flair framework distributed under the // CECILL-C License, Version 1.0. // %flair:license} #include "DataPlot2D.h" #include "Layout.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include DataPlot2D::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): DataRemote(plot_name,"DataPlot2D",parent,enabled,period) { plot=new QwtPlot(NULL); plot->setEnabled(enabled); parent->addWidget(plot,row,col); visible_widget=plot; view_size=20;//default 20s /* // Disable polygon clipping QwtPainter::setDeviceClipping(false); // We don't need the cache here plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false); */ #if QT_VERSION >= 0x040000 #ifdef Q_WS_X11 /* Qt::WA_PaintOnScreen is only supported for X11, but leads to substantial bugs with Qt 4.2.x/Windows */ plot->canvas()->setAttribute(Qt::WA_PaintOnScreen, true); #endif #endif alignScales(); //d_x=new QList; //d_y=new QList; datas=new QList; datas_type=new QList; // Assign a title plot->setTitle(plot_name); // Axis plot->setAxisTitle(QwtPlot::xBottom, x_name); setXAxisScale(xmin,xmax); plot->setAxisTitle(QwtPlot::yLeft, y_name); setYAxisScale(ymin,ymax); QwtPlotRescaler* rescaler = new QwtPlotRescaler( plot->canvas() ); rescaler->setRescalePolicy( QwtPlotRescaler::Fixed );/* rescaler->setReferenceAxis(QwtPlot::xBottom); rescaler->setAspectRatio(QwtPlot::yLeft, 1.0);*/ // grid QwtPlotGrid *grid = new QwtPlotGrid; //grid->enableXMin(false); grid->setPen(QPen(Qt::black, 0, Qt::DotLine)); //grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine)); grid->attach(plot); //zoomer QwtPlotMagnifier * zoomer = new QwtPlotMagnifier(plot->canvas()); zoomer->setMouseButton(Qt::RightButton,Qt::ControlModifier); //scroller QwtPlotPanner *scroller =new QwtPlotPanner(plot->canvas()); //legend QwtLegend* new_legend=new QwtLegend(); new_legend->setDefaultItemMode(QwtLegendData::Checkable); plot->insertLegend(new_legend, QwtPlot::BottomLegend); connect( new_legend, SIGNAL( checked( const QVariant &, bool, int ) ), SLOT( legendChecked( const QVariant &, bool ) ) ); plot->canvas()->installEventFilter(this); } DataPlot2D::~DataPlot2D() { for(int i=0;icanvas() ) { switch(e->type()) { case QEvent::MouseButtonPress: { mousePressEvent((QMouseEvent*)e); break; } default: break; } } return plot->eventFilter(o, e); } void DataPlot2D::legendChecked( const QVariant &itemInfo, bool on ) { QwtPlotItem *plotItem = plot->infoToItem( itemInfo ); if ( plotItem ) showCurve( plotItem, on ); } void DataPlot2D::showCurve(QwtPlotItem *item, bool on) { item->setVisible(on); QwtLegend *lgd = qobject_cast( plot->legend() ); QList legendWidgets = lgd->legendWidgets( plot->itemToInfo( item ) ); if ( legendWidgets.size() == 1 ) { QwtLegendLabel *legendLabel = qobject_cast( legendWidgets[0] ); if ( legendLabel ) legendLabel->setChecked( on ); } plot->replot(); } void DataPlot2D::addCurve(QPen pen,QString legend,QString type) { double* new_dx; new_dx=(double*)malloc(view_size/refresh_rate*sizeof(double)); d_x.append(new_dx); double* new_dy; new_dy=(double*)malloc(view_size/refresh_rate*sizeof(double)); d_y.append(new_dy); // Initialize data for (int i = 0; i< view_size/refresh_rate; i++) new_dx[i] = 0; for (int i = 0; i< view_size/refresh_rate; i++) new_dy[i] = 0; // Insert new curve QwtPlotCurve* new_data; new_data = new QwtPlotCurve(legend); new_data->attach(plot); new_data->setPen(pen); datas->append(new_data); showCurve(new_data, true); datas_type->append(type); bool tmp=true; datas_first_update.append(tmp); // Attach (don't copy) data. Both curves use the same x array. new_data->setRawSamples(new_dx, new_dy, view_size/refresh_rate); if(type=="float") { receivesize+=sizeof(float); } else if(type=="int8_t") { receivesize+=sizeof(int8_t); } else if(type=="int16_t") { receivesize+=sizeof(int16_t); } else { printf("DataPlot2D::addCurve unknown type %s\n",type.toLocal8Bit().constData()); } } void DataPlot2D::setXAxisScale(float xmin,float xmax) { xmin_orig=xmin; xmax_orig=xmax; plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig); } void DataPlot2D::setYAxisScale(float ymin,float ymax) { ymin_orig=ymin; ymax_orig=ymax; plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig); } // // Set a plain canvas frame and align the scales to it // void DataPlot2D::alignScales(void) { // The code below shows how to align the scales to // the canvas frame, but is also a good example demonstrating // why the spreaded API needs polishing. /* plot->canvas()->setFrameStyle(QFrame::Box | QFrame::Plain ); plot->canvas()->setLineWidth(1); */ for ( int i = 0; i < QwtPlot::axisCnt; i++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)plot->axisWidget(i); if ( scaleWidget ) scaleWidget->setMargin(0); QwtScaleDraw *scaleDraw = (QwtScaleDraw *)plot->axisScaleDraw(i); if ( scaleDraw ) scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false); } } void DataPlot2D::BufEvent(char **buf,int *buf_size,uint16_t period,bool big_endian) { plot->setEnabled(IsEnabled()); if(IsEnabled()==false || RefreshRate_ms()!=period) return; for(int i=0;icount();i++) { if(datas_type->at(i)=="float") { uint32_t data1_raw; float* data1=(float*)&data1_raw; uint32_t data2_raw; float* data2=(float*)&data2_raw; memcpy((void*)&data1_raw,*buf,sizeof(uint32_t)); *buf+=sizeof(uint32_t); memcpy((void*)&data2_raw,*buf,sizeof(uint32_t)); *buf+=sizeof(uint32_t); if(big_endian==true) data1_raw=qFromBigEndian(data1_raw); if(big_endian==true) data2_raw=qFromBigEndian(data2_raw); plot_data(*data1,*data2,i); } else if(datas_type->at(i)=="int8_t") { int8_t data1,data2; memcpy((void*)&data1,*buf,sizeof(data1)); *buf+=sizeof(data1); memcpy((void*)&data2,*buf,sizeof(data2)); *buf+=sizeof(data2); plot_data(data1,data2,i); } else if(datas_type->at(i)=="int16_t") { int16_t data1,data2; memcpy((void*)&data1,*buf,sizeof(data1)); *buf+=sizeof(data1); memcpy((void*)&data2,*buf,sizeof(data2)); *buf+=sizeof(data2); plot_data(data1,data2,i); } else { printf("DataPlot1D::DrawDatas type non connu\n"); } } plot->replot(); } void DataPlot2D::plot_data(double data_x,double data_y,int index) { if(indexbutton() == Qt::RightButton) { QMenu * menu = new QMenu("nom", plot); // ajout des actions QAction *a,*z,*d; a=menu->addAction("reset zoom"); menu->addSeparator(); d=menu->addAction(QString("set view size (%1s)").arg(view_size)); appendmenu(menu); z=execmenu(plot,menu,event->globalPos()); delete menu; if(z==a) { //zoom to original size plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig); plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig); } if(z==d) { bool ok; float time = QInputDialog::getInt(plot, QString("Set view size (%1)").arg(plot->title().text()),tr("Value (s):"), view_size, 1, 65535, 10, &ok); if(ok==true) { for(int i=0;icount();i++) { if(time>view_size) { double* buf=(double*)malloc(time/refresh_rate*sizeof(double)); d_x[i]=(double*)realloc(d_x.at(i),time/refresh_rate*sizeof(double)); memcpy(buf,d_x[i],(view_size/refresh_rate)*sizeof(double)); memcpy(&d_x[i][(int)(time/refresh_rate)-(int)(view_size/refresh_rate)],buf,(view_size/refresh_rate)*sizeof(double)); d_y[i]=(double*)realloc(d_y.at(i),time/refresh_rate*sizeof(double)); memcpy(buf,d_y[i],(view_size/refresh_rate)*sizeof(double)); memcpy(&d_y[i][(int)(time/refresh_rate)-(int)(view_size/refresh_rate)],buf,(view_size/refresh_rate)*sizeof(double)); free(buf); for(int j=0;j<(int)(time/refresh_rate)-(int)(view_size/refresh_rate);j++) { d_x.at(i)[j]=d_x.at(i)[(int)(time/refresh_rate)-(int)(view_size/refresh_rate)+1]; d_y.at(i)[j]=d_y.at(i)[(int)(time/refresh_rate)-(int)(view_size/refresh_rate)+1]; } } else { double* buf=(double*)malloc(time/refresh_rate*sizeof(double)); memcpy(buf,&d_x[i][(int)(view_size/refresh_rate)-(int)(time/refresh_rate)],(time/refresh_rate)*sizeof(double)); d_x[i]=(double*)realloc(d_x.at(i),time/refresh_rate*sizeof(double)); memcpy(d_x[i],buf,(time/refresh_rate)*sizeof(double)); memcpy(buf,&d_y[i][(int)(view_size/refresh_rate)-(int)(time/refresh_rate)],(time/refresh_rate)*sizeof(double)); d_y[i]=(double*)realloc(d_y.at(i),time/refresh_rate*sizeof(double)); memcpy(d_y[i],buf,(time/refresh_rate)*sizeof(double)); free(buf); } datas->at(i)->setRawSamples(d_x.at(i), d_y.at(i), time/refresh_rate); } view_size=time; } } } }