Results 1 to 7 of 7

Thread: Fill area with color depending on third value array

  1. #1
    Join Date
    Nov 2019
    Posts
    31
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default 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. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,250
    Thanked 860 Times in 809 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default 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. #3
    Join Date
    Nov 2019
    Posts
    31
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default 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:
    Qt Code:
    1. QLinearGradient linearGrad(QPointF(0, 1), QPointF(3, 1));
    2. linearGrad.setCoordinateMode(QGradient::StretchToDeviceMode);
    3. linearGrad.setColorAt(0, Qt::black);
    4. linearGrad.setColorAt(0.2, Qt::white);
    5. curve->setBrush(linearGrad);
    6. curve->setBaseline(1);
    7.  
    8. // ???????? ????? ?? ????? ????????? ??????
    9. QPolygonF points;
    10.  
    11. points << QPointF( 0.0, 0.0 ) // ?????????? x, y
    12. << QPointF( 0.5, 1.5 ) << QPointF( 1.0, 1.5 )
    13. << QPointF( 1.5, 1.0 ) << QPointF( 2.0, 0.5 )
    14. << 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.
    Attached Images Attached Images

  4. #4
    Join Date
    Nov 2019
    Posts
    31
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default 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:
    1. double x0 = ui->qwtPlot->transform(ui->qwtPlot->x(), 0);
    2. double y0 = ui->qwtPlot->transform(ui->qwtPlot->y(), 1);
    3. double x1 = ui->qwtPlot->transform(ui->qwtPlot->x(), 3.0);
    4. double y1 = ui->qwtPlot->transform(ui->qwtPlot->y(), 1);
    5.  
    6. QLinearGradient linearGrad(QPointF(x0, x0), QPointF(x1, y1));
    7. linearGrad.setCoordinateMode(QGradient::LogicalMode);
    8. linearGrad.setColorAt(0, Qt::black);
    9. linearGrad.setColorAt(0.5, Qt::white);
    10. curve->setBrush(linearGrad);
    11. curve->setBaseline(1);
    12.  
    13. QPolygonF points;
    14.  
    15. points << QPointF( 0.0, 0.0 ) // ?????????? x, y
    16. << QPointF( 0.5, 1.5 ) << QPointF( 1.0, 1.5 )
    17. << QPointF( 1.5, 1.0 ) << QPointF( 2.0, 0.5 )
    18. << QPointF(2.5, 0.5) << QPointF(3.0, 1.0);
    19.  
    20. 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. #5
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,250
    Thanked 860 Times in 809 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

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

    Quote Originally Posted by Vasya View Post
    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. #6
    Join Date
    Nov 2019
    Posts
    31
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default 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:
    1. return d_p1 + ( s - d_ts1 ) * d_cnv;
    To copy to clipboard, switch view to plain text mode 
    where:
    Qt Code:
    1. double d_s1, d_s2; // scale interval boundaries ??
    2. double d_p1, d_p2; // paint device interval boundaries ??
    3.  
    4. double d_cnv; // conversion factor ??
    5. 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. #7
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,250
    Thanked 860 Times in 809 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default 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)

Similar Threads

  1. Replies: 5
    Last Post: 17th December 2014, 12:07
  2. Replies: 10
    Last Post: 7th March 2012, 18:22
  3. Replies: 3
    Last Post: 7th September 2011, 12:26
  4. Fill area of QPainterPath
    By vides2012 in forum Qt Programming
    Replies: 6
    Last Post: 17th June 2011, 13:00
  5. Replies: 1
    Last Post: 9th May 2011, 15:19

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.