timeseries_qwt.cpp
Go to the documentation of this file.
00001 #include "timeseries_qwt.h"
00002 #include <limits>
00003 #include <stdexcept>
00004 #include <QMessageBox>
00005 #include <QString>
00006 
00007 TimeseriesQwt::TimeseriesQwt(PlotDataPtr base):
00008     _plot_data(base),
00009     _subsample(1),
00010     _transform( noTransform ),
00011     _time_offset(0)
00012 {
00013     updateData();
00014 }
00015 
00016 QPointF TimeseriesQwt::sample(size_t i) const
00017 {
00018     if(_transform == noTransform)
00019     {
00020         auto p = _plot_data->at(i);
00021         return QPointF(p.x - _time_offset, p.y);
00022     }
00023     return _cached_transformed_curve[i];
00024 }
00025 
00026 QRectF TimeseriesQwt::boundingRect() const
00027 {
00028     return _bounding_box;
00029 }
00030 
00031 size_t TimeseriesQwt::size() const
00032 {
00033     if(_transform == noTransform){
00034         return _plot_data->size();
00035     }
00036     return _cached_transformed_curve.size();
00037 }
00038 
00039 void TimeseriesQwt::setSubsampleFactor()
00040 {
00041     //  _subsample = (_plot_data->size() / 2000) + 1;
00042 }
00043 
00044 void TimeseriesQwt::updateData()
00045 {
00046     if(_plot_data->size() == 0) return;
00047 
00048     double min_y =( std::numeric_limits<double>::max() );
00049     double max_y =(-std::numeric_limits<double>::max() );
00050     double min_x =( std::numeric_limits<double>::max() );
00051     double max_x =(-std::numeric_limits<double>::max() );
00052 
00053     //if(updated || force_transform)
00054     {
00055         if(_transform == noTransform)
00056         {
00057             _cached_transformed_curve.resize( 0 );
00058             _cached_transformed_curve.shrink_to_fit();
00059 
00060             for (size_t i=0; i< _plot_data->size(); i++ )
00061             {
00062                 auto p = _plot_data->at( i );
00063                 p.x -= _time_offset;
00064 
00065                 if(min_y > p.y) min_y =(p.y);
00066                 else if(max_y    < p.y) max_y =(p.y);
00067 
00068                 if(min_x   > p.x) min_x =(p.x);
00069                 else if(max_x  < p.x) max_x =(p.x);
00070             }
00071         }
00072         else if(_transform == firstDerivative)
00073         {
00074             if( _plot_data->size() < 1){
00075                 _cached_transformed_curve.clear();
00076             }
00077             else{
00078                 _cached_transformed_curve.resize( _plot_data->size() - 1 );
00079             }
00080 
00081             for (size_t i=0; i< _plot_data->size() -1; i++ )
00082             {
00083                 const auto& p0 = _plot_data->at( i );
00084                 const auto& p1 = _plot_data->at( i+1 );
00085                 const auto delta = p1.x - p0.x;
00086                 const auto vel = (p1.y - p0.y) /delta;
00087                 QPointF p( (p1.x + p0.x)*0.5, vel);
00088                 p.setX( p.x() - _time_offset);
00089                 _cached_transformed_curve[i] = p;
00090 
00091                 if(min_y > p.y()) min_y =(p.y());
00092                 else if(max_y    < p.y()) max_y =(p.y());
00093 
00094                 if(min_x   > p.x()) min_x =(p.x());
00095                 else if(max_x  < p.x()) max_x =(p.x());
00096             }
00097         }
00098         else if(_transform == secondDerivative)
00099         {
00100             if( _plot_data->size() < 2){
00101                 _cached_transformed_curve.clear();
00102             }
00103             else{
00104                 _cached_transformed_curve.resize( _plot_data->size() - 2 );
00105             }
00106 
00107             for (size_t i=0; i< _cached_transformed_curve.size(); i++ )
00108             {
00109                 const auto& p0 = _plot_data->at( i );
00110                 const auto& p1 = _plot_data->at( i+1 );
00111                 const auto& p2 = _plot_data->at( i+2 );
00112                 const auto delta = (p2.x - p0.x) *0.5;
00113                 const auto acc = ( p2.y - 2.0* p1.y + p0.y)/(delta*delta);
00114                 QPointF p( (p2.x + p0.x)*0.5, acc );
00115                 p.setX( p.x() - _time_offset);
00116                 _cached_transformed_curve[i] = p;
00117 
00118                 if(min_y > p.y()) min_y =(p.y());
00119                 else if(max_y    < p.y()) max_y =(p.y());
00120 
00121                 if(min_x   > p.x()) min_x =(p.x());
00122                 else if(max_x  < p.x()) max_x =(p.x());
00123             }
00124         }
00125         else if( _transform == XYPlot && _alternative_X_axis)
00126         {
00127             bool failed = false;
00128             const size_t N = _alternative_X_axis->size();
00129 
00130             if( _plot_data->size() != N ){
00131                 failed = true ;
00132             }
00133 
00134             for (size_t i=0; i<N && !failed; i++ )
00135             {
00136                 if( _alternative_X_axis->at(i).x != _plot_data->at(i).x ){
00137                     failed = true ;
00138                     break;
00139                 }
00140             }
00141 
00142             if( failed){
00143                 QMessageBox::warning(0, QString("Warning"),
00144                                      QString("The creation of the XY plot failed because at least two "
00145                                              "timeseries don't share the same time axis.") );
00146                 return;
00147             }
00148             else{
00149                 _cached_transformed_curve.resize(N);
00150                 for (size_t i=0; i<N; i++ )
00151                 {
00152                     const QPointF p(_alternative_X_axis->at(i).y, _plot_data->at(i).y );
00153                     _cached_transformed_curve[i] = p;
00154 
00155                     if(min_y > p.y()) min_y =(p.y());
00156                     else if(max_y    < p.y()) max_y =(p.y());
00157 
00158                     if(min_x   > p.x()) min_x =(p.x());
00159                     else if(max_x  < p.x()) max_x =(p.x());
00160                 }
00161             }
00162         }
00163     }
00164     _bounding_box.setBottom(min_y);
00165     _bounding_box.setTop(max_y);
00166     _bounding_box.setLeft(min_x);
00167     _bounding_box.setRight(max_x);
00168 }
00169 
00170 PlotData::RangeTimeOpt TimeseriesQwt::getVisualizationRangeX()
00171 {   
00172     // std::lock_guard<std::mutex> lock(_mutex);
00173     if( this->size() < 2 )
00174         return  PlotData::RangeTimeOpt();
00175     else{
00176         return PlotData::RangeTimeOpt( { _bounding_box.left(), _bounding_box.right() } );
00177     }
00178 }
00179 
00180 
00181 PlotData::RangeValueOpt TimeseriesQwt::getVisualizationRangeY(int first_index, int last_index)
00182 {
00183     if( first_index < 0 || last_index < 0 || first_index > last_index)
00184     {
00185         return PlotData::RangeValueOpt();
00186     }
00187 
00188     if( (_transform == XYPlot && _alternative_X_axis) ||
00189             ( first_index==0 && last_index == size() -1) )
00190     {
00191         return PlotData::RangeValueOpt( { _bounding_box.bottom(), _bounding_box.top() } );
00192     }
00193 
00194     const double first_Y = sample(first_index).y();
00195     double y_min = first_Y;
00196     double y_max = first_Y;
00197 
00198     for (int i = first_index+1; i < last_index; i++)
00199     {
00200         const double Y = sample(i).y();
00201 
00202         if( Y < y_min )      y_min = Y;
00203         else if( Y > y_max ) y_max = Y;
00204     }
00205     return PlotData::RangeValueOpt( { y_min, y_max } );
00206 }
00207 
00208 void TimeseriesQwt::setAlternativeAxisX(PlotDataPtr new_x_data)
00209 {
00210     _alternative_X_axis = new_x_data;
00211 }
00212 
00213 nonstd::optional<QPointF> TimeseriesQwt::sampleFromTime(double t)
00214 {
00215     if( _transform == XYPlot && _alternative_X_axis)
00216     {
00217         auto res1 = _alternative_X_axis->getYfromX( t );
00218         if( res1)
00219         {
00220             auto res2 = _plot_data->getYfromX( t );
00221             if( res2 ){
00222                 return nonstd::optional<QPointF>(
00223                             QPointF(res1.value(), res2.value() ) ) ;
00224             }
00225         }
00226     }
00227     else{
00228         auto res = _plot_data->getYfromX( t );
00229         if(res){
00230             return nonstd::optional<QPointF>( QPointF(t, res.value() ) ) ;
00231         }
00232     }
00233     return nonstd::optional<QPointF>();
00234 }
00235 
00236 void TimeseriesQwt::setTransform(TimeseriesQwt::Transform trans)
00237 {
00238     if(trans != _transform)
00239     {
00240         _transform = trans;
00241         updateData();
00242     }
00243 }
00244 
00245 void TimeseriesQwt::setTimeOffset(double offset)
00246 {
00247     _time_offset = offset;
00248     updateData();
00249 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:57