How to make replot qicker with curves and marker in a plot ?
Hi all. There are curves with about 300,000 samples and several thousands markers show curves's name in a plot. The markers set value according to curves's x value and y value , and the number of markers should be changed as we set different steps in Y axis. Right now it takes about 10 seconds to refresh the plot . We would like to make it .What can I do to make it happen ?
Re: How to make replot qicker with curves and marker in a plot ?
Having several thousands of plot items ( here markers ) is possible, but not exactly intended by the design of the QwtPlot framework. A better solution would be to derive from QwtPlotCurve or to create a new type of plot item handling all the labels.
But this all doesn't explain 10 seconds - there must be something completely wrong in your application code how to use the plot widget. So before changing any code you should identify what is going on: a simple QElapsedTimer::elapsed around QwtPlot::drawItems() will probably indicate, that your code triggers many, many replots where a single one would be good enough.
Uwe
Re: How to make replot qicker with curves and marker in a plot ?
Uwe , thank you very much . I have find out what costs the time . Each time I creat a QwtPlotMarer showing curve's name , it would take about 10-18 milliseconds to locate the value in X axis according to the given value in Y axis.
As the number of markers increases , it would take much longer .
Now comes another question , is there better way to locate it ? The code below is base on the qwt-examples.
Quote:
QLineF BaseCurve::curveLineAt(QPolygonF poly, double y)
{
QLineF line;
if ( poly.size() >= 2 )
{
const QRectF br = poly.boundingRect();
if ( br.isValid() && y >= br.top() && y <= br.bottom() )
{
int index = -1;
if(poly.at(0).y()<= y && poly.at(1).y()> y)
index = 1;
// here the for circle takes most of the time
for(int i = 1 ; i < poly.size() ; i++)
{
if(poly.at(i).y() >=y && poly.at(i -1).y() < y) {
index = i ;
}
}
if ( index == -1 &&
y == poly.at( poly.size() - 1 ).y() )
{
index = poly.size() - 1;
}
if ( index > 0 )
{
line.setP1( poly.at( index - 1 ) );
line.setP2( poly.at( index ) );
}
}
}
return line;
}
Re: How to make replot qicker with curves and marker in a plot ?
Well, when your samples are x or y ordered you could use a binary search algo, what is O(log n) instead of O(n) like in your code. F.e. have a look at CurveTracker::curveLineAt() in playground/curvetracker/curvetracker.cpp.
Uwe
Re: How to make replot qicker with curves and marker in a plot ?
Thanks again , it works much better now.
Added after 45 minutes:
If one curve's about 300,000 samples, with 3,4 curves in a plot. It would take about 240 milliseconds to replot , plus the time taken by handling with data , it would be up to 500 milliseconds . Is there a faster way to drawitems and replot ?
Re: How to make replot qicker with curves and marker in a plot ?
Quote:
Originally Posted by
lwz
If one curve's about 300,000 samples, with 3,4 curves in a plot ...
There are several ways how to improve the performance for drawing of a curve, but before going into details you should have an idea about what is consuming the time in your plot. So try the following:
Code:
{
....
virtual void drawSeries
( QPainter *painter,
const QRectF &canvasRect,
int from,
int to
) const {
QElapsedTimer timer;
timer.start();
QwtPlotCurve::drawSeries( painter, xMap, yMap, canvasRect, from, to
);
qDebug() << "Elapsed: #" << to - from << timer.elapsed();
}
};
Then:
- disable antialiasing
- set "no symbols"
- use a curve line width of 0
Now you will know if rendering of the curves is the main factor of the time used in a replot cycle.
Uwe
Re: How to make replot qicker with curves and marker in a plot ?
Re: How to make replot qicker with curves and marker in a plot ?
My curves have no symbol, and it takes almost the same time with QwtPlotItem::RenderAntialiased true or false , 45 milliseconds approximately.
Anything else can do ?
Re: How to make replot qicker with curves and marker in a plot ?
Don't believe that antialiasing is really no issue, but anyway - the next step is trying to reduce the number of lines to be painted. Should be obvious, that when trying to draw 300000 lines to a widget with a resolution of ~1000 pixels has a lot of pointless overhead.
A common and very effective way to deal with huge number of samples is to have 3-4 sets with different levels of detail. In situations where many points would be visible, you would display a set with a lower resolution, while in situations, where you zoom in deep the polygon clipping algo, that is in implemented in Qwt, will reduce the number of points. Calculating the different sets can be done with Douglas Peucker f.e offered by QwtWeedingCurveFitter.
Unfortunately Douglas Peucker is a heavy algo and should not be done inside of the render cycle ( so better don't use it with QwtPlotCurve::setCurveFitter() ).
Uwe
Re: How to make replot qicker with curves and marker in a plot ?
Hei,Uwe, i know you have done some applications linked to the oil industry. Mine is also linked to the oil drilling . How do you handle so many samples and draw curves in plots ?
Re: How to make replot qicker with curves and marker in a plot ?
See above: same question, same answer.
Uwe