Results 1 to 7 of 7

Thread: QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

  1. #1
    Join Date
    Jun 2008
    Location
    Boulder, Colorado, USA
    Posts
    70
    Thanks
    16
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

    We're finding that QwtPlotCurves with the "Steps" CurveStyle show a misleading value when extending beyond the visible area of the QwtPlot.

    The following image shows three QwtPlots with the same series data, drawn with a line width of 2 pixels, shown with magnified insets:
    .
    • Top: Drawn with the "Lines" CurveStyle. Good.
    • Middle: Drawn with the "Steps" CurveStyle. Shows problem.
    • Bottom: Vertically zoomed out "Steps" view.


    StepClip1.jpg

    This image also available here:
    http://cadswes2.colorado.edu/~philw/.../StepClip1.png

    We're using Qwt 6.1.2 on Windows. We're seeing this with both Qt 4.8.5 and Qt 5.5.1.

    We're hoping that we won't have to intervene at the application level -- detecting crossings of the plot edge and breaking the curve into multiple curves or segments.

    Is this a known problem with the "Steps" CurveStyle?
    Any ideas on what to do?
    Thank you in advance.
    Last edited by philw; 28th July 2016 at 02:08.

  2. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,277
    Thanked 871 Times in 819 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

    A small demo code with a curve in steps style - demonstrating the problem ?

    Uwe

  3. #3
    Join Date
    Jun 2008
    Location
    Boulder, Colorado, USA
    Posts
    70
    Thanks
    16
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

    Here is a simple code example, and annotated screenshot, showing this problem. This is with Qwt 6.1.2.

    StepClip2.jpg

    Image also available here:
    http://cadswes2.colorado.edu/~philw/.../StepClip2.png

    Qt Code:
    1. void SlotPlot::test1_Gnats5737()
    2. {
    3. QwtPlot* myPlot = new QwtPlot (NULL);
    4. myPlot->setWindowTitle ("Step Curve Clipping, Qwt 6.1.2");
    5. myPlot->resize (520, 220);
    6.  
    7. QPolygonF dataPoly;
    8. dataPoly << QPointF (10.0, 0.0)
    9. << QPointF (20.0, 0.0)
    10. << QPointF (30.0, 90.0)
    11. << QPointF (40.0, 45.0)
    12. << QPointF (50.0, 0.0)
    13. << QPointF (60.0, 0.0);
    14.  
    15. QwtPlotCurve* curve1 = new QwtPlotCurve ("Curve 1");
    16. QwtPlotCurve* curve2 = new QwtPlotCurve ("Curve 2");
    17. QwtPlotCurve* curve3 = new QwtPlotCurve ("Curve 3");
    18. QwtPlotCurve* curve4 = new QwtPlotCurve ("Curve 4");
    19.  
    20. curve1->setSamples (dataPoly);
    21. curve2->setSamples (dataPoly.translated (70.0, 0.0));
    22. curve3->setSamples (dataPoly.translated (140.0, 0.0));
    23. curve4->setSamples (dataPoly.translated (210.0, 0.0));
    24.  
    25. QPen curvePen (Qt::black);
    26. curvePen.setWidth (4);
    27. curve1->setPen (curvePen);
    28. curve2->setPen (curvePen);
    29. curve3->setPen (curvePen);
    30. curve4->setPen (curvePen);
    31.  
    32. curve1->setStyle (QwtPlotCurve::Lines);
    33. curve2->setStyle (QwtPlotCurve::Steps);
    34. curve3->setStyle (QwtPlotCurve::Lines);
    35. curve4->setStyle (QwtPlotCurve::Steps);
    36.  
    37. curve3->setRenderHint (QwtPlotItem::RenderAntialiased, true);
    38. curve4->setRenderHint (QwtPlotItem::RenderAntialiased, true);
    39.  
    40. const QBrush symB (Qt::red);
    41. const QPen symP (Qt::blue);
    42. const QSize symS (8,8);
    43. curve1->setSymbol (new QwtSymbol (QwtSymbol::Ellipse, symB, symP, symS));
    44. curve2->setSymbol (new QwtSymbol (QwtSymbol::Ellipse, symB, symP, symS));
    45. curve3->setSymbol (new QwtSymbol (QwtSymbol::Ellipse, symB, symP, symS));
    46. curve4->setSymbol (new QwtSymbol (QwtSymbol::Ellipse, symB, symP, symS));
    47.  
    48. curve1->attach (myPlot);
    49. curve2->attach (myPlot);
    50. curve3->attach (myPlot);
    51. curve4->attach (myPlot);
    52.  
    53. // Zoom vertically every other invocation
    54. static int callCnt (0);
    55. if ((++callCnt % 2) != 0)
    56. {
    57. myPlot->setAxisScale (QwtPlot::yLeft, 0.0, 50.0);
    58. myPlot->updateAxes();
    59. }
    60.  
    61. // finally, refresh the plot
    62. myPlot->replot();
    63. myPlot->show();
    64. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,277
    Thanked 871 Times in 819 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

    This is a bug of the polygon clipping - the clip rectangle has to be the canvas rectangle extended by 0.5 of the pen width ( missing in case of Steps ).
    Bug has been fixed in SVN in all relevant branches >= 6.1.

    If you need a workaround without updating Qwt you could disable polygon clipping ( curve->setPaintAttribute( QwtPlotCurve::ClipPolygons, false) ), but in case of zooming in deep it would have an significant negative effect on the performance.

    Uwe

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

    philw (29th July 2016)

  6. #5
    Join Date
    Jun 2008
    Location
    Boulder, Colorado, USA
    Posts
    70
    Thanks
    16
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

    Uwe, thanks so much for that fix. I took a look at what you did (in the SVN Qwt 6.1 development head). In method QwtPlotCurve::drawSteps(), you're using a slightly enlarged copy of the canvasRect parameter for the clipping rectangle.

    I see that QwtPlotCurve::drawSteps() is virtual, and we are, in fact, already using our own subclass of QwtPlotCurve. Even though the provided canvasRect is also used for something else (i.e. also when calling fillCurve()), we are getting the desired results by OVERRIDING the drawSteps method in order to provided a (conditionally) expanded copy of canvasRect. The code below is doing that only for the current and older versions of Qwt, and only when polygon clipping is enabled.

    Uwe, does it make sense that the slightly expanded copy of canvasRect is not actually causing a problem for the call to fillCurve()? ... i.e. within the actual QwtPlotCurve::drawSteps() implementation.

    Qt Code:
    1. // virtual from QwtPlotCurve
    2. void SlotCurve::drawSteps (QPainter *painter,
    3. const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    4. const QRectF &canvasRect, int from, int to) const
    5. {
    6. //---------------------------------------------------------------------
    7. // Fixup to QwtPlotCurve bug which will be fixed after Qwt 6.1.3.
    8. // See QtCentre/Qwt Thread: http://www.qtcentre.org/threads/66464
    9. // "QwtPlotCurve Step CurveStyle incorrect when extending beyond
    10. // QwtPlot edge". [July 2016].
    11. //
    12. // If required, adjust the canvasRect to be larger, on all four sides,
    13. // by the thickness of the drawn curve (i.e. the QPainter QPen width).
    14. //---------------------------------------------------------------------
    15.  
    16. // Note: QWT_VERSION is (major << 16) + (minor << 8) + patch.
    17. const bool versNeedsCanvasRectExpand = (QWT_VERSION <= 0x060103);
    18. const bool clipOn = testPaintAttribute (QwtPlotCurve::ClipPolygons);
    19.  
    20. QRectF adjustedCanvasRect (canvasRect);
    21. if (versNeedsCanvasRectExpand && clipOn)
    22. {
    23. qreal pw = qMax (qreal(1.0), painter->pen().widthF());
    24. adjustedCanvasRect = canvasRect.adjusted (-pw, -pw, pw, pw);
    25. }
    26.  
    27. // Call the Qwt base class method
    28. QwtPlotCurve::drawSteps (painter, xMap, yMap,
    29. adjustedCanvasRect, from, to);
    30. }
    To copy to clipboard, switch view to plain text mode 

  7. #6
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,277
    Thanked 871 Times in 819 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

    Quote Originally Posted by philw View Post
    Uwe, does it make sense that the slightly expanded copy of canvasRect is not actually causing a problem for the call to fillCurve()?
    Not exactly sure what you mean, but my fix in SVN does not expand the bounding rectangle of the canvas - it expands the clip rectangle for polygon clipping.
    If you have a problem with filling please provide another demo code and I will have a look at it.

    Uwe

  8. #7
    Join Date
    Jun 2008
    Location
    Boulder, Colorado, USA
    Posts
    70
    Thanks
    16
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QwtPlotCurve Step CurveStyle incorrect when extending beyond QwtPlot edge

    Uwe, thanks for trying to field also that last question. The is somewhat academic. I'm satisfied with how we are applying the fix you devised. (We've introduced a "virtual override wrapper method" of QwtPlotCurve::drawSteps() in Qwt 6.1.2, to modify the canvasRect parameter value).

    Just FWIW, I'll show the Qwt code I'm talking about. Our virtual override wrapper (see code in my prior message) is calling this Qwt 6.1.2 method which lacks the new fix you devised (shown in the 2nd code block below).

    The point is that the slightly expanded canvasRect passed in to the Qwt 6.1.2 version of this method is used in BOTH lines 52 and 62. The former is for the intended fix. The latter -- the call to fillCurve() -- doesn't "want" the expanded canvasRect, but its getting it anyway. (And this doesn't seem to be causing an actual problem. I was just wondering if you think that it might).

    Qt Code:
    1. void QwtPlotCurve::drawSteps( QPainter *painter,
    2. const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    3. const QRectF &canvasRect, int from, int to ) const
    4. {
    5. const bool doAlign = QwtPainter::roundingAlignment( painter );
    6.  
    7. QPolygonF polygon( 2 * ( to - from ) + 1 );
    8. QPointF *points = polygon.data();
    9.  
    10. bool inverted = orientation() == Qt::Vertical;
    11. if ( d_data->attributes & Inverted )
    12. inverted = !inverted;
    13.  
    14. const QwtSeriesData<QPointF> *series = data();
    15.  
    16. int i, ip;
    17. for ( i = from, ip = 0; i <= to; i++, ip += 2 )
    18. {
    19. const QPointF sample = series->sample( i );
    20. double xi = xMap.transform( sample.x() );
    21. double yi = yMap.transform( sample.y() );
    22. if ( doAlign )
    23. {
    24. xi = qRound( xi );
    25. yi = qRound( yi );
    26. }
    27.  
    28. if ( ip > 0 )
    29. {
    30. const QPointF &p0 = points[ip - 2];
    31. QPointF &p = points[ip - 1];
    32.  
    33. if ( inverted )
    34. {
    35. p.rx() = p0.x();
    36. p.ry() = yi;
    37. }
    38. else
    39. {
    40. p.rx() = xi;
    41. p.ry() = p0.y();
    42. }
    43. }
    44.  
    45. points[ip].rx() = xi;
    46. points[ip].ry() = yi;
    47. }
    48.  
    49. if ( d_data->paintAttributes & ClipPolygons )
    50. {
    51. const QPolygonF clipped = QwtClipper::clipPolygonF(
    52. canvasRect, polygon, false );
    53.  
    54. QwtPainter::drawPolyline( painter, clipped );
    55. }
    56. else
    57. {
    58. QwtPainter::drawPolyline( painter, polygon );
    59. }
    60.  
    61. if ( d_data->brush.style() != Qt::NoBrush )
    62. fillCurve( painter, xMap, yMap, canvasRect, polygon );
    63. }
    To copy to clipboard, switch view to plain text mode 

    FWIW, below is an excerpt of your revision to this method (for after Qwt 6.1.3). This includes the necessary minor expansion of the canvasRect parameter, defined as "clipRect," for use by QwtPainter::drawPolyline() ...

    Qt Code:
    1. if ( d_data->paintAttributes & ClipPolygons )
    2. {
    3. qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
    4. const QRectF clipRect = canvasRect.adjusted(-pw, -pw, pw, pw);
    5.  
    6. const QPolygonF clipped = QwtClipper::clipPolygonF(
    7. clipRect, polygon, false );
    8.  
    9. QwtPainter::drawPolyline( painter, clipped );
    10. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. Make a new QwtPlotCurve on a QwtPlot?
    By bigjoeystud in forum Qwt
    Replies: 2
    Last Post: 23rd October 2014, 23:02
  2. Selecting QwtPlotCurve from QwtPlot
    By Christoss in forum Qwt
    Replies: 11
    Last Post: 23rd July 2013, 12:32
  3. Replies: 6
    Last Post: 7th June 2013, 13:39
  4. Replies: 1
    Last Post: 11th May 2012, 08:02
  5. Replies: 1
    Last Post: 13th July 2011, 08:55

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.