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
00016 template <typename Time, typename Value> class PlotDataGeneric
00017 {
00018 public:
00019
00020 struct RangeTime{
00021 Time min;
00022 Time max;
00023 };
00024
00025 struct RangeValue{
00026 Value min;
00027 Value max;
00028 };
00029
00030 typedef nonstd::optional<RangeTime> RangeTimeOpt;
00031 typedef nonstd::optional<RangeValue> RangeValueOpt;
00032
00033 class Point{
00034 public:
00035 Time x;
00036 Value y;
00037 Point( Time _x, Value _y):
00038 x(_x), y(_y) {}
00039 Point() = default;
00040 };
00041
00042 enum{
00043 MAX_CAPACITY = 1024*1024,
00044 ASYNC_BUFFER_CAPACITY = 1024
00045 };
00046
00047 typedef Time TimeType;
00048
00049 typedef Value ValueType;
00050
00051 PlotDataGeneric(const char* name);
00052
00053 virtual ~PlotDataGeneric() {}
00054
00055 std::string name() const { return _name; }
00056
00057 virtual size_t size() const;
00058
00059 int getIndexFromX(Time x) const;
00060
00061 nonstd::optional<Value> getYfromX(Time x ) const;
00062
00063 const Point& at(size_t index) const;
00064
00065 void clear();
00066
00067 void pushBack(Point p);
00068
00069 void pushBackAsynchronously(Point p);
00070
00071 bool flushAsyncBuffer();
00072
00073 QColor getColorHint() const;
00074
00075 void setColorHint(QColor color);
00076
00077 void setMaximumRangeX(Time max_range);
00078
00079 static std::mutex& asyncPushMutex() { return _mutex; }
00080
00081 protected:
00082
00083 std::string _name;
00084 std::deque<Point> _points;
00085 std::deque<Point> _pushed_points;
00086
00087 QColor _color_hint;
00088
00089 private:
00090
00091 Time _max_range_X;
00092 static std::mutex _mutex;
00093 };
00094
00095
00096 typedef PlotDataGeneric<double,double> PlotData;
00097 typedef PlotDataGeneric<double, nonstd::any> PlotDataAny;
00098
00099
00100 typedef std::shared_ptr<PlotData> PlotDataPtr;
00101 typedef std::shared_ptr<PlotDataAny> PlotDataAnyPtr;
00102
00103 typedef struct{
00104 std::map<std::string, PlotDataPtr> numeric;
00105 std::map<std::string, PlotDataAnyPtr> user_defined;
00106 } PlotDataMap;
00107
00108
00109
00110
00111 template < typename Time, typename Value>
00112 std::mutex PlotDataGeneric<Time, Value>::_mutex;
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 template<typename Time, typename Value>
00124 inline PlotDataGeneric<Time, Value>::PlotDataGeneric(const char *name):
00125 _max_range_X( std::numeric_limits<Time>::max() )
00126 , _color_hint(Qt::black)
00127 , _name(name)
00128 {
00129 static_assert( std::is_arithmetic<Time>::value ,"Only numbers can be used as time");
00130 }
00131
00132 template < typename Time, typename Value>
00133 inline void PlotDataGeneric<Time, Value>::pushBack(Point point)
00134 {
00135 _points.push_back( point );
00136 }
00137
00138 template < typename Time, typename Value>
00139 inline void PlotDataGeneric<Time, Value>::pushBackAsynchronously(Point point)
00140 {
00141 _pushed_points.push_back( point );
00142 while(_pushed_points.size() > ASYNC_BUFFER_CAPACITY) _pushed_points.pop_front();
00143 }
00144
00145 template < typename Time, typename Value>
00146 inline bool PlotDataGeneric<Time, Value>::flushAsyncBuffer()
00147 {
00148
00149 if( _pushed_points.empty() ) return false;
00150
00151 while( !_pushed_points.empty() )
00152 {
00153 const Point& point = _pushed_points.front();
00154 _points.push_back( point );
00155 _pushed_points.pop_front();
00156 }
00157
00158 while( _points.size()>2 &&
00159 _points.back().x - _points.front().x > _max_range_X)
00160 {
00161 _points.pop_front();
00162 }
00163 return true;
00164 }
00165
00166
00167 template < typename Time, typename Value>
00168 inline int PlotDataGeneric<Time, Value>::getIndexFromX(Time x ) const
00169 {
00170 if( _points.size() == 0 ){
00171 return -1;
00172 }
00173 auto lower = std::lower_bound(_points.begin(), _points.end(), Point(x,0),
00174 [](const Point &a, const Point &b)
00175 { return a.x < b.x; } );
00176
00177 auto index = std::distance( _points.begin(), lower);
00178
00179 if( index >= _points.size() )
00180 {
00181 return _points.size() -1;
00182 }
00183 if( index < 0)
00184 {
00185 return 0;
00186 }
00187 return index;
00188 }
00189
00190
00191 template < typename Time, typename Value>
00192 inline nonstd::optional<Value> PlotDataGeneric<Time, Value>::getYfromX(Time x) const
00193 {
00194 int index = getIndexFromX( x );
00195 if( index == -1 )
00196 {
00197 return nonstd::optional<Value>();
00198 }
00199 return _points.at(index).y;
00200 }
00201
00202 template < typename Time, typename Value>
00203 inline const typename PlotDataGeneric<Time, Value>::Point&
00204 PlotDataGeneric<Time, Value>::at(size_t index) const
00205 {
00206 return _points[index];
00207 }
00208
00209 template<typename Time, typename Value>
00210 void PlotDataGeneric<Time, Value>::clear()
00211 {
00212 _points.clear();
00213 }
00214
00215
00216 template < typename Time, typename Value>
00217 inline size_t PlotDataGeneric<Time, Value>::size() const
00218 {
00219 return _points.size();
00220 }
00221
00222 template < typename Time, typename Value>
00223 inline QColor PlotDataGeneric<Time, Value>::getColorHint() const
00224 {
00225 return _color_hint;
00226 }
00227
00228 template < typename Time, typename Value>
00229 inline void PlotDataGeneric<Time, Value>::setColorHint(QColor color)
00230 {
00231 _color_hint = color;
00232 }
00233
00234
00235 template < typename Time, typename Value>
00236 inline void PlotDataGeneric<Time, Value>::setMaximumRangeX(Time max_range)
00237 {
00238 _max_range_X = max_range;
00239 }
00240
00241 #endif // PLOTDATA_H