# Thread: Fill area with color depending on third value array

1. Novice
Join Date
Nov 2019
Posts
31
Thanks
8
Qt products
Platforms

## 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

2. Uwe
Expert
Join Date
Feb 2006
Location
Munich, Germany
Posts
3,250
Thanked 860 Times in 809 Posts
Qt products
Platforms

## 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

3. Novice
Join Date
Nov 2019
Posts
31
Thanks
8
Qt products
Platforms

## Re: Fill area with color depending on third value array

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:
Qt Code:
`QLinearGradient linearGrad(QPointF(0, 1), QPointF(3, 1));    linearGrad.setCoordinateMode(QGradient::StretchToDeviceMode);    linearGrad.setColorAt(0, Qt::black);    linearGrad.setColorAt(0.2, Qt::white);    curve->setBrush(linearGrad);    curve->setBaseline(1);     // ???????? ????? ?? ????? ????????? ??????    QPolygonF points;            points << QPointF( 0.0, 0.0 ) // ?????????? x, y        << QPointF( 0.5, 1.5 ) << QPointF( 1.0, 1.5 )        << QPointF( 1.5, 1.0 ) << QPointF( 2.0, 0.5 )        << QPointF(2.5, 0.5) << QPointF(3.0, 1.0);`
To copy to clipboard, switch view to plain text mode
And I get the image:
qtasdf.jpg
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.

4. Novice
Join Date
Nov 2019
Posts
31
Thanks
8
Qt products
Platforms

## 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):
Qt 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); QLinearGradient linearGrad(QPointF(x0, x0), QPointF(x1, y1));linearGrad.setCoordinateMode(QGradient::LogicalMode);linearGrad.setColorAt(0, Qt::black);linearGrad.setColorAt(0.5, Qt::white);curve->setBrush(linearGrad);curve->setBaseline(1); QPolygonF points;            points << QPointF( 0.0, 0.0 ) // ?????????? x, y        << QPointF( 0.5, 1.5 ) << QPointF( 1.0, 1.5 )        << QPointF( 1.5, 1.0 ) << QPointF( 2.0, 0.5 )        << QPointF(2.5, 0.5) << QPointF(3.0, 1.0); curve->setSamples( points ); // ????????????? ????? ????? ? ??????`
To copy to clipboard, switch view to plain text mode
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?
1.jpg2.jpg

5. Uwe
Expert
Join Date
Feb 2006
Location
Munich, Germany
Posts
3,250
Thanked 860 Times in 809 Posts
Qt products
Platforms

## Re: Fill area with color depending on third value array

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

6. Novice
Join Date
Nov 2019
Posts
31
Thanks
8
Qt products
Platforms

## Re: Fill area with color depending on third value array

Uwe,
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.

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):
Qt Code:
`return d_p1 + ( s - d_ts1 ) * d_cnv;`
To copy to clipboard, switch view to plain text mode
where:
Qt 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`
To copy to clipboard, switch view to plain text mode
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

best regards

7. Uwe
Expert
Join Date
Feb 2006
Location
Munich, Germany
Posts
3,250
Thanked 860 Times in 809 Posts
Qt products
Platforms

## 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

8. ## The following user says thank you to Uwe for this useful post:

Vasya (26th February 2020)