Fill area with color depending on third value array

Hi,

I wonder is there a way to plot curve and fill the area between this curve and baseline with colors that depend on the third array values? Example of this you can see here (second and third plots): https://www.mathworks.com/matlabcent...screenshot.png

To do this for a single curve we should have **X-array** values, **Y-array** values and the third array values **Z** and **Z** codes the color of filled polygon in each point **(X, Y)**.

In Matlab that is done with patch() function https://www.mathworks.com/help/matlab/ref/patch.html

Best regards

Re: Fill area with color depending on third value array

In general the filling is done by a QBrush and a brush can be defined by a linear gradient.

Now the problem is to make the gradient steps being related to the coordinate system of the plot ?

How is the situation in your case - I can imagine, that you need [0.0, 1.0] of the gradient being corresponding to [ curve->baseline() - delta, curve->baseline() + delta ] ?

Uwe

2 Attachment(s)

Re: Fill area with color depending on third value array

Uwe, Thank for the answer,

Yes, first of all I don't understand how to make gradient steps related to the QWT axes coordinate system.

Actually I don't fully understand what input parameters of **void QGradient::setColorAt(qreal position, const QColor &color)** means beacause **qreal position** is a single number and I have two numbers (one for x- and other for y-axis).

So in my case I'm trying to implement the second plot of https://www.mathworks.com/matlabcent...screenshot.png

So for any **(x0, y0)** point I need to set color as bright as **z0 **value is.

I tried:

Code:

linearGrad.

setCoordinateMode(QGradient::StretchToDeviceMode);

linearGrad.setColorAt(0, Qt::black);

linearGrad.setColorAt(0.2, Qt::white);

curve->setBrush(linearGrad);

curve->setBaseline(1);

// ???????? ????? ?? ????? ????????? ??????

points <<

QPointF( 0.0,

0.0 ) // ?????????? x, y

And I get the image:

Attachment 13343

But I can't understand how points are related to the axes coordinate system?

And the next step would be how to code color with **z-value** array for each point? I suspect it would be done with **void QGradient::setColorAt(qreal position, const QColor &color)** and the algorithm how to transform z-value to the color is well known in Internet and I think will find the answer for this.

2 Attachment(s)

Re: Fill area with color depending on third value array

Uwe,

I'm trying to find pixels coordinate of the (x0, y0) point. I use the function double **QwtPlot::transform(int axisId, double value)**:

Code:

double x0 = ui->qwtPlot->transform(ui->qwtPlot->x(), 0);

double y0 = ui->qwtPlot->transform(ui->qwtPlot->y(), 1);

double x1 = ui->qwtPlot->transform(ui->qwtPlot->x(), 3.0);

double y1 = ui->qwtPlot->transform(ui->qwtPlot->y(), 1);

linearGrad.

setCoordinateMode(QGradient::LogicalMode);

linearGrad.setColorAt(0, Qt::black);

linearGrad.setColorAt(0.5, Qt::white);

curve->setBrush(linearGrad);

curve->setBaseline(1);

points <<

QPointF( 0.0,

0.0 ) // ?????????? x, y

curve->setSamples( points ); // ????????????? ????? ????? ? ??????

and I get wrong pixels coordinate. For example I use QwtPlot Widget and I can see in Designer that the size its **width is 782 pixels** (see picture attached) but I get **x1 = 137.0**.

Am I doing something wrong?

Attachment 13344Attachment 13345

Re: Fill area with color depending on third value array

Quote:

Originally Posted by

**Vasya**
I'm trying to ....

Before talking about code I need to understand what ( not how ! ) you want to achieve.

When looking at mathworks page the 3 plots are different:

- Plot 1)

A solid filling - Plot 2)

Not 100% sure, but it looks like the filling depends on the distance between the value and the baseline, while

you have the same color for all points on the other coordinate. In the screenshot the baseline is an x coordinate

and all points with the same y coordinate have the same color.

- Plot 3)

Here the filling seems to be unrelated to the curve point and the color changes according to the distance from the baseline.

For Plot 2/3 you would need to derive from QwtPlotCurve, where you add a QwtColorMap and set a QwtInterval, that is the bounding interval for distances from the baseline in plot coordinates.

Then for Plot 3 you need to overload QwtPlotCurve::fillCurve, where you calculate the gradient from the color map and then update the brush, before calling he base class.

For Plot2 you will have to iterate over all points to calculate the gradient stops from the color map. So be careful when having many points.

HTH,

Uwe

Re: Fill area with color depending on third value array

Uwe,

Quote:

Plot 2)

Not 100% sure, but it looks like the filling depends on the distance between the value and the baseline, while

you have the same color for all points on the other coordinate. In the screenshot the baseline is an x coordinate

and all points with the same y coordinate have the same color.

I'm going to implement plot2 and yes the fill color depends on the distance between curve and baseline for each point of curve.

Quote:

For Plot2 you will have to iterate over all points to calculate the gradient stops from the color map. So be careful when having many points.

It is going to be a about 100 000 points I understand that the perfomance may suffer but I want test it.

And to calculate gradient stops I need to transform every point with axes coordinate (x0, y0) to pixels. I stopped here. As I understand this is done via QwtScaleMap::transform(x) wich return the calculated value as (from qwt_scale_map.h):

Code:

return d_p1 + ( s - d_ts1 ) * d_cnv;

where:

Code:

double d_s1, d_s2; // scale interval boundaries ??

double d_p1, d_p2; // paint device interval boundaries ??

double d_cnv; // conversion factor ??

double d_ts1; // don't know what it is

Actually I dont'fully understand how these variables are connected with canvas size because I tried to change canvas size in designer and in debug mode looked their values and couldn't understand their meaning:confused:

best regards

Re: Fill area with color depending on third value array

I recommend to use one of the development branches > Qwt 6.1, where you find the FilterPointsAggressive flag, that will reduce the number of points to be painted to a reasonable number.

Then overload QwtPlotCurve::fillCurve, the polygon parameter contains the points to be painted already being translated in widget coordinates. When using the QwtScaleMap

you can always translate between widget and plot coordinates.

Have a look at the implementation of QwtPlotCurve::fillCurve - the code is only truth, when trying to understand how certain things work.

HTH,

Uwe