1 #ifndef WATERFALL_GLOBAL_DATA_CPP
2 #define WATERFALL_GLOBAL_DATA_CPP
4 #include <waterfallGlobalData.h>
6 #include <Waterfall3DDisplayPlot.h>
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 */))
12 _intensityRange = QwtDoubleInterval(-200.0, 0.0);
14 _fftPoints = fftPoints;
15 _historyLength = historyExtent;
17 _spectrumData = new double[_fftPoints * _historyLength];
22 WaterfallData::~WaterfallData(){
23 delete[] _spectrumData;
26 void WaterfallData::Reset(){
27 memset(_spectrumData, 0x0, _fftPoints*_historyLength*sizeof(double));
29 _numLinesToUpdate = -1;
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];
41 SetSpectrumDataBuffer(rhs->GetSpectrumDataBuffer());
42 SetNumLinesToUpdate(rhs->GetNumLinesToUpdate());
43 setRange(rhs->range());
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)){
51 setBoundingRect(QwtDoubleRect(startFreq, 0, stopFreq-startFreq, boundingRect().height()));
52 _fftPoints = fftPoints;
53 delete[] _spectrumData;
54 _spectrumData = new double[_fftPoints * _historyLength];
60 QwtRasterData *WaterfallData::copy() const{
61 WaterfallData* returnData = new WaterfallData(boundingRect().left(), boundingRect().right(), _fftPoints, _historyLength);
62 returnData->Copy(this);
66 QwtDoubleInterval WaterfallData::range() const{
67 return _intensityRange;
70 void WaterfallData::setRange(const QwtDoubleInterval& newRange){
71 _intensityRange = newRange;
74 double WaterfallData::value(double x, double y) const{
75 double returnValue = 0.0;
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);
82 const int location = (intY * _fftPoints) + intX;
83 if((location > -1) && (location < static_cast<int64_t>(_fftPoints * _historyLength))){
84 returnValue = _spectrumData[location];
90 uint64_t WaterfallData::GetNumFFTPoints()const{
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;
99 // Any valid data rolled off the display so just fill in zeros and write new data
100 if(heightOffset < 0){
102 drawingDroppedFrames = static_cast<uint64_t>(_historyLength-1);
105 // Copy the old data over if any available
106 if(heightOffset > 0){
107 memmove( _spectrumData, &_spectrumData[(drawingDroppedFrames+1) * _fftPoints], heightOffset * _fftPoints * sizeof(double)) ;
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));
115 // add the new buffer
116 memcpy(&_spectrumData[(_historyLength - 1) * _fftPoints], fftData, _fftPoints*sizeof(double));
121 double* WaterfallData::GetSpectrumDataBuffer()const{
122 return _spectrumData;
125 void WaterfallData::SetSpectrumDataBuffer(const double* newData){
126 memcpy(_spectrumData, newData, _fftPoints * _historyLength * sizeof(double));
129 int WaterfallData::GetNumLinesToUpdate()const{
130 return _numLinesToUpdate;
133 void WaterfallData::SetNumLinesToUpdate(const int newNum){
134 _numLinesToUpdate = newNum;
137 void WaterfallData::IncrementNumLinesToUpdate(){
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(){
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);
156 Waterfall3DData::~Waterfall3DData(){
157 for ( unsigned i = 0; i < umesh_p; i++){
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);
175 bool Waterfall3DData::create()
177 if ((umesh_p<=2) || (vmesh_p<=2) || !plotwidget_p)
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...
185 double dx = (maxu_p - minu_p) / (umesh_p - 1);
186 double dy = (maxv_p - minv_p) / (vmesh_p - 1);
188 for (i = 0; i < umesh_p; ++i)
190 for (j = 0; j < vmesh_p; ++j)
192 data[i][j] = operator()(minu_p + i*dx, minv_p + j*dy);
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;
201 Q_ASSERT(plotwidget_p);
204 fprintf(stderr,"Function: no valid Plot3D Widget assigned");
208 ((Waterfall3DDisplayPlot*)plotwidget_p)->loadFromData(data, umesh_p, vmesh_p, minu_p, maxu_p, minv_p, maxv_p);
214 double Waterfall3DData::operator()(double x, double y){
215 return value(x,y) - _floorValue;
218 double Waterfall3DData::GetFloorValue()const{
222 void Waterfall3DData::SetFloorValue(const double newValue){
223 _floorValue = newValue;
226 double Waterfall3DData::minZ()const{
227 return range_p.minVertex.z;
230 double Waterfall3DData::maxZ()const{
231 return range_p.maxVertex.z;
234 void Waterfall3DData::setMesh(unsigned int, unsigned int){
236 printf("Should Not Reach this Function\n");
239 void Waterfall3DData::_ResizeMesh(){
240 // Clear out the old mesh
241 for ( unsigned i = 0; i < umesh_p; i++){
246 Qwt3D::Function::setMesh(static_cast<int>(boundingRect().width()/20.0), _historyLength);
247 setDomain( boundingRect().left(), static_cast<int>(boundingRect().right()), 0, _historyLength);
249 /* allocate some space for the mesh */
251 data = new double* [umesh_p] ;
252 for ( i = 0; i < umesh_p; i++)
254 data[i] = new double [vmesh_p];
258 #endif /* WATERFALL_GLOBAL_DATA_CPP */