diff --git a/src/plot.cpp b/src/plot.cpp --- a/src/plot.cpp +++ b/src/plot.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2017 Hasan Yavuz Özderya + Copyright © 2018 Hasan Yavuz Özderya This file is part of serialplot. @@ -31,9 +31,9 @@ static const int SYMBOL_SHOW_AT_WIDTH = 5; static const int SYMBOL_SIZE_MAX = 7; -Plot::Plot(QWidget* parent) : +Plot::Plot(const Stream* stream, QWidget* parent) : QwtPlot(parent), - zoomer(this->canvas(), false), + zoomer(this->canvas(), stream, false), sZoomer(this, &zoomer) { isAutoScaled = true; diff --git a/src/plot.h b/src/plot.h --- a/src/plot.h +++ b/src/plot.h @@ -1,5 +1,5 @@ /* - Copyright © 2017 Hasan Yavuz Özderya + Copyright © 2018 Hasan Yavuz Özderya This file is part of serialplot. @@ -47,7 +47,7 @@ public: ShowSymbolsHide }; - Plot(QWidget* parent = 0); + Plot(const Stream* stream, QWidget* parent = 0); ~Plot(); public slots: diff --git a/src/plotmanager.cpp b/src/plotmanager.cpp --- a/src/plotmanager.cpp +++ b/src/plotmanager.cpp @@ -31,9 +31,9 @@ PlotManager::PlotManager(QWidget* plotAr const Stream* stream, QObject* parent) : QObject(parent) { + _stream = stream; construct(plotArea, menu); - _stream = stream; - if (_stream == NULL) return; + if (_stream == nullptr) return; // connect to ChannelInfoModel infoModel = _stream->infoModel(); @@ -62,6 +62,7 @@ PlotManager::PlotManager(QWidget* plotAr Snapshot* snapshot, QObject *parent) : QObject(parent) { + _stream = nullptr; construct(plotArea, menu); setNumOfSamples(snapshot->numSamples()); @@ -305,7 +306,7 @@ void PlotManager::setupLayout(bool multi Plot* PlotManager::addPlotWidget() { - auto plot = new Plot(); + auto plot = new Plot(_stream); plotWidgets.append(plot); layout->addWidget(plot); diff --git a/src/plotmanager.h b/src/plotmanager.h --- a/src/plotmanager.h +++ b/src/plotmanager.h @@ -41,7 +41,7 @@ class PlotManager : public QObject public: explicit PlotManager(QWidget* plotArea, PlotMenu* menu, - const Stream* stream = NULL, + const Stream* stream = nullptr, QObject *parent = 0); explicit PlotManager(QWidget* plotArea, PlotMenu* menu, Snapshot* snapshot, @@ -82,7 +82,7 @@ private: QList curves; QList plotWidgets; Plot* emptyPlot; ///< for displaying when all channels are hidden - const Stream* _stream; ///< attached stream, can be `NULL` + const Stream* _stream; ///< attached stream, can be `nullptr` const ChannelInfoModel* infoModel; bool isDemoShown; bool _autoScaled; diff --git a/src/stream.h b/src/stream.h --- a/src/stream.h +++ b/src/stream.h @@ -51,9 +51,8 @@ public: Stream(unsigned nc = 0, bool x = false, unsigned ns = 0); ~Stream(); - // implementations for `Source` - virtual bool hasX() const; - virtual unsigned numChannels() const; + bool hasX() const; + unsigned numChannels() const; unsigned numSamples() const; const StreamChannel* channel(unsigned index) const; diff --git a/src/streamchannel.cpp b/src/streamchannel.cpp --- a/src/streamchannel.cpp +++ b/src/streamchannel.cpp @@ -17,6 +17,7 @@ along with serialplot. If not, see . */ +#include #include "streamchannel.h" StreamChannel::StreamChannel(unsigned i, const FrameBuffer* x, @@ -42,3 +43,35 @@ const FrameBuffer* StreamChannel::yData( FrameBuffer* StreamChannel::yData() {return _y;} const ChannelInfoModel* StreamChannel::info() const {return _info;} void StreamChannel::setX(const FrameBuffer* x) {_x = x;}; + +double StreamChannel::findValue(double x) const +{ + int index = findIndex(x); + if (index >= 0) + return _y->sample(index); + else + return std::numeric_limits::quiet_NaN(); +} + +int StreamChannel::findIndex(double x) const +{ + // TODO: optimize, implement in `framebuffer` + bool first = true; + for (int i = _x->size()-1; i > 0; i--) + { + double val = _x->sample(i); + if (x >= val) + { + // TODO: optional linear approx. method + // check if previous sample (bigger one) is actually closer + if (!first && (x - val) > (_x->sample(i + 1) - x)) + { + ++i; + } + + return i; + } + first = false; + } + return -1; +} diff --git a/src/streamchannel.h b/src/streamchannel.h --- a/src/streamchannel.h +++ b/src/streamchannel.h @@ -50,11 +50,17 @@ public: const ChannelInfoModel* info() const; void setX(const FrameBuffer* x); + /// Returns sample value for closest X + double findValue(double x) const; + private: unsigned _index; const FrameBuffer* _x; FrameBuffer* _y; ChannelInfoModel* _info; + + /// Finds index of closest X in `xData` + int findIndex(double x) const; }; #endif // STREAMCHANNEL_H diff --git a/src/zoomer.cpp b/src/zoomer.cpp --- a/src/zoomer.cpp +++ b/src/zoomer.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2017 Hasan Yavuz Özderya + Copyright © 2018 Hasan Yavuz Özderya This file is part of serialplot. @@ -23,10 +23,11 @@ #include -Zoomer::Zoomer(QWidget* widget, bool doReplot) : +Zoomer::Zoomer(QWidget* widget, const Stream* stream, bool doReplot) : ScrollZoomer(widget) { is_panning = false; + _stream = stream; setTrackerMode(AlwaysOn); @@ -102,6 +103,31 @@ QRegion Zoomer::rubberBandMask() const return QRegion(r); } +void Zoomer::drawTracker(QPainter* painter) const +{ + ScrollZoomer::drawTracker(painter); + auto x = invTransform(trackerPosition()).x(); + qDebug() << x; + if (_stream != nullptr && _stream->numChannels()) + { + qDebug() << findValues(x); + } + return; +} + +QVector Zoomer::findValues(double x) const +{ + unsigned nc = _stream->numChannels(); + QVector r(nc); + for (unsigned ci = 0; ci < nc; ci++) + { + auto chan = _stream->channel(ci); + double val = chan->findValue(x); + r[ci] = val; + } + return r; +} + void Zoomer::widgetMousePressEvent(QMouseEvent* mouseEvent) { if (mouseEvent->modifiers() & Qt::ControlModifier) diff --git a/src/zoomer.h b/src/zoomer.h --- a/src/zoomer.h +++ b/src/zoomer.h @@ -1,5 +1,5 @@ /* - Copyright © 2017 Hasan Yavuz Özderya + Copyright © 2018 Hasan Yavuz Özderya This file is part of serialplot. @@ -20,16 +20,19 @@ #ifndef ZOOMER_H #define ZOOMER_H -#include +#include + +#include "scrollzoomer.h" +#include "stream.h" class Zoomer : public ScrollZoomer { Q_OBJECT public: - Zoomer(QWidget *, bool doReplot=true); + Zoomer(QWidget*, const Stream* stream, bool doReplot=true); void zoom(int up); - void zoom( const QRectF & ); + void zoom(const QRectF&); signals: void unzoomed(); @@ -39,6 +42,8 @@ protected: QwtText trackerTextF(const QPointF &pos) const; /// Re-implemented for alpha background void drawRubberBand(QPainter* painter) const; + /// Re-implemented to draw sample values + void drawTracker(QPainter* painter) const; /// Re-implemented for alpha background (masking is basically disabled) QRegion rubberBandMask() const; /// Overloaded for panning @@ -51,6 +56,9 @@ protected: private: bool is_panning; QPointF pan_point; + const Stream* _stream; + + QVector findValues(double x) const; }; #endif // ZOOMER_H