Imported Upstream version 3.2.2
[debian/gnuradio] / gr-qtgui / src / lib / waterfallGlobalData.cc
1 #ifndef WATERFALL_GLOBAL_DATA_CPP
2 #define WATERFALL_GLOBAL_DATA_CPP
3
4 #include <waterfallGlobalData.h>
5
6 #include <Waterfall3DDisplayPlot.h>
7
8 WaterfallData::WaterfallData(const double minimumFrequency, const double maximumFrequency, const uint64_t fftPoints, const unsigned int historyExtent):
9   QwtRasterData(QwtDoubleRect(minimumFrequency /* X START */,  0 /* Y START */, maximumFrequency - minimumFrequency /* WIDTH */,  static_cast<double>(historyExtent)/* HEIGHT */))
10
11 {
12   _intensityRange = QwtDoubleInterval(-200.0, 0.0);
13   
14   _fftPoints = fftPoints;
15   _historyLength = historyExtent;
16
17   _spectrumData = new double[_fftPoints * _historyLength];
18
19   Reset();
20 }
21
22 WaterfallData::~WaterfallData(){
23   delete[] _spectrumData;
24 }
25
26 void WaterfallData::Reset(){
27   memset(_spectrumData, 0x0, _fftPoints*_historyLength*sizeof(double));
28
29   _numLinesToUpdate = -1;
30 }
31
32 void WaterfallData::Copy(const WaterfallData* rhs){
33   if((_fftPoints != rhs->GetNumFFTPoints()) ||
34      (boundingRect() != rhs->boundingRect()) ){
35     _fftPoints = rhs->GetNumFFTPoints();
36     setBoundingRect(rhs->boundingRect());
37     delete[] _spectrumData;
38     _spectrumData = new double[_fftPoints * _historyLength];
39   }
40   Reset();
41   SetSpectrumDataBuffer(rhs->GetSpectrumDataBuffer());
42   SetNumLinesToUpdate(rhs->GetNumLinesToUpdate());
43   setRange(rhs->range());
44 }
45
46 void WaterfallData::ResizeData(const double startFreq, const double stopFreq, const uint64_t fftPoints){
47   if((fftPoints != GetNumFFTPoints()) ||
48      (boundingRect().width() != (stopFreq - startFreq)) ||
49      (boundingRect().left() != startFreq)){
50
51     setBoundingRect(QwtDoubleRect(startFreq, 0, stopFreq-startFreq, boundingRect().height()));
52     _fftPoints = fftPoints;
53     delete[] _spectrumData;
54     _spectrumData = new double[_fftPoints * _historyLength];
55   }
56    
57   Reset();
58 }
59
60 QwtRasterData *WaterfallData::copy() const{
61   WaterfallData* returnData =  new WaterfallData(boundingRect().left(), boundingRect().right(), _fftPoints, _historyLength);
62   returnData->Copy(this);
63   return returnData;
64 }
65
66 QwtDoubleInterval WaterfallData::range() const{
67   return _intensityRange;
68 }
69
70 void WaterfallData::setRange(const QwtDoubleInterval& newRange){
71   _intensityRange = newRange;
72 }
73
74 double WaterfallData::value(double x, double y) const{
75   double returnValue = 0.0;
76
77   const unsigned int intY = static_cast<unsigned int>((1.0 - (y/boundingRect().height())) * 
78                                                       static_cast<double>(_historyLength - 1));
79   const unsigned int intX = static_cast<unsigned int>((((x - boundingRect().left()) / boundingRect().width()) * 
80                                                        static_cast<double>(_fftPoints-1)) + 0.5);
81
82   const int location = (intY * _fftPoints) + intX;
83   if((location > -1) && (location < static_cast<int64_t>(_fftPoints * _historyLength))){
84     returnValue = _spectrumData[location];
85   }
86
87   return returnValue;
88 }
89
90 uint64_t WaterfallData::GetNumFFTPoints()const{
91   return _fftPoints;
92 }
93
94 void WaterfallData::addFFTData(const double* fftData, const uint64_t fftDataSize, const int droppedFrames){
95   if(fftDataSize == _fftPoints){
96     int64_t heightOffset = _historyLength - 1 - droppedFrames;
97     uint64_t drawingDroppedFrames = droppedFrames;
98
99     // Any valid data rolled off the display so just fill in zeros and write new data
100     if(heightOffset < 0){
101       heightOffset = 0;
102       drawingDroppedFrames = static_cast<uint64_t>(_historyLength-1);
103     }
104     
105     // Copy the old data over if any available
106     if(heightOffset > 0){
107       memmove( _spectrumData, &_spectrumData[(drawingDroppedFrames+1) * _fftPoints], heightOffset * _fftPoints * sizeof(double)) ;
108     }
109
110     if(drawingDroppedFrames > 0){
111       // Fill in zeros data for dropped data
112       memset(&_spectrumData[heightOffset * _fftPoints], 0x00, static_cast<int64_t>(drawingDroppedFrames) * _fftPoints * sizeof(double));
113     }
114
115     // add the new buffer
116     memcpy(&_spectrumData[(_historyLength - 1) * _fftPoints], fftData, _fftPoints*sizeof(double));
117
118   }
119 }
120
121 double* WaterfallData::GetSpectrumDataBuffer()const{
122   return _spectrumData;
123 }
124
125 void WaterfallData::SetSpectrumDataBuffer(const double* newData){
126   memcpy(_spectrumData, newData, _fftPoints * _historyLength * sizeof(double));
127 }
128
129 int WaterfallData::GetNumLinesToUpdate()const{
130   return _numLinesToUpdate;
131 }
132
133 void WaterfallData::SetNumLinesToUpdate(const int newNum){
134   _numLinesToUpdate = newNum;
135 }
136
137 void WaterfallData::IncrementNumLinesToUpdate(){
138   _numLinesToUpdate++;
139 }
140
141 Waterfall3DData::Waterfall3DData(const double minimumFrequency, const double maximumFrequency, const uint64_t fftPoints, const unsigned int historyExtent):
142   WaterfallData(minimumFrequency,  maximumFrequency, fftPoints, historyExtent), Qwt3D::Function(){
143
144   _floorValue = 0.0;
145   setMinZ(0.0);
146   setMaxZ(200.0);
147
148   // Create the dummy mesh data until _ResizeMesh is called
149   data = new double*[1];
150   data[0] = new double[1];
151   Qwt3D::Function::setMesh(1,1);
152
153   _ResizeMesh();
154 }
155
156 Waterfall3DData::~Waterfall3DData(){
157   for ( unsigned i = 0; i < umesh_p; i++){
158     delete[] data[i];
159   }
160   delete[] data;
161
162 }
163
164 void Waterfall3DData::ResizeData(const double startFreq, const double stopFreq, const uint64_t fftPoints){
165   if((fftPoints != GetNumFFTPoints()) ||
166      (boundingRect().width() != (stopFreq - startFreq)) ||
167      (boundingRect().left() != startFreq)){
168     WaterfallData::ResizeData(startFreq, stopFreq, fftPoints);
169     _ResizeMesh();
170   }
171    
172   Reset();
173 }
174
175 bool Waterfall3DData::create()
176 {
177   if ((umesh_p<=2) || (vmesh_p<=2) || !plotwidget_p)
178     return false;
179
180   // Almost the same as the old create, except that here we store our own data buffer in the class rather than re-creating it each time...
181
182   unsigned i,j;
183
184   /* get the data */
185   double dx = (maxu_p - minu_p) / (umesh_p - 1);
186   double dy = (maxv_p - minv_p) / (vmesh_p - 1);
187   
188   for (i = 0; i < umesh_p; ++i) 
189     {
190       for (j = 0; j < vmesh_p; ++j) 
191         {
192           data[i][j] = operator()(minu_p + i*dx, minv_p + j*dy);
193           
194           if (data[i][j] > range_p.maxVertex.z)
195             data[i][j] = range_p.maxVertex.z;
196           else if (data[i][j] < range_p.minVertex.z)
197             data[i][j] = range_p.minVertex.z;
198         }
199     }
200   
201   Q_ASSERT(plotwidget_p);
202   if (!plotwidget_p)
203     {
204       fprintf(stderr,"Function: no valid Plot3D Widget assigned");
205     }
206   else
207     {
208       ((Waterfall3DDisplayPlot*)plotwidget_p)->loadFromData(data, umesh_p, vmesh_p, minu_p, maxu_p, minv_p, maxv_p);
209     }
210   
211   return true;
212 }
213
214 double Waterfall3DData::operator()(double x, double y){
215   return value(x,y) - _floorValue;
216 }
217
218 double Waterfall3DData::GetFloorValue()const{
219   return _floorValue;
220 }
221
222 void Waterfall3DData::SetFloorValue(const double newValue){
223   _floorValue = newValue;
224 }
225
226 double Waterfall3DData::minZ()const{
227   return range_p.minVertex.z;
228 }
229
230 double Waterfall3DData::maxZ()const{
231   return range_p.maxVertex.z;
232 }
233
234 void Waterfall3DData::setMesh(unsigned int, unsigned int){
235   // Do Nothing
236   printf("Should Not Reach this Function\n");
237 }
238
239 void Waterfall3DData::_ResizeMesh(){
240   // Clear out the old mesh
241   for ( unsigned i = 0; i < umesh_p; i++){
242     delete[] data[i];
243   }
244   delete[] data;
245   
246   Qwt3D::Function::setMesh(static_cast<int>(boundingRect().width()/20.0), _historyLength);
247   setDomain( boundingRect().left(), static_cast<int>(boundingRect().right()), 0, _historyLength);
248
249   /* allocate some space for the mesh */
250   unsigned i;
251   data         = new double* [umesh_p] ;
252   for ( i = 0; i < umesh_p; i++) 
253     {
254       data[i]         = new double [vmesh_p];
255     }
256 }
257
258 #endif /* WATERFALL_GLOBAL_DATA_CPP */