1 #ifndef WATERFALL_3D_DISPLAY_PLOT_C
2 #define WATERFALL_3D_DISPLAY_PLOT_C
4 #include <Waterfall3DDisplayPlot.h>
6 #include <qwt3d_helper.h>
7 #include <qapplication.h>
9 Waterfall3DColorMap::Waterfall3DColorMap(): Qwt3D::Color(), QwtLinearColorMap(){
10 _interval.setInterval(0, 1.0);
14 Waterfall3DColorMap::~Waterfall3DColorMap(){
19 Waterfall3DColorMap::operator()(double, double, double z) const
21 return Qwt3D::RGBA(Qwt3D::Qt2GL(color(_interval, z)));
25 Waterfall3DColorMap::SetInterval(const double minValue, const double maxValue)
27 _interval.setInterval(minValue, maxValue);
31 Waterfall3DColorMap::createVector(Qwt3D::ColorVector& vec)
33 // Generate 100 interval values and then return those
34 Qwt3D::ColorVector colorVec;
35 for(unsigned int number = 0; number < 100; number++){
36 double value = (_interval.width() * (static_cast<double>(number) / 100.0)) + _interval.minValue();
37 colorVec.push_back(operator()(0,0,value));
44 const int Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR;
45 const int Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_WHITE_HOT;
46 const int Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_BLACK_HOT;
47 const int Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_INCANDESCENT;
48 const int Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED;
50 Waterfall3DDisplayPlot::Waterfall3DDisplayPlot(QWidget* parent):Qwt3D::SurfacePlot(parent)
53 _stopFrequency = 4000;
55 _createCoordinateSystemFlag = true;
61 _displayIntervalTime = (1.0/5.0); // 1/5 of a second between updates
63 timespec_reset(&_lastReplot);
65 _useCenterFrequencyFlag = false;
66 _centerFrequency = 0.0;
69 timespec_reset(&_dataTimestamp);
71 coordinates()->setAutoScale(false);
73 _waterfallData = new Waterfall3DData(_startFrequency, _stopFrequency, _numPoints, 200);
74 _waterfallData->assign(this);
75 _waterfallData->create();
77 _intensityColorMapType = -1;
78 SetIntensityColorMapType(INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR, Qt::white, Qt::black, true, true);
80 legend()->setScale(Qwt3D::LINEARSCALE);
81 legend()->setTitleString("Intensity");
86 Waterfall3DDisplayPlot::~Waterfall3DDisplayPlot()
88 delete _waterfallData;
92 Waterfall3DDisplayPlot::Init()
94 if(!_initialized && initializedGL()){
95 resize(parentWidget()->width(), parentWidget()->height());
97 // Attempting to prevent valgrind uninitialized variable errors in QwtPlot3d::Drawable class
98 glDisable(GL_POLYGON_OFFSET_FILL);
100 setPlotStyle(Qwt3D::FILLED);
102 setCoordinateStyle(Qwt3D::FRAME);
103 setFloorStyle(Qwt3D::FLOORDATA);
111 Waterfall3DDisplayPlot::Reset()
113 _waterfallData->ResizeData(_startFrequency, _stopFrequency, _numPoints);
114 _waterfallData->Reset();
117 setScale(1, static_cast<int>(((_stopFrequency - _startFrequency) / 200) ), 10);
120 _createCoordinateSystemFlag = true;
122 timespec_reset(&_dataTimestamp);
127 Waterfall3DDisplayPlot::SetFrequencyRange(const double constStartFreq,
128 const double constStopFreq,
129 const double constCenterFreq,
130 const bool useCenterFrequencyFlag,
132 const std::string &strunits)
134 double startFreq = constStartFreq / units;
135 double stopFreq = constStopFreq / units;
136 double centerFreq = constCenterFreq / units;
138 if(stopFreq > startFreq) {
139 _startFrequency = startFreq;
140 _stopFrequency = stopFreq;
142 _useCenterFrequencyFlag = useCenterFrequencyFlag;
143 _centerFrequency = centerFreq;
147 // Only replot if screen is visible
155 Waterfall3DDisplayPlot::loadFromData(double** data, unsigned int columns, unsigned int rows
156 ,double minx, double maxx, double miny, double maxy)
159 Qwt3D::GridData* gridPtr = (Qwt3D::GridData*)actualData_p;
161 gridPtr->setPeriodic(false,false);
162 gridPtr->setSize(columns,rows);
163 readIn(*gridPtr,data,columns,rows,minx,maxx,miny,maxy);
164 calcNormals(*gridPtr);
169 if( _createCoordinateSystemFlag ){
170 createCoordinateSystem();
172 for (unsigned i=0; i!=coordinates()->axes.size(); ++i)
174 coordinates()->axes[i].setMajors(5);
175 coordinates()->axes[i].setMinors(3);
178 coordinates()->axes[Qwt3D::Y1].setLabelString("Time");
179 coordinates()->axes[Qwt3D::Y2].setLabelString("Time");
180 coordinates()->axes[Qwt3D::Y3].setLabelString("Time");
181 coordinates()->axes[Qwt3D::Y4].setLabelString("Time");
182 coordinates()->axes[Qwt3D::Z1].setLabelString("Intensity (dB)");
183 coordinates()->axes[Qwt3D::Z2].setLabelString("Intensity (dB)");
184 coordinates()->axes[Qwt3D::Z3].setLabelString("Intensity (dB)");
185 coordinates()->axes[Qwt3D::Z4].setLabelString("Intensity (dB)");
187 coordinates()->axes[Qwt3D::X1].setLabelString((!_useCenterFrequencyFlag ? "Frequency (Hz)" : "Frequency (kHz)"));
188 coordinates()->axes[Qwt3D::X2].setLabelString((!_useCenterFrequencyFlag ? "Frequency (Hz)" : "Frequency (kHz)"));
189 coordinates()->axes[Qwt3D::X3].setLabelString((!_useCenterFrequencyFlag ? "Frequency (Hz)" : "Frequency (kHz)"));
190 coordinates()->axes[Qwt3D::X4].setLabelString((!_useCenterFrequencyFlag ? "Frequency (Hz)" : "Frequency (kHz)"));
192 // The QwtPlot3D Interface takes ownership of these items, so there is no need to delete them...
193 coordinates()->axes[Qwt3D::X1].setScale(new FrequencyScale(_useCenterFrequencyFlag, _centerFrequency));
194 coordinates()->axes[Qwt3D::X2].setScale(new FrequencyScale(_useCenterFrequencyFlag, _centerFrequency));
195 coordinates()->axes[Qwt3D::X3].setScale(new FrequencyScale(_useCenterFrequencyFlag, _centerFrequency));
196 coordinates()->axes[Qwt3D::X4].setScale(new FrequencyScale(_useCenterFrequencyFlag, _centerFrequency));
198 coordinates()->axes[Qwt3D::Y1].setScale(new TimeScale(this));
199 coordinates()->axes[Qwt3D::Y2].setScale(new TimeScale(this));
200 coordinates()->axes[Qwt3D::Y3].setScale(new TimeScale(this));
201 coordinates()->axes[Qwt3D::Y4].setScale(new TimeScale(this));
203 coordinates()->axes[Qwt3D::Z1].setScale(new IntensityScale(_waterfallData->GetFloorValue()));
204 coordinates()->axes[Qwt3D::Z2].setScale(new IntensityScale(_waterfallData->GetFloorValue()));
205 coordinates()->axes[Qwt3D::Z3].setScale(new IntensityScale(_waterfallData->GetFloorValue()));
206 coordinates()->axes[Qwt3D::Z4].setScale(new IntensityScale(_waterfallData->GetFloorValue()));
208 _createCoordinateSystemFlag = false;
215 Waterfall3DDisplayPlot::GetStartFrequency() const
217 return _startFrequency;
221 Waterfall3DDisplayPlot::GetStopFrequency() const
223 return _stopFrequency;
227 Waterfall3DDisplayPlot::PlotNewData(const double* dataPoints,
228 const int64_t numDataPoints,
229 const double timePerFFT,
230 const timespec timestamp,
231 const int droppedFrames)
233 if(numDataPoints > 0){
234 if(numDataPoints != _numPoints){
235 _numPoints = numDataPoints;
243 _createCoordinateSystemFlag = true;
245 _lastReplot = get_highres_clock();
248 _dataTimestamp = timestamp;
249 _timePerFFT = timePerFFT;
251 _waterfallData->addFFTData(dataPoints, numDataPoints, droppedFrames);
252 _waterfallData->IncrementNumLinesToUpdate();
255 // Allow at least a 50% duty cycle
256 if(diff_timespec(get_highres_clock(), _lastReplot) > _displayIntervalTime){
257 // Only update when window is visible
262 _lastReplot = get_highres_clock();
267 Waterfall3DDisplayPlot::SetIntensityRange(const double minIntensity,
268 const double maxIntensity)
270 _waterfallData->SetFloorValue(minIntensity);
271 _waterfallData->setMinZ(0);
272 _waterfallData->setMaxZ(maxIntensity-minIntensity);
274 _createCoordinateSystemFlag = true;
276 emit UpdatedLowerIntensityLevel(minIntensity);
277 emit UpdatedUpperIntensityLevel(maxIntensity);
279 SetIntensityColorMapType(_intensityColorMapType,
280 _userDefinedLowIntensityColor,
281 _userDefinedLowIntensityColor, true);
285 Waterfall3DDisplayPlot::replot()
291 const timespec startTime = get_highres_clock();
293 _waterfallData->create();
295 legend()->setMajors(4);
296 legend()->setMinors(5);
298 coordinates()->axes[Qwt3D::Z1].limits(start,stop);
299 legend()->setLimits( _waterfallData->GetFloorValue(), _waterfallData->GetFloorValue() + stop - start );
301 coordinates()->axes[Qwt3D::X1].limits(start,stop);
303 showColorLegend(true);
307 double differenceTime = (diff_timespec(get_highres_clock(), startTime));
309 // Require at least a 20% duty cycle
310 differenceTime *= 4.0;
311 if(differenceTime > (1.0/5.0)){
312 _displayIntervalTime = differenceTime;
318 Waterfall3DDisplayPlot::resizeSlot( QSize *s )
320 resize(s->width(), s->height());
324 Waterfall3DDisplayPlot::GetIntensityColorMapType() const
326 return _intensityColorMapType;
330 Waterfall3DDisplayPlot::SetIntensityColorMapType(const int newType,
331 const QColor lowColor,
332 const QColor highColor,
333 const bool forceFlag,
334 const bool noReplotFlag)
336 if(((_intensityColorMapType != newType) || forceFlag) ||
337 ((newType == INTENSITY_COLOR_MAP_TYPE_USER_DEFINED) &&
338 (lowColor.isValid() && highColor.isValid()))){
340 Waterfall3DColorMap* colorMap = new Waterfall3DColorMap();
341 colorMap->SetInterval(_waterfallData->minZ(), _waterfallData->maxZ());
344 case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR:{
345 _intensityColorMapType = newType;
346 colorMap->setColorInterval(Qt::darkCyan, Qt::white);
347 colorMap->addColorStop(0.25, Qt::cyan);
348 colorMap->addColorStop(0.5, Qt::yellow);
349 colorMap->addColorStop(0.75, Qt::red);
350 setBackgroundColor(Qwt3D::Qt2GL(Qt::gray));
353 case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT:{
354 _intensityColorMapType = newType;
355 colorMap->setColorInterval(Qt::black, Qt::white);
356 setBackgroundColor(Qwt3D::Qt2GL(Qt::blue));
359 case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT:{
360 _intensityColorMapType = newType;
361 colorMap->setColorInterval(Qt::white, Qt::black);
362 setBackgroundColor(Qwt3D::Qt2GL(Qt::blue));
365 case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT:{
366 _intensityColorMapType = newType;
367 colorMap->setColorInterval(Qt::black, Qt::white);
368 colorMap->addColorStop(0.5, Qt::darkRed);
369 setBackgroundColor(Qwt3D::Qt2GL(Qt::gray));
372 case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED:{
373 _userDefinedLowIntensityColor = lowColor;
374 _userDefinedHighIntensityColor = highColor;
375 _intensityColorMapType = newType;
376 colorMap->setColorInterval(_userDefinedLowIntensityColor, _userDefinedHighIntensityColor);
377 setBackgroundColor(Qwt3D::Qt2GL(Qt::white));
381 colorMap->setColorInterval(Qt::black, Qt::white);
385 // Qwt3D takes over destruction of this object...
386 setDataColor(colorMap);
392 // Update the last replot timer
393 _lastReplot = get_highres_clock();
399 Waterfall3DDisplayPlot::GetUserDefinedLowIntensityColor() const
401 return _userDefinedLowIntensityColor;
405 Waterfall3DDisplayPlot::GetUserDefinedHighIntensityColor() const
407 return _userDefinedHighIntensityColor;
410 #endif /* WATERFALL_3D_DISPLAY_PLOT_C */