PDA

View Full Version : Problem while changing size of QVector with linking to QwtPlotCurve



Momergil
11th June 2014, 22:01
Hello!

Although this question involves Qwt, I think the problem may not be regarding that class, but a more general "memory address and pointer" issue.

I have a QwtPlot with some QwtPlotCurves. In another part of my code, I have two QVector<double>, one for X points and the other for Y points. I initialize those vectors when creating a class (putting 0.0, 1.0, 2.0 etc in X vector and 0.0 in the Y vector). Later, I call QwtPlotCurve::setRawSamples() to point to those QVectors.

After that, the graph appears and I start receiving data; everything plots correctly with no problems.

But my graph has a feature of changing the X scale, from 0-60 to 0-600 and back to 0-60. In order to do that, not only I have to call the QwtPlot::setAxisScale() method, but I need to resize my QVectors as well to have the new size.

The problem is that, when I do that, the graph stops plotting correctly and start plotting some thrash. I was thinking about the problem and I noticed that the problem was probably due to the fact that QVector may change it's position in the memory if the resize() is performed in such as way that it doesn't find space where the current data is located; so it copies the current data to a new location and adds the new added data. In other words, after calling a resize(), the address returned by the method QVector::constData() may be different.

So what I did was to make my QwtPlotCurves call setRawSamples() each time the size of the vectors is changed and call a QwtPlot::replot() after that. I imagined that by doing this, my QwtPlotCurves would always work with the current data position in memory.

But it didn't work :/ The graph continues to plot thrash instead. I did some debugging and I noticed that the resize and populate mechanics is working correctly; it really seems something related to memory address. But what am I missing?

What follows is part of the code. I'm glad for any help,

Momergil



//Do the resize of the vectors
void DataStream::setTrendsParameters(const DataStream::TrendsTimeInterval value)
{
if (!trendsMutex.tryLock())
{
usleep(2);
trendsMutex.lock();
}

int aaa, bbb;
const int previousPointsCount = m_data.trends.numPoints;

switch (value)
{
case OneMinute: m_data.trends.numPoints = Trends60Points; break;
case TenMinutes: m_data.trends.numPoints = Trends600Points; break;
case Infinite: m_data.trends.numPoints = TrendsInfinite; break;
}

static const int diff = Trends600Points - Trends60Points;

switch (CFG_ED.realTimeTrendsOperationMode())
{
case OneMinute:
m_data.trends.pqDataX.resize(Trends60Points);

for (aaa = 0; aaa < 2; aaa++)
{
for (bbb = 0; bbb < (RE8K_ICDEF_TRENDS_ITEM_COUNT/2); bbb++)
{
if (Q_LIKELY(m_data.trends.pqDataY[aaa][bbb].size() == Trends600Points))
m_data.trends.pqDataY[aaa][bbb] = m_data.trends.pqDataY[aaa][bbb].mid(0,diff);
}
}

break;

case TenMinutes:
case Infinite:
if (previousPointsCount == Trends60Points)
{
m_data.trends.pqDataX.resize(Trends600Points);

for (aaa = Trends60Points; aaa < Trends600Points; aaa++)
m_data.trends.pqDataX[aaa] = (qwt_point)aaa;

qwt_data emptyData(diff,0.0);

for (aaa = 0; aaa < 2; aaa++)
{
for (bbb = 0; bbb < (RE8K_ICDEF_TRENDS_ITEM_COUNT/2); bbb++)
{
m_data.trends.pqDataY[aaa][bbb] = emptyData + m_data.trends.pqDataY[aaa][bbb];
}
}
}
break;
}

for (aaa = 0; aaa < 2; aaa++)
{
for (bbb = 0; bbb < (RE8K_ICDEF_TRENDS_ITEM_COUNT/2); bbb++)
m_data.trends.poDataY[aaa][bbb] = &m_data.trends.pqDataY[aaa][bbb];
}

trendsMutex.unlock();
}

//Update the data
int aaa, bbb;

for (aaa = 0; aaa < pqTrendsStruct.numItems; aaa++)
m_data.trends.pqDataY[pqTrendsStruct.side][aaa].append(pqTrendsStruct.selectedItemsValues[aaa].value);

switch (CFG_ED.realTimeTrendsOperationMode())
{
case OneMinute:
case TenMinutes:
for (aaa = 0; aaa < pqTrendsStruct.numItems; aaa++)
m_data.trends.pqDataY[pqTrendsStruct.side][aaa].remove(0,1); //D_TOVER
break;

case Infinite: //problem not even arises here, so this part actually doesn't matter
{
static const int diff = Trends600Points - Trends60Points;

for (aaa = 0; aaa < pqTrendsStruct.numItems; aaa++)
{
m_data.trends.pqDataY[pqTrendsStruct.numItems][aaa].remove(qrand() % diff);

for (bbb = 0; bbb < diff; bbb++)
{
if (m_data.trends.pqDataY[pqTrendsStruct.numItems][aaa].at(bbb) > 0.0)
m_data.trends.pqDataY[pqTrendsStruct.numItems][aaa][bbb] = m_data.trends.pqDataY[pqTrendsStruct.numItems][aaa].at(bbb) - 1.0;
else if (m_data.trends.pqDataY[pqTrendsStruct.numItems][aaa].at(bbb) < 0.0)
m_data.trends.pqDataY[pqTrendsStruct.numItems][aaa][bbb] = m_data.trends.pqDataY[pqTrendsStruct.numItems][aaa].at(bbb) + 1.0;
}
}
}
break;
}

if (updateUi)
emit signalNewTrendsData(); //class replot()