plotdata.h
Go to the documentation of this file.
00001 #ifndef PLOTDATA_RAW_H
00002 #define PLOTDATA_RAW_H
00003 
00004 #include <vector>
00005 #include <memory>
00006 #include <string>
00007 #include <map>
00008 #include <mutex>
00009 #include <deque>
00010 #include "PlotJuggler/optional.hpp"
00011 #include "PlotJuggler/any.hpp"
00012 #include <QDebug>
00013 #include <QColor>
00014 #include <type_traits>
00015 #include <cmath>
00016 #include <cstdlib>
00017 #include <unordered_map>
00018 
00019 inline double Abs(double val)
00020 {
00021     return val < 0 ? -val : val;
00022 }
00023 
00024 template <typename Time, typename Value> class PlotDataGeneric
00025 {
00026 public:
00027 
00028   struct RangeTime{
00029     Time min;
00030     Time max;
00031   };
00032 
00033   struct RangeValue{
00034     Value min;
00035     Value max;
00036   };
00037 
00038   typedef nonstd::optional<RangeTime>  RangeTimeOpt;
00039   typedef nonstd::optional<RangeValue> RangeValueOpt;
00040 
00041   class Point{
00042   public:
00043     Time x;
00044     Value y;
00045     Point( Time _x, Value _y):
00046         x(_x), y(_y) {}
00047     Point() = default;   
00048   };
00049 
00050   enum{
00051     MAX_CAPACITY = 1024*1024,
00052     ASYNC_BUFFER_CAPACITY = 1024
00053   };
00054 
00055   typedef Time    TimeType;
00056 
00057   typedef Value   ValueType;
00058 
00059   typedef typename std::deque<Point>::iterator Iterator;
00060 
00061   typedef typename std::deque<Point>::const_iterator ConstIterator;
00062 
00063   PlotDataGeneric(const std::string& name);
00064 
00065   PlotDataGeneric( const PlotDataGeneric<Time,Value>& other) = delete;
00066 
00067   PlotDataGeneric(PlotDataGeneric&& other)
00068   {
00069       _name = std::move(other._name);
00070       _points = std::move(other._points);
00071       _color_hint = std::move(other._color_hint);
00072       _max_range_X = other._max_range_X;
00073   }
00074 
00075   void swapData( PlotDataGeneric<Time,Value>& other)
00076   {
00077       std::swap(_points, other._points);
00078   }
00079 
00080   PlotDataGeneric& operator = (const PlotDataGeneric<Time,Value>& other) = delete;
00081 
00082   virtual ~PlotDataGeneric() {}
00083 
00084   const std::string& name() const { return _name; }
00085 
00086   virtual size_t size() const;
00087 
00088   int getIndexFromX(Time x) const;
00089 
00090   nonstd::optional<Value> getYfromX(Time x ) const;
00091 
00092   const Point &at(size_t index) const;
00093 
00094   Point &at(size_t index);
00095 
00096   const Point& operator[](size_t index) const { return at(index); }
00097 
00098   Point& operator[](size_t index) { return at(index); }
00099 
00100   void clear();
00101 
00102   void pushBack(Point p);
00103 
00104   QColor getColorHint() const;
00105 
00106   void setColorHint(QColor color);
00107 
00108   void setMaximumRangeX(Time max_range);
00109 
00110   Time maximumRangeX() const { return _max_range_X; }
00111 
00112   const Point& front() const { return _points.front(); }
00113 
00114   const Point& back() const { return _points.back(); }
00115 
00116   ConstIterator begin() const { return _points.begin(); }
00117 
00118   ConstIterator end() const { return _points.end(); }
00119 
00120   Iterator begin() { return _points.begin(); }
00121 
00122   Iterator end() { return _points.end(); }
00123 
00124   void resize(size_t new_size) { _points.resize(new_size); }
00125 
00126   void popFront() { _points.pop_front(); }
00127 
00128 protected:
00129 
00130   std::string _name;
00131   std::deque<Point> _points;
00132   QColor _color_hint;
00133 
00134 private:
00135   Time _max_range_X;
00136 };
00137 
00138 
00139 typedef PlotDataGeneric<double,double>  PlotData;
00140 typedef PlotDataGeneric<double, nonstd::any> PlotDataAny;
00141 
00142 
00143 typedef struct{
00144   std::unordered_map<std::string, PlotData>     numeric;
00145   std::unordered_map<std::string, PlotDataAny>  user_defined;
00146 
00147   std::unordered_map<std::string, PlotData>::iterator addNumeric(const std::string& name)
00148   {
00149       return numeric.emplace( std::piecewise_construct,
00150                        std::forward_as_tuple(name),
00151                        std::forward_as_tuple(name)
00152                        ).first;
00153   }
00154 
00155 
00156   std::unordered_map<std::string, PlotDataAny>::iterator addUserDefined(const std::string& name)
00157   {
00158       return user_defined.emplace( std::piecewise_construct,
00159                                    std::forward_as_tuple(name),
00160                                    std::forward_as_tuple(name)
00161                                    ).first;
00162   }
00163 
00164 } PlotDataMapRef;
00165 
00166 
00167 //-----------------------------------
00168 template<typename Value>
00169 inline void AddPrefixToPlotData(const std::string &prefix, std::unordered_map<std::string, Value>& data)
00170 {
00171     if( prefix.empty() ) return;
00172 
00173     std::unordered_map<std::string, Value> temp;
00174 
00175     for(auto& it: data)
00176     {
00177         std::string key;
00178         key.reserve( prefix.size() + 2 + it.first.size() );
00179         if( it.first.front() == '/' )
00180         {
00181             key = prefix + it.first;
00182         }
00183         else{
00184             key = prefix + "/" + it.first;
00185         }
00186 
00187         auto new_plot = temp.emplace( std::piecewise_construct,
00188                                       std::forward_as_tuple(key),
00189                                       std::forward_as_tuple(key) ).first;
00190 
00191         new_plot->second.swapData( it.second );
00192     }
00193     std::swap(data, temp);
00194 }
00195 
00196 //template < typename Time, typename Value>
00197 //inline PlotDataGeneric<Time, Value>::PlotDataGeneric():
00198 //  _max_range_X( std::numeric_limits<Time>::max() )
00199 //  , _color_hint(Qt::black)
00200 //{
00201 //    static_assert( std::is_arithmetic<Time>::value ,"Only numbers can be used as time");
00202 //}
00203 
00204 template<typename Time, typename Value>
00205 inline PlotDataGeneric<Time, Value>::PlotDataGeneric(const std::string &name):
00206     _max_range_X( std::numeric_limits<Time>::max() )
00207     , _color_hint(Qt::black)
00208     , _name(name)
00209 {
00210     static_assert( std::is_arithmetic<Time>::value ,"Only numbers can be used as time");
00211 }
00212 
00213 template < typename Time, typename Value>
00214 inline void PlotDataGeneric<Time, Value>::pushBack(Point point)
00215 {
00216   _points.push_back( point );
00217 
00218   while( _points.size()>2 &&
00219          (_points.back().x - _points.front().x) > _max_range_X)
00220   {
00221         _points.pop_front();
00222   }
00223 }
00224 
00225 template <> // template specialization
00226 inline void PlotDataGeneric<double, double>::pushBack(Point point)
00227 {
00228     if( std::isinf( point.y ) || std::isnan( point.y ) )
00229     {
00230         return; // skip
00231     }
00232     _points.push_back( point );
00233 
00234     while( _points.size()>2 &&
00235            (_points.back().x - _points.front().x) > _max_range_X)
00236     {
00237         _points.pop_front();
00238     }
00239 }
00240 
00241 template < typename Time, typename Value>
00242 inline int PlotDataGeneric<Time, Value>::getIndexFromX(Time x ) const
00243 {
00244   if( _points.size() == 0 ){
00245     return -1;
00246   }
00247   auto lower = std::lower_bound(_points.begin(), _points.end(), Point(x,0),
00248                                 [](const Point &a, const Point &b)
00249                                 { return a.x < b.x; } );
00250   auto index = std::distance( _points.begin(), lower);
00251 
00252   if( index >= _points.size() )
00253   {
00254     return _points.size() -1;
00255   }
00256   if( index < 0)
00257   {
00258     return 0;
00259   }
00260 
00261   if( index > 0)
00262   {
00263     if( Abs( _points[index-1].x - x) < Abs( _points[index].x - x) )
00264     {
00265       return index-1;
00266     }
00267     else{
00268       return index;
00269     }
00270   }
00271   return index;
00272 }
00273 
00274 
00275 template < typename Time, typename Value>
00276 inline nonstd::optional<Value> PlotDataGeneric<Time, Value>::getYfromX(Time x) const
00277 {
00278   int index = getIndexFromX( x );
00279   if( index == -1 )
00280   {
00281     return nonstd::optional<Value>();
00282   }
00283   return _points.at(index).y;
00284 }
00285 
00286 template < typename Time, typename Value>
00287 inline const typename PlotDataGeneric<Time, Value>::Point&
00288 PlotDataGeneric<Time, Value>::at(size_t index) const
00289 {
00290     return _points[index];
00291 }
00292 
00293 template < typename Time, typename Value>
00294 inline typename PlotDataGeneric<Time, Value>::Point&
00295 PlotDataGeneric<Time, Value>::at(size_t index)
00296 {
00297     return _points[index];
00298 }
00299 
00300 template<typename Time, typename Value>
00301 void PlotDataGeneric<Time, Value>::clear()
00302 {
00303     _points.clear();
00304 }
00305 
00306 
00307 template < typename Time, typename Value>
00308 inline size_t PlotDataGeneric<Time, Value>::size() const
00309 {
00310   return _points.size();
00311 }
00312 
00313 template < typename Time, typename Value>
00314 inline QColor PlotDataGeneric<Time, Value>::getColorHint() const
00315 {
00316   return _color_hint;
00317 }
00318 
00319 template < typename Time, typename Value>
00320 inline void PlotDataGeneric<Time, Value>::setColorHint(QColor color)
00321 {
00322   _color_hint = color;
00323 }
00324 
00325 
00326 template < typename Time, typename Value>
00327 inline void PlotDataGeneric<Time, Value>::setMaximumRangeX(Time max_range)
00328 {
00329   _max_range_X = max_range;
00330   while( _points.size()>2 &&
00331          _points.back().x - _points.front().x > _max_range_X)
00332   {
00333         _points.pop_front();
00334   }
00335 }
00336 
00337 #endif // PLOTDATA_H


plotjuggler
Author(s): Davide Faconti
autogenerated on Wed Jul 3 2019 19:28:04