Results 1 to 9 of 9

Thread: How to plot the real time data in qwtplot while erasing fixed-width old data?

  1. #1
    Join Date
    May 2020
    Location
    HongKong
    Posts
    4
    Qt products
    Qt4 Qt5 Qt/Embedded

    Question How to plot the real time data in qwtplot while erasing fixed-width old data?

    This video is the effect I want,I referenced that oscilloscope code,but I did not use that QwtPlotDirectPainter class,because I can't achieve the effect I want?there are 12 curves refreshed at the same time,but high CPU usage,average over 90% on my pi 3b.


    2020-05-08_234635.jpg
    2020-05-08_230040.jpg
    2020-05-08_224200.jpg
    This is my code compression package.myoscilloscope.zip

    I use below method to update the graph in real time.
    Qt Code:
    1. //class MPlotWaveCurve inherit from QwtPlotCurve
    2. void MPlotWaveCurve::drawCurve(QPainter * painter, int style,
    3. const QwtScaleMap & xMap, const QwtScaleMap & yMap,
    4. const QRectF & canvasRect, int from, int to) const
    5. {
    6. switch (style)
    7. {
    8. case Lines:
    9. if (testCurveAttribute(Fitted))
    10. {
    11. // we always need the complete
    12. // curve for fitting
    13. from = 0;
    14. to = dataSize() - 1;
    15. }
    16. /*
    17. below 10 lines code achieved my effect,
    18. variable m_iEaserCount represents the erased width,
    19. variable m_iCurrentPoint represents the latest data index
    20. */
    21. if ((from < m_iCurrentPoint) && (m_iCurrentPoint < to - m_iEaserCount))
    22. {
    23. drawLines(painter, xMap, yMap, canvasRect, from, m_iCurrentPoint);
    24. drawLines(painter, xMap, yMap, canvasRect, m_iCurrentPoint + m_iEaserCount, to);
    25. }
    26. else
    27. {
    28. drawLines(painter, xMap, yMap, canvasRect, from, m_iCurrentPoint);
    29. }
    30. break;
    31. case Sticks:
    32. drawSticks(painter, xMap, yMap, canvasRect, from, to);
    33. break;
    34. case Steps:
    35. drawSteps(painter, xMap, yMap, canvasRect, from, to);
    36. break;
    37. case Dots:
    38. drawDots(painter, xMap, yMap, canvasRect, from, to);
    39. break;
    40. case NoCurve:
    41. default:
    42. break;
    43. }
    44. }
    To copy to clipboard, switch view to plain text mode 

    Calculate the current refreshed area first, then draw the points that need to be drawn currently.The data container size is 1000.
    Qt Code:
    1. void Plot::updateCurve(int index)
    2. {
    3. CurveData *curveData = static_cast<CurveData *>( d_curve[index]->data() );
    4. curveData->lock();
    5.  
    6. int iCurrentPoint = curveData->getCurrentPointIndex();//Get the index number of the latest data in the container, starting from 0
    7. int iMaxPointCount = curveData->getMaxPointCount();//Get the capacity of a container
    8. int size = curveData->size();//Get the current size of the container
    9. if(iCurrentPoint == m_iLastPaintedPoint)
    10. {
    11. curveData->unlock();
    12. return;
    13. }
    14. QRect canvasRect = canvas()->contentsRect();
    15.  
    16. QRegion region;//Save the area to be redrawn
    17. const QwtScaleMap xMap = canvasMap( d_curve[index]->xAxis() );
    18. const QwtScaleMap yMap = canvasMap( d_curve[index]->yAxis() );
    19.  
    20. //Get the last starting X coordinate
    21. int calc_start = (m_iLastPaintedPoint > 0)?m_iLastPaintedPoint -1:m_iLastPaintedPoint;
    22. double start_x = xMap.transform( d_curve[index]->sample(calc_start).x() );
    23.  
    24. if ( iCurrentPoint > m_iLastPaintedPoint )//The data does not appear to flip, new data is added from the back
    25. {
    26. /*
    27.   Depending on the platform setting a clip might be an important
    28.   performance issue. F.e. for Qt Embedded this reduces the
    29.   part of the backing store that has to be copied out - maybe
    30.   to an unaccelerated frame buffer device.
    31.   */
    32. QRect br;
    33. if(size < iMaxPointCount)//The initial container is not full
    34. {
    35. double stop_x = xMap.transform( d_curve[index]->sample(iCurrentPoint).x());
    36. br = QRect( start_x, canvasRect.top(), stop_x - start_x, canvasRect.height());
    37. }
    38. else//After the container is full
    39. {
    40. if(iCurrentPoint + d_iEaserCount <= iMaxPointCount - 1)//If the erased point does not exceed the boundary
    41. {
    42. double stop_x = xMap.transform( d_curve[index]->sample(iCurrentPoint + d_iEaserCount).x());
    43. br = QRect( start_x, canvasRect.top(), stop_x - start_x, canvasRect.height());
    44. }
    45. else//If the boundary is exceeded, only the remaining part is erased
    46. {
    47. br = QRect( start_x, canvasRect.top(), canvasRect.right() - start_x, canvasRect.height());
    48. }
    49. }
    50. region += br;
    51. }
    52. else //Data flipped
    53. {
    54. //Tail
    55. double stop_x = xMap.transform( d_curve[index]->sample(iCurrentPoint + d_iEaserCount).x());
    56. double stop2_x = xMap.transform( d_curve[index]->sample(iMaxPointCount - 1).x());
    57. QRect r1( start_x , canvasRect.top(), stop2_x - start_x , canvasRect.height());
    58. region += r1;
    59. //Head
    60. double start2_x = xMap.transform( d_curve[index]->sample(0).x());
    61. QRect r2( start2_x, canvasRect.top(), stop_x - start2_x, canvasRect.height());
    62. region += r2;
    63. }
    64. //Set the latest data index of 12 curves
    65. for(int i = 0;i < 12;i++)
    66. {
    67. d_curve[i]->SetCurrentPoint(iCurrentPoint);
    68. }
    69.  
    70. m_iLastPaintedPoint = iCurrentPoint;
    71. curveData->unlock();
    72. //Partial refresh,replot 12 curves
    73. canvas()->update(region);
    74. }
    To copy to clipboard, switch view to plain text mode 

    In order to achieve the effect I want, how to reduce CPU consumption ?

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

    Default Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    QWidget does not offer to "erase" something - all you can do is to redraw from scratch. This is why QwtPlotDirectPainter is useful - it at least allows to draw on top of something existing.

    Uwe

  3. #3
    Join Date
    May 2020
    Location
    HongKong
    Posts
    4
    Qt products
    Qt4 Qt5 Qt/Embedded

    Question Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    Quote Originally Posted by Uwe View Post
    QWidget does not offer to "erase" something - all you can do is to redraw from scratch. This is why QwtPlotDirectPainter is useful - it at least allows to draw on top of something existing.

    Uwe
    Another way to achieve the effect I want,and in this way, the CPU usage is also very small,but need to write a lot of code,use the most primitive QPainter , not as concise as the qwt.The code snippet is as follows:
    Qt Code:
    1. void Mywidget::paintEvent(QPaintEvent* event)
    2. {
    3. QPainter painter(this);
    4. painter.drawPixmap(0,0,m_gridPixmap);//paint grid backgroup pixmap
    5. painter.drawPixmap(0,0,m_curvePixmap);//paint curve pixmap on the top, and set QPainter::CompositionMode_Source mode when paint m_curvePixmap
    6. painter.end();
    7. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. void Mywidget::updateCurvePixmap()
    2. {
    3. QPainter painter;
    4. painter.begin(&m_curvePixmap);
    5. painter.setCompositionMode(QPainter::CompositionMode_Source);
    6.  
    7. //Calculate the current 12 refreshed area first,and fill transparent
    8. for(int i = 0; i < 12;i++)
    9. {
    10. QRect rect;//The calculation process is omitted here!!!
    11. painter.fillRect(rect,Qt::transparent);
    12.  
    13. //Plot newly added data points
    14. QPolygonF points;//The process of filling points is omitted!!!
    15. painter.drawPoints(points);
    16. }
    17. painter.end();
    18.  
    19. //At this point, the new data point is successfully partial updated on the m_curvePixmap,Partial refresh widget
    20. QRegion region;//save all need updated area
    21. for(int i = 0; i < 12;i++)
    22. {
    23. QRect rect;//The calculation process is omitted here!!!
    24. region += rect;
    25. }
    26. update(region );
    27. }
    To copy to clipboard, switch view to plain text mode 
    Refer to this example:https://doc.qt.io/qt-5/qtwidgets-pai...n-example.html,
    Used this class method:QPainter::setCompositionMode.

    In order to achieve the effect I want, is this the only way?
    Last edited by lockdown; 10th May 2020 at 16:19.

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

    Default Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    Guess what you mean by this code snippet is that you draw each curve to its own pixmap first and the plot is done finally by drawing the pixmaps.
    Then you would have only one drawPolyline call, when only one curve has changed.
    Of course the code as being posted is not even close to what needs to be done in reality - but the idea is understood.

    So your code will have a positive effect, when having several curves, that are updated on different intervals - but it won't help for a situation with one curve and many points.

    Uwe

  5. #5
    Join Date
    May 2020
    Location
    HongKong
    Posts
    4
    Qt products
    Qt4 Qt5 Qt/Embedded

    Default Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    Quote Originally Posted by Uwe View Post
    Guess what you mean by this code snippet is that you draw each curve to its own pixmap first and the plot is done finally by drawing the pixmaps.
    Then you would have only one drawPolyline call, when only one curve has changed.
    Of course the code as being posted is not even close to what needs to be done in reality - but the idea is understood.

    So your code will have a positive effect, when having several curves, that are updated on different intervals - but it won't help for a situation with one curve and many points.

    Uwe
    All curves plot in the only m_curvePixmap,I update the code snippet in the previous reply. All curves partial update at the same time ,update every 30ms.

    The original code looks too complicated,I just want to try to modify it as simple as the qwt.

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

    Default Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    Quote Originally Posted by lockdown View Post
    All curves plot in the only m_curvePixmap,....
    Then your code does not make any sense.

    Uwe

  7. #7
    Join Date
    May 2020
    Location
    HongKong
    Posts
    4
    Qt products
    Qt4 Qt5 Qt/Embedded

    Default Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    Quote Originally Posted by Uwe View Post
    Then your code does not make any sense.

    Uwe
    I have renewed.Thanks for the quick reply!

    What I don’t understand is why these my two methods are so different, why the CPU consumption is so different? Looks like they are doing the same partial refresh.

    Maybe as you said:QWidget does not offer to "erase" something - all you can do is to redraw from scratch.

  8. #8
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,247
    Thanked 860 Times in 809 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    Quote Originally Posted by lockdown View Post
    What I don’t understand is why these my two methods are so different, why the CPU consumption is so different?
    Hard to say what your code is doing as the code snippet does not show the real code.

    But the plot canvas is actually using a backing store ( a QPixmap ), that gets updated on certain operations like when the size of the canvas is changing or replot has been called.
    Beside that the content of the widget is always restored from this backing store only.

    So when calling QWidget::update( region ) only all what happens is, that the rectangles from region will be copied from the backing store of the canvas to another backing store - the default one every widgets has.

    Uwe

  9. #9
    Join Date
    Jun 2020
    Posts
    2
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: How to plot the real time data in qwtplot while erasing fixed-width old data?

    @lockdown Have you found a way to achieve this? because I am running in circles about the same issue and that would be really great help.

Similar Threads

  1. Replies: 2
    Last Post: 31st December 2019, 18:24
  2. Plot the graph for real time data
    By swinetha in forum Qwt
    Replies: 13
    Last Post: 1st August 2013, 04:56
  3. Replies: 2
    Last Post: 5th April 2013, 04:58
  4. real time data display
    By hammer256 in forum Qt Programming
    Replies: 13
    Last Post: 25th March 2013, 16:47
  5. Replies: 1
    Last Post: 27th April 2011, 10:35

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.