Fixes a lot of warnings by cleaning up namespace issues.
[debian/gnuradio] / gr-qtgui / src / lib / FrequencyDisplayPlot.cc
1 #ifndef FREQUENCY_DISPLAY_PLOT_C
2 #define FREQUENCY_DISPLAY_PLOT_C
3
4 #include <FrequencyDisplayPlot.h>
5
6 #include <qwt_scale_draw.h>
7
8 class FreqPrecisionClass
9 {
10 public:
11   FreqPrecisionClass(const int freqPrecision)
12   {
13     _frequencyPrecision = freqPrecision;
14   }
15
16   virtual ~FreqPrecisionClass()
17   {
18   }
19
20   virtual unsigned int GetFrequencyPrecision() const
21   {
22     return _frequencyPrecision;
23   }
24
25   virtual void SetFrequencyPrecision(const unsigned int newPrecision)
26   {
27     _frequencyPrecision = newPrecision;
28   }
29 protected:
30   unsigned int _frequencyPrecision;
31
32 private:
33
34 };
35
36 class FreqDisplayScaleDraw: public QwtScaleDraw, public FreqPrecisionClass
37 {
38 public:
39   FreqDisplayScaleDraw(const unsigned int precision)
40     : QwtScaleDraw(), FreqPrecisionClass(precision)
41   {
42   }
43
44   virtual ~FreqDisplayScaleDraw() 
45   {
46   }
47
48   virtual QwtText label(double value) const
49   {
50     return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision());
51   }
52
53 protected:
54
55 private:
56
57 };
58
59 class FreqDisplayZoomer: public QwtPlotZoomer, public FreqPrecisionClass
60 {
61 public:
62   FreqDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision)
63     : QwtPlotZoomer(canvas),FreqPrecisionClass(freqPrecision)
64   {
65     setTrackerMode(QwtPicker::AlwaysOn);
66   }
67
68   virtual ~FreqDisplayZoomer(){
69
70   }
71   
72   virtual void updateTrackerText(){
73     updateDisplay();
74   }
75
76   void SetUnitType(const std::string &type)
77   {
78     _unitType = type;
79   }
80
81 protected:
82   using QwtPlotZoomer::trackerText;
83   virtual QwtText trackerText( const QwtDoublePoint& p ) const
84   {
85     QwtText t(QString("%1 %2, %3 dB").
86               arg(p.x(), 0, 'f', GetFrequencyPrecision()).
87               arg(_unitType.c_str()).arg(p.y(), 0, 'f', 2));
88     return t;
89   }
90
91 private:
92   std::string _unitType;
93 };
94
95 FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
96   : QwtPlot(parent)
97 {
98   _startFrequency = 0;
99   _stopFrequency = 4000;
100   
101   timespec_reset(&_lastReplot);
102
103   resize(parent->width(), parent->height());
104   
105   _useCenterFrequencyFlag = false;
106
107   _numPoints = 1024;
108   _dataPoints = new double[_numPoints];
109   _minFFTPoints = new double[_numPoints];
110   _maxFFTPoints = new double[_numPoints];
111   _xAxisPoints = new double[_numPoints];
112
113   // Disable polygon clipping
114   QwtPainter::setDeviceClipping(false);
115   
116   // We don't need the cache here
117   canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
118   canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
119   
120   QPalette palette;
121   palette.setColor(canvas()->backgroundRole(), QColor("white"));
122   canvas()->setPalette(palette);  
123
124   setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
125   setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0));
126
127   _minYAxis = -120;
128   _maxYAxis = 10;
129   setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
130   setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis);
131   setAxisTitle(QwtPlot::yLeft, "Power (dB)");
132
133   // Automatically deleted when parent is deleted
134   _fft_plot_curve = new QwtPlotCurve("Power Spectrum");
135   _fft_plot_curve->attach(this);
136   _fft_plot_curve->setPen(QPen(Qt::blue));
137   _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints);
138
139   _min_fft_plot_curve = new QwtPlotCurve("Minimum Power");
140   _min_fft_plot_curve->attach(this);
141   _min_fft_plot_curve->setPen(QPen(Qt::magenta));
142   _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
143   _min_fft_plot_curve->setVisible(false);
144
145   _max_fft_plot_curve = new QwtPlotCurve("Maximum Power");
146   _max_fft_plot_curve->attach(this);
147   _max_fft_plot_curve->setPen(QPen(Qt::darkYellow));
148   _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
149   _max_fft_plot_curve->setVisible(false);
150
151   _lower_intensity_marker = new QwtPlotMarker();
152   _lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
153   _lower_intensity_marker->setLinePen(QPen(Qt::cyan));
154   _lower_intensity_marker->attach(this);
155
156   _upper_intensity_marker = new QwtPlotMarker();
157   _upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
158   _upper_intensity_marker->setLinePen(QPen(Qt::green, 0, Qt::DotLine));
159   _upper_intensity_marker->attach(this);
160
161   memset(_dataPoints, 0x0, _numPoints*sizeof(double));
162   memset(_xAxisPoints, 0x0, _numPoints*sizeof(double));
163
164   for(int64_t number = 0; number < _numPoints; number++){
165     _minFFTPoints[number] = 200.0;
166     _maxFFTPoints[number] = -280.0;
167   }
168
169   // set up peak marker
170   QwtSymbol symbol;
171
172   _markerPeakAmplitude = new QwtPlotMarker();
173   _markerPeakAmplitude->setLinePen(QPen(Qt::yellow));
174   symbol.setStyle(QwtSymbol::Diamond);
175   symbol.setSize(8);
176   symbol.setPen(QPen(Qt::yellow));
177   symbol.setBrush(QBrush(Qt::yellow));
178   _markerPeakAmplitude->setSymbol(symbol);
179   _markerPeakAmplitude->attach(this);
180
181   _markerNoiseFloorAmplitude = new QwtPlotMarker();
182   _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine);
183   _markerNoiseFloorAmplitude->setLinePen(QPen(Qt::darkRed, 0, Qt::DotLine));
184   _markerNoiseFloorAmplitude->attach(this);
185
186   _peakFrequency = 0;
187   _peakAmplitude = -HUGE_VAL;
188
189   _noiseFloorAmplitude = -HUGE_VAL;
190
191   replot();
192
193   _zoomer = new FreqDisplayZoomer(canvas(), 0);
194 #if QT_VERSION < 0x040000
195   _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
196                           Qt::RightButton, Qt::ControlModifier);
197 #else
198   _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
199                           Qt::RightButton, Qt::ControlModifier);
200 #endif
201   _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
202                           Qt::RightButton);
203
204   _panner = new QwtPlotPanner(canvas());
205   _panner->setAxisEnabled(QwtPlot::yRight, false);
206   _panner->setMouseButton(Qt::MidButton);
207
208   // Avoid jumping when labels with more/less digits
209   // appear/disappear when scrolling vertically
210
211   const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
212   QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
213   sd->setMinimumExtent( fm.width("100.00") );
214
215   const QColor c(Qt::darkRed);
216   _zoomer->setRubberBandPen(c);
217   _zoomer->setTrackerPen(c);
218
219   // Do this after the zoomer has been built
220   _resetXAxisPoints();
221 }
222
223 FrequencyDisplayPlot::~FrequencyDisplayPlot()
224 {
225   delete[] _dataPoints;
226   delete[] _maxFFTPoints;
227   delete[] _minFFTPoints;
228   delete[] _xAxisPoints;
229
230   // _fft_plot_curves deleted when parent deleted
231   // _zoomer and _panner deleted when parent deleted
232 }
233
234 void
235 FrequencyDisplayPlot::set_yaxis(double min, double max)
236 {
237   // Get the new max/min values for the plot
238   _minYAxis = min;
239   _maxYAxis = max;
240
241   // Set the axis max/min to the new values
242   setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis);
243
244   // Reset the base zoom level to the new axis scale set here
245   _zoomer->setZoomBase();
246 }
247
248 void
249 FrequencyDisplayPlot::SetFrequencyRange(const double constStartFreq,
250                                         const double constStopFreq,
251                                         const double constCenterFreq,
252                                         const bool useCenterFrequencyFlag,
253                                         const double units, const std::string &strunits)
254 {
255   double startFreq = constStartFreq / units;
256   double stopFreq = constStopFreq / units;
257   double centerFreq = constCenterFreq / units;
258
259   _useCenterFrequencyFlag = useCenterFrequencyFlag;
260
261   if(_useCenterFrequencyFlag){
262     startFreq = (startFreq + centerFreq);
263     stopFreq = (stopFreq + centerFreq);
264   }
265
266   bool reset = false;
267   if((startFreq != _startFrequency) || (stopFreq != _stopFrequency))
268     reset = true;
269
270   if(stopFreq > startFreq) {
271     _startFrequency = startFreq;
272     _stopFrequency = stopFreq;
273     
274     if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)){
275       double display_units = ceil(log10(units)/2.0);
276       setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(display_units));
277       setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str()));
278
279       if(reset)
280         _resetXAxisPoints();
281       
282       ((FreqDisplayZoomer*)_zoomer)->SetFrequencyPrecision(display_units);
283       ((FreqDisplayZoomer*)_zoomer)->SetUnitType(strunits);
284     }
285   }
286 }
287
288
289 double
290 FrequencyDisplayPlot::GetStartFrequency() const
291 {
292   return _startFrequency;
293 }
294
295 double
296 FrequencyDisplayPlot::GetStopFrequency() const
297 {
298   return _stopFrequency;
299 }
300
301 void
302 FrequencyDisplayPlot::replot()
303 {
304   _markerNoiseFloorAmplitude->setYValue(_noiseFloorAmplitude);
305   
306   // Make sure to take into account the start frequency
307   if(_useCenterFrequencyFlag){
308     _markerPeakAmplitude->setXValue((_peakFrequency/1000.0) + _startFrequency);
309   }
310   else{
311     _markerPeakAmplitude->setXValue(_peakFrequency + _startFrequency);
312   }
313   _markerPeakAmplitude->setYValue(_peakAmplitude);
314   
315   QwtPlot::replot();
316 }
317  
318 void
319 FrequencyDisplayPlot::resizeSlot( QSize *s )
320 {
321   resize(s->width(), s->height());
322 }
323
324 void
325 FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDataPoints,
326                                   const double noiseFloorAmplitude, const double peakFrequency,
327                                   const double peakAmplitude, const double timeInterval)
328 {
329   // Only update plot if there is data and if the time interval has elapsed
330   if((numDataPoints > 0) && 
331      (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) {
332     
333     if(numDataPoints != _numPoints) {
334       _numPoints = numDataPoints;
335       
336       delete[] _dataPoints;
337       delete[] _minFFTPoints;
338       delete[] _maxFFTPoints;
339       delete[] _xAxisPoints;
340       _dataPoints = new double[_numPoints];
341       _xAxisPoints = new double[_numPoints];
342       _minFFTPoints = new double[_numPoints];
343       _maxFFTPoints = new double[_numPoints];
344       
345       _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints);
346       _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
347       _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
348       
349       _resetXAxisPoints();
350       ClearMaxData();
351       ClearMinData();
352     }
353     
354     memcpy(_dataPoints, dataPoints, numDataPoints*sizeof(double));
355     for(int64_t point = 0; point < numDataPoints; point++){
356       if(dataPoints[point] < _minFFTPoints[point]){
357         _minFFTPoints[point] = dataPoints[point];
358       }
359       if(dataPoints[point] > _maxFFTPoints[point]){
360         _maxFFTPoints[point] = dataPoints[point];
361       }
362     }
363
364     _noiseFloorAmplitude = noiseFloorAmplitude;
365     _peakFrequency = peakFrequency;
366     _peakAmplitude = peakAmplitude;
367
368     SetUpperIntensityLevel(_peakAmplitude);
369
370     replot();
371     
372     _lastReplot = get_highres_clock();
373   }
374 }
375
376 void
377 FrequencyDisplayPlot::ClearMaxData()
378 {
379   for(int64_t number = 0; number < _numPoints; number++){
380     _maxFFTPoints[number] = _minYAxis;
381   }
382 }
383
384 void
385 FrequencyDisplayPlot::ClearMinData()
386 {
387   for(int64_t number = 0; number < _numPoints; number++){
388     _minFFTPoints[number] = _maxYAxis;
389   }
390 }
391
392 void
393 FrequencyDisplayPlot::SetMaxFFTVisible(const bool visibleFlag)
394 {
395   _max_fft_plot_curve->setVisible(visibleFlag);
396 }
397
398 void
399 FrequencyDisplayPlot::SetMinFFTVisible(const bool visibleFlag)
400 {
401   _min_fft_plot_curve->setVisible(visibleFlag);
402 }
403
404 void
405 FrequencyDisplayPlot::_resetXAxisPoints()
406 {
407   double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast<double>(_numPoints);
408   double freqValue = _startFrequency;
409   for(int64_t loc = 0; loc < _numPoints; loc++){
410     _xAxisPoints[loc] = freqValue;
411     freqValue += fft_bin_size;
412   }
413
414   setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency);
415
416   // Set up zoomer base for maximum unzoom x-axis
417   // and reset to maximum unzoom level
418   QwtDoubleRect zbase = _zoomer->zoomBase();
419   zbase.setLeft(_startFrequency);
420   zbase.setRight(_stopFrequency);
421   _zoomer->zoom(zbase);
422   _zoomer->setZoomBase(zbase);
423   _zoomer->zoom(0);
424 }
425
426 void
427 FrequencyDisplayPlot::SetLowerIntensityLevel(const double lowerIntensityLevel)
428 {
429   _lower_intensity_marker->setYValue( lowerIntensityLevel );
430 }
431
432 void
433 FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel)
434 {
435   _upper_intensity_marker->setYValue( upperIntensityLevel );
436 }
437
438
439 #endif /* FREQUENCY_DISPLAY_PLOT_C */