summaryrefslogtreecommitdiff
path: root/gr-qtgui/lib/TimeDomainDisplayPlot.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-qtgui/lib/TimeDomainDisplayPlot.cc')
-rw-r--r--gr-qtgui/lib/TimeDomainDisplayPlot.cc311
1 files changed, 311 insertions, 0 deletions
diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc
new file mode 100644
index 000000000..f635a2b0c
--- /dev/null
+++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc
@@ -0,0 +1,311 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TIME_DOMAIN_DISPLAY_PLOT_C
+#define TIME_DOMAIN_DISPLAY_PLOT_C
+
+#include <TimeDomainDisplayPlot.h>
+
+#include <qwt_scale_draw.h>
+#include <qwt_legend.h>
+#include <QColor>
+#include <iostream>
+
+class TimePrecisionClass
+{
+public:
+ TimePrecisionClass(const int timePrecision)
+ {
+ _timePrecision = timePrecision;
+ }
+
+ virtual ~TimePrecisionClass()
+ {
+ }
+
+ virtual unsigned int GetTimePrecision() const
+ {
+ return _timePrecision;
+ }
+
+ virtual void SetTimePrecision(const unsigned int newPrecision)
+ {
+ _timePrecision = newPrecision;
+ }
+protected:
+ unsigned int _timePrecision;
+};
+
+
+class TimeDomainDisplayZoomer: public QwtPlotZoomer, public TimePrecisionClass
+{
+public:
+ TimeDomainDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int timePrecision)
+ : QwtPlotZoomer(canvas),TimePrecisionClass(timePrecision)
+ {
+ setTrackerMode(QwtPicker::AlwaysOn);
+ }
+
+ virtual ~TimeDomainDisplayZoomer(){
+
+ }
+
+ virtual void updateTrackerText(){
+ updateDisplay();
+ }
+
+ void SetUnitType(const std::string &type)
+ {
+ _unitType = type;
+ }
+
+protected:
+ using QwtPlotZoomer::trackerText;
+ virtual QwtText trackerText( const QwtDoublePoint& p ) const
+ {
+ QwtText t(QString("%1 %2, %3 V").arg(p.x(), 0, 'f', GetTimePrecision()).
+ arg(_unitType.c_str()).
+ arg(p.y(), 0, 'f', 4));
+
+ return t;
+ }
+
+private:
+ std::string _unitType;
+};
+
+TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent)
+ : QwtPlot(parent), _nplots(nplots)
+{
+ resize(parent->width(), parent->height());
+
+ _numPoints = 1024;
+ _xAxisPoints = new double[_numPoints];
+ memset(_xAxisPoints, 0x0, _numPoints*sizeof(double));
+
+ _zoomer = new TimeDomainDisplayZoomer(canvas(), 0);
+ _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection);
+
+ // Disable polygon clipping
+ QwtPainter::setDeviceClipping(false);
+
+ // We don't need the cache here
+ canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
+ canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
+
+ QPalette palette;
+ palette.setColor(canvas()->backgroundRole(), QColor("white"));
+ canvas()->setPalette(palette);
+
+ setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
+ setXaxis(0, _numPoints);
+ setAxisTitle(QwtPlot::xBottom, "Time (sec)");
+
+ setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
+ setYaxis(-2.0, 2.0);
+ setAxisTitle(QwtPlot::yLeft, "Amplitude");
+
+ QList<QColor> colors;
+ colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green)
+ << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta)
+ << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed)
+ << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray);
+
+ int ncolors = colors.size();
+
+ // Setup dataPoints and plot vectors
+ // Automatically deleted when parent is deleted
+ for(int i = 0; i < _nplots; i++) {
+ _dataPoints.push_back(new double[_numPoints]);
+ memset(_dataPoints[i], 0x0, _numPoints*sizeof(double));
+
+ _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i)));
+ _plot_curve[i]->attach(this);
+ _plot_curve[i]->setPen(QPen(colors[i]));
+ _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints);
+ }
+
+ _sampleRate = 1;
+ _resetXAxisPoints();
+
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
+ Qt::RightButton, Qt::ControlModifier);
+ _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
+ Qt::RightButton);
+
+ _panner = new QwtPlotPanner(canvas());
+ _panner->setAxisEnabled(QwtPlot::yRight, false);
+ _panner->setMouseButton(Qt::MidButton);
+
+ // emit the position of clicks on widget
+ _picker = new QwtDblClickPlotPicker(canvas());
+ connect(_picker, SIGNAL(selected(const QwtDoublePoint &)),
+ this, SLOT(OnPickerPointSelected(const QwtDoublePoint &)));
+
+ // Configure magnify on mouse wheel
+ _magnifier = new QwtPlotMagnifier(canvas());
+ _magnifier->setAxisEnabled(QwtPlot::xBottom, false);
+
+ // Avoid jumping when labels with more/less digits
+ // appear/disappear when scrolling vertically
+
+ const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
+ QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
+ sd->setMinimumExtent( fm.width("100.00") );
+
+ const QColor c(Qt::darkRed);
+ _zoomer->setRubberBandPen(c);
+ _zoomer->setTrackerPen(c);
+
+ QwtLegend* legendDisplay = new QwtLegend(this);
+ legendDisplay->setItemMode(QwtLegend::CheckableItem);
+ insertLegend(legendDisplay);
+
+ connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ),
+ this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) ));
+}
+
+TimeDomainDisplayPlot::~TimeDomainDisplayPlot()
+{
+ for(int i = 0; i < _nplots; i++)
+ delete [] _dataPoints[i];
+ delete[] _xAxisPoints;
+
+ // _zoomer and _panner deleted when parent deleted
+}
+
+void
+TimeDomainDisplayPlot::setYaxis(double min, double max)
+{
+ setAxisScale(QwtPlot::yLeft, min, max);
+ _zoomer->setZoomBase();
+}
+
+void
+TimeDomainDisplayPlot::setXaxis(double min, double max)
+{
+ setAxisScale(QwtPlot::xBottom, min, max);
+ _zoomer->setZoomBase();
+}
+
+void
+TimeDomainDisplayPlot::setTitle(int which, QString title)
+{
+ _plot_curve[which]->setTitle(title);
+}
+
+void
+TimeDomainDisplayPlot::setColor(int which, QString color)
+{
+ _plot_curve[which]->setPen(QPen(color));
+}
+
+void TimeDomainDisplayPlot::replot()
+{
+ QwtPlot::replot();
+}
+
+void
+TimeDomainDisplayPlot::resizeSlot( QSize *s )
+{
+ // -10 is to spare some room for the legend and x-axis label
+ resize(s->width()-10, s->height()-10);
+}
+
+void TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints,
+ const int64_t numDataPoints,
+ const double timeInterval)
+{
+ if((numDataPoints > 0)) {
+ if(numDataPoints != _numPoints){
+ _numPoints = numDataPoints;
+
+ delete[] _xAxisPoints;
+ _xAxisPoints = new double[_numPoints];
+
+ for(int i = 0; i < _nplots; i++) {
+ delete[] _dataPoints[i];
+ _dataPoints[i] = new double[_numPoints];
+ _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints);
+ }
+
+ setXaxis(0, numDataPoints);
+ _resetXAxisPoints();
+ }
+
+ for(int i = 0; i < _nplots; i++) {
+ memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double));
+ }
+ }
+}
+
+void TimeDomainDisplayPlot::_resetXAxisPoints()
+{
+ double delt = 1.0/_sampleRate;
+ for(long loc = 0; loc < _numPoints; loc++){
+ _xAxisPoints[loc] = loc*delt;
+ }
+ setAxisScale(QwtPlot::xBottom, 0, _numPoints*delt);
+
+ // Set up zoomer base for maximum unzoom x-axis
+ // and reset to maximum unzoom level
+ QwtDoubleRect zbase = _zoomer->zoomBase();
+ zbase.setLeft(0);
+ zbase.setRight(_numPoints*delt);
+ _zoomer->zoom(zbase);
+ _zoomer->setZoomBase(zbase);
+ _zoomer->zoom(0);
+}
+
+void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on)
+{
+ plotItem->setVisible(!on);
+}
+
+void
+TimeDomainDisplayPlot::SetSampleRate(double sr, double units,
+ const std::string &strunits)
+{
+ double newsr = sr/units;
+ if(newsr != _sampleRate) {
+ _sampleRate = sr/units;
+ _resetXAxisPoints();
+
+ // While we could change the displayed sigfigs based on the unit being
+ // displayed, I think it looks better by just setting it to 4 regardless.
+ //double display_units = ceil(log10(units)/2.0);
+ double display_units = 4;
+ setAxisTitle(QwtPlot::xBottom, QString("Time (%1)").arg(strunits.c_str()));
+ ((TimeDomainDisplayZoomer*)_zoomer)->SetTimePrecision(display_units);
+ ((TimeDomainDisplayZoomer*)_zoomer)->SetUnitType(strunits);
+ }
+}
+
+void
+TimeDomainDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p)
+{
+ QPointF point = p;
+ //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y());
+ emit plotPointSelected(point);
+}
+
+#endif /* TIME_DOMAIN_DISPLAY_PLOT_C */