00001 /*************************************************************************** 00002 * SpikeStream Application * 00003 * Copyright (C) 2007 by David Gamez * 00004 * david@davidgamez.eu * 00005 * Version 0.1 * 00006 * * 00007 * This program is free software; you can redistribute it and/or modify * 00008 * it under the terms of the GNU General Public License as published by * 00009 * the Free Software Foundation; either version 2 of the License, or * 00010 * (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License * 00018 * along with this program; if not, write to the * 00019 * Free Software Foundation, Inc., * 00020 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00021 ***************************************************************************/ 00022 00023 //SpikeStream includes 00024 #include "MonitorDataset.h" 00025 #include "Debug.h" 00026 00027 //Other includes 00028 #include <iostream> 00029 using namespace std; 00030 00031 00032 /*! Standard constructor that initialises everything. */ 00033 MonitorDataset::MonitorDataset(int bufSize, double rangeL, double rangeH) : QwtData(){ 00034 /* Initialise the data used in this class. These are all pointers so need to be 00035 allocated on the heap. */ 00036 //Dataset starts inserting at zero and starts reading at zero 00037 insertPos = new int; 00038 *insertPos = 0; 00039 00040 //Store buffer size 00041 bufferSize = new int; 00042 *bufferSize = bufSize; 00043 00044 //Initialise parameters that will be used to learn the range once the buffer is full 00045 xIncrement = new double; 00046 *xIncrement = 0.0; 00047 xOld =new double; 00048 *xOld = 0.0; 00049 yMin = new double; 00050 *yMin = 0.0; 00051 yMax = new double; 00052 *yMax = 0.0; 00053 bufferFull = new bool; 00054 *bufferFull = false; 00055 00056 //Initialise bounds rectangle to the default range 00057 //QwtDoubleRect(double left, double top, double width, double height); 00058 bndRect = new QwtDoubleRect(0.0, rangeL, *bufferSize, rangeH - rangeL); 00059 00060 //Create arrays to hold the x and y values 00061 xArray = new double[*bufferSize]; 00062 yArray = new double[*bufferSize]; 00063 00064 //Initialise arrays to zero 00065 for(int i=0; i<*bufferSize; ++i){ 00066 xArray[i] = 0.0; 00067 yArray[i] = 0.0; 00068 } 00069 } 00070 00071 00072 /*! Constructor that does not initialise - used by copy(). */ 00073 MonitorDataset::MonitorDataset(){ 00074 } 00075 00076 00077 /*! Destructor. This does not do any cleaning up because a reference copy is made of this 00078 class and so cleaning up might entail this destructor being called twice. Need to 00079 call cleanUp() explicitly to delete the data structures. */ 00080 MonitorDataset::~MonitorDataset(){ 00081 #ifdef MEMORY_DEBUG 00082 cout<<"DESTROYING MONITOR DATASET"<<endl; 00083 #endif//MEMORY_DEBUG 00084 } 00085 00086 00087 //----------------------------------------------------------------------- 00088 //--------------------------- PUBLIC METHODS ---------------------------- 00089 //----------------------------------------------------------------------- 00090 00091 /*! Adds a point to the dataset. This is added at insertPos, which is rotated so that 00092 the oldest point is overwritten. */ 00093 void MonitorDataset::addPoint(double xVal, double yVal){ 00094 //Store points 00095 xArray[*insertPos] = xVal; 00096 yArray[*insertPos] = yVal; 00097 00098 //Work out how fast we are advancing with each additional point 00099 *xIncrement = xVal - *xOld; 00100 *xOld = xVal; 00101 00102 //Store y range 00103 if(yVal > *yMax) 00104 *yMax = yVal; 00105 else if(yVal < *yMin) 00106 *yMin = yVal; 00107 00108 //Advance insert position 00109 ++(*insertPos); 00110 *insertPos %= *bufferSize; 00111 if(*insertPos == 0) 00112 //Record that buffer has been filled up, so we can now start advancing the window 00113 *bufferFull = true; 00114 00115 //If we have enough data points. 00116 if(*bufferFull){ 00117 /* Check that xVal is visible. It can vanish when the monitoring is stopped 00118 whilst the simulation is running. */ 00119 if(xVal < bndRect->left() || xVal > (bndRect->left() + bndRect->width())){ 00120 //Reposition drawing point 19/20 of the way along the bound rectangle 00121 double leftPos = xVal - ( ((double)*bufferSize * 19.0 ) / 20.0) * (*xIncrement); 00122 bndRect->setLeft(leftPos);//( 00123 } 00124 00125 /*Adjust position of the rectangle based on the ranges 00126 We have advanced bufferWidth times, each time with increment xIncrement 00127 so width of window should be bufferWidth * xIncrement. */ 00128 bndRect->setRect(bndRect->left() + *xIncrement, *yMin, *bufferSize * (*xIncrement), *yMax - *yMin); 00129 } 00130 else{ 00131 //Want to start adjusting the width straight away 00132 bndRect->setWidth(*bufferSize * (*xIncrement)); 00133 } 00134 } 00135 00136 00137 /*! Returns the bounding rectangle of the dataset. */ 00138 QwtDoubleRect MonitorDataset::boundingRect() const{ 00139 return *bndRect; 00140 } 00141 00142 00143 /*! Returns a reference to the bounding rectangle of the dataset. */ 00144 QwtDoubleRect* MonitorDataset::boundingRectRef() const{ 00145 return bndRect; 00146 } 00147 00148 00149 /*! Deletes everything in the class. 00150 Carry this out here instead of the destructor because copy() returns a copy 00151 of the references and so the destructor could be invoked twice on the same 00152 objects. */ 00153 void MonitorDataset::cleanUp(){ 00154 #ifdef MEMORY_DEBUG 00155 cout<<"CLEANING UP MONITOR DATASET"<<endl; 00156 #endif//MEMORY_DEBUG 00157 00158 //Delete everything allocated on the stack. 00159 delete [] xArray; 00160 delete [] yArray; 00161 delete insertPos; 00162 delete bufferSize; 00163 delete xIncrement; 00164 delete xOld; 00165 delete yMin; 00166 delete yMax; 00167 delete bufferFull; 00168 delete bndRect; 00169 } 00170 00171 00172 /*! Copies references so that new class updates in sync with old. 00173 Copy all the references to data and arrays and the rectangle. Do it this way 00174 because QwtPlot uses a copy of this dataset and invokes methods on the copy. */ 00175 MonitorDataset* MonitorDataset::copy() const{ 00176 MonitorDataset* tempMonitorData = new MonitorDataset(); 00177 tempMonitorData->bufferSize = bufferSize; 00178 tempMonitorData->xIncrement = xIncrement; 00179 tempMonitorData->xOld = xOld; 00180 tempMonitorData->yMin = yMin; 00181 tempMonitorData->yMax = yMax; 00182 tempMonitorData->bndRect = bndRect; 00183 tempMonitorData->xArray = xArray; 00184 tempMonitorData->yArray = yArray; 00185 tempMonitorData->insertPos = insertPos; 00186 tempMonitorData->bufferFull = bufferFull; 00187 00188 return tempMonitorData; 00189 } 00190 00191 00192 /*! Returns the number of data points held by this class. */ 00193 size_t MonitorDataset::size() const{ 00194 return *bufferSize; 00195 } 00196 00197 00198 /*! Returns the x value at position i. */ 00199 double MonitorDataset::x(size_t i) const{ 00200 // cout<<"READING X: bufferSize="<<*bufferSize<<"; i="<<i<<"; insertPos="<<*insertPos<<"; VALUE = "<<xArray[(i + *insertPos) % *bufferSize]<<endl; 00201 return xArray[(i + *insertPos) % *bufferSize]; 00202 } 00203 00204 00205 /*! Returns the y value at position i. */ 00206 double MonitorDataset::y(size_t i) const{ 00207 return yArray[(i + *insertPos) % *bufferSize]; 00208 } 00209 00210
1.4.4