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
00197
00198
00199
00200
00201
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 <>
00226 inline void PlotDataGeneric<double, double>::pushBack(Point point)
00227 {
00228 if( std::isinf( point.y ) || std::isnan( point.y ) )
00229 {
00230 return;
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