PDA

View Full Version : Fill mode using QPainter



lni
22nd March 2009, 15:54
Hi,

I am plotting a set of curves next to one another, amplitude vs. time (amplitudes are measured at different time), where time is in y axis and amplitude is in x axis.

I need to fill all curves whose amplitudes are over a certain amplitude, or those whose amplitudes are less than a certain amplitude.

In the attached example, I only fill positive amplitude, but eventually I need be able to fill negative amplitude too..

How can I effectively do this with good performance? QPainter::setClipPath is extremely slow...

Thanks

lni
23rd March 2009, 13:12
Can anyone give a suggestion? Let's say I just need to draw one curve, where I need to fill the area whose amplitude are greater than a certain value...

Thanks

spud
23rd March 2009, 14:10
Have you tried QPainter::drawPolyon()?
And how slow is slow? How many values does a typical curve have?

lni
23rd March 2009, 14:21
Have you tried QPainter::drawPolyon()?
And how slow is slow? How many values does a typical curve have?

That is what I am using. To fill the area, I need to clip the painter using QPainter::setClipPath, which in turn needs to call QPainterPath::addPolygon. In my test, I have 512 curves with 370 points in each curve, this takes 2 to 5 seconds to plot. The real data will have more curves and more points...

I have seen no visual delay in plotting much larger data from other software, so I guess I am doing it wrong....

spud
23rd March 2009, 16:53
If you can avoid using a clip path, you will certainly be faster, but plotting 200.000 points is going to be slow however you do it. You have to reduce the complexity somehow, or cache rendered pixmaps.

lni
23rd March 2009, 17:29
If you can avoid using a clip path, you will certainly be faster, but plotting 200.000 points is going to be slow however you do it. You have to reduce the complexity somehow, or cache rendered pixmaps.

Then how do you fill the area whose amplitudes are larger than the given value? It may be slow, but I am comparing similar software that has more points than my test data, and they are much faster...

spud
23rd March 2009, 17:48
This code is performant enough for me with up to 10.000 points:

class Plot : public QWidget
{
public:
Plot()
{
for(int x=0;x<POINT_COUNT;x++)
data[x] = QPointF(qreal(x)/POINT_COUNT, sin(x/20.));
data[POINT_COUNT-1]=QPointF(1, 0);
}
void paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(0, height()/2);
painter.scale(width(), height()/2);
painter.setPen(Qt::darkGreen);
painter.setBrush(Qt::green);
painter.drawPolygon(data, POINT_COUNT);
}
static const int POINT_COUNT = 1000;
QPointF data[POINT_COUNT];
};
It will be faster without antialiasing of course.
If you want to speed it up more, you could use multiple threads that paint on QImages which are combined, or you could try painting on an OpenGL window.
But first of all I would try reducing complexity. How large is your rendering target? You don't need to use more than one point every two pixels or so.

lni
23rd March 2009, 18:03
Thanks!

The requirements are to fill the area whose amplitudes are bigger than a certain value, for instance, in your sine curve example, only fill the area whose amplitudes are bigger than 0.7, not to fill the entire polygon...

I didn't specify render hint, so the default hint is used which I think should be a faster one...

The data set has dimension of 256 x 370, the plot widget has a size of 800 x 800...

There is no multi-thread involved because the software I am comparing to doesn't use multi-thread...