Results 1 to 7 of 7

Thread: replot() performance

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Feb 2007
    Posts
    63
    Qt products
    Qt3
    Platforms
    Unix/X11

    Default replot() performance

    Hi everyone,
    i know that this has been previously discussed in the form. I'll start by explaining my requirement.
    I have drawn 4 plots( each with approx 20000 points) on the canvas. Now i am calling a timer function in which i am reading data in the real time and moving a vertical Bar along with the label to show the instantaneous value of the vertical bar. For this i am doing a replot() after every movement of the vertical bar in the timer function. The plots can also be zoomed. Now i have noticed that speed of the vertical bar is slow when there are 4 plots in the canvas compared to when there is one plot. And i know that this behavior is because replot() function will plot all the points in the canvas every time it is called.
    I have gone through some previous posts and found that pixmap caching, bounding rect, etc may be used to improve the performance. However i am new to this and don't know as how to implement them. can somebody help me in this case?
    Also is there any example or similar application which can be shared ?

    Regards
    Raghav

  2. #2
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: replot() performance

    You should not have to use replot.
    Your vertical bar can easily be a widget (parented to the canvas).
    This way you get maximum performance with minimum effort.

    Another simple alternative would be to update curve to replot only invalidated part of itself, instead of whole thing.

    Here's example how you deal with the widget:
    Qt Code:
    1. Animatron::Animatron( QWidget* p ) // parent has to be the canvas
    2. :
    3. QWidget( p ),
    4. moveTimer( new QTimer( this ) )
    5. {
    6. Q_ASSERT( p );
    7.  
    8. this->setFixedWidth( 4 );
    9.  
    10. connect( this->moveTimer, SIGNAL( timeout() ), this, SLOT( moveMe() ) );
    11. this->moveTimer->start( 50 );
    12.  
    13. p->installEventFilter( this );
    14.  
    15. this->setStyleSheet( "background: red" );
    16. }
    17.  
    18. bool Animatron::eventFilter( QObject* o, QEvent* e )
    19. {
    20. switch( e->type() )
    21. {
    22. case QEvent::Resize:
    23. qDebug() << this->parentWidget()->size();
    24. this->setFixedHeight( this->parentWidget()->height() );
    25. this->move( 0, 0 );
    26. break;
    27. default:
    28. break;
    29. }
    30.  
    31. return QWidget::eventFilter( o, e );
    32. }
    33.  
    34. void Animatron::paintEvent( QPaintEvent* )
    35. {
    36. QPainter p( this );
    37.  
    38. p.fillRect( this->rect(), Qt::red );
    39. }
    40.  
    41. void Animatron::moveMe( void )
    42. {
    43. int x = this->pos().x() + this->width();
    44. if( x > this->parentWidget()->width() )
    45. {
    46. x = 0;
    47. }
    48. this->move( x, 0 );
    49. }
    To copy to clipboard, switch view to plain text mode 
    You need to add to it a way of getting any data if you want it to be displayed somewhere, but that's a small problem.

  3. #3
    Join Date
    Feb 2007
    Posts
    63
    Qt products
    Qt3
    Platforms
    Unix/X11

    Default Re: replot() performance

    Thanx for the reply spitfire,
    I tried your code it seems to have improved the performance.
    But now i am facing another problem.
    I am moving the Vertical bar in x direction. However the x value is taken from the left edge of the canvas, and it is not slaved to the x axis set by me. As a result when i zoom or pan the graph, the vertical bar still remains in its position.
    Also in my original application i am displaying the instantaneously value of the plot being crossed by the vertical bar (using QwtText and QwtMarker). Can i get the same through code. I am attaching a screen shot of my original application (which uses replot()) for more clarity.

    Regards
    Raghav
    Screenshot-1.jpg

  4. #4
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: replot() performance

    Of course you can.

    I assume you know how to get the value (as you already displaying it on the plot) of the point you're interested in.
    You need to take this value and translate it to canvas coordinates (plot->transform( QwtPlot::xBottom, world_x_value ) ).
    From that you will get X value of where the vertical line should be.
    To get where the little circle on the vertical line should be you do the same for Y value of the point (plot->transform( QwtPlot::yLeft, world_y_value ) ).

    And that's all you need.
    To display it, simply make the vertical line widget wider (as wide as the circle you want to draw), draw the vertical line as wide as you want in the middle of the widget and add the circle afterwards.
    To display a text, simply create QLabel and parent it to the vertical line widget (set Y position accordingly to where you draw the circle).

    Actually, I have something similar done for someone else, it shoud answer all your questions and do what you want after slight modification (in here the line is following the mouse):

    Qt Code:
    1. // definition
    2. #ifndef LINEMARKER_H
    3. #define LINEMARKER_H
    4.  
    5. #include <QWidget>
    6.  
    7.  
    8. /*! \brief Widget representing current cursor position on the curve.
    9.  
    10.   \note
    11.   Marker <b>is not</b> and independent object.\n
    12.   It requires QwtPlotCurve and data vector to work efficiently.\n
    13.  
    14.   When enabled it indicates current mouse position on the curve. It follows curve's Y values for mouse X position.\n
    15.  
    16.   \note
    17.   Life span of the marker is controlled by client code but it is parented to the canvas so it will get deleted if canvas is destroyed.\n
    18.  
    19.   Exapmle use:
    20.   \code
    21.   QVector< double > x_values;
    22.   QVector< double > y_values;
    23.   QwtPlotCurve* curve = new QwtPlotCurve();
    24.   curve->setSamples( x_values, y_values, qMin( x_values.size(), y_values.size() ) );
    25.   Marker* m = new Marker( *curve, x_values );
    26.   m->attach( plot->canvas() );
    27.   m->setEnabled( true );
    28.   \endcode
    29.  */
    30. class LineMarker : public QWidget
    31. {
    32. Q_OBJECT
    33. public:
    34. /*! \brief Constructor.
    35.   */
    36. explicit LineMarker( const QwtPlotCurve& curve, const QVector< double >& v );
    37.  
    38. /*! \brief Overloaded Qt function.
    39.  
    40.   It calls move( const QPoint& );
    41.   */
    42. void move( int x, int y );
    43.  
    44. /*! \brief Overloaded Qt function.
    45.  
    46.   This version centres the widget horizontally.
    47.   */
    48. void move( const QPoint& );
    49.  
    50. public slots:
    51. /*! \brief Snaps marker to point on the curve lying along current cursor X axis.
    52.   */
    53. void snapToCursor( void );
    54.  
    55. /*! \brief Reimplemented Qt function.
    56.  
    57.   In this implementation whenever Marker is enabled it is also shown.\n
    58.   If it is disabled it gets hidden.\n
    59.  
    60.   \param enabled Flag indicating if Marker should be enabled or disabled.
    61.   */
    62. void setEnabled( bool enabled );
    63.  
    64. protected:
    65. /*! \brief Overloaded Qt function.
    66.  
    67.   Draws marker's shape.
    68.  
    69.   \param e Event.
    70.   */
    71. void paintEvent( QPaintEvent* e );
    72.  
    73. /*! \brief Overloaded Qt function.
    74.  
    75.   Handles events incoming from QwtPlotCanvas:\n
    76.   - QEvent::MouseMove: marker is moved along curve according to current mouse x coordinate,\n
    77.   - QEvent::Resize: Changes fixed height of the marker to match height of the canvas,\n
    78.  
    79.   \param o Object triggering the event.
    80.   \param e Event.
    81.   \return true if event is to be filtered out (i.e. stop it being handled further), false otherwise.
    82.   */
    83. bool eventFilter( QObject* o, QEvent* e );
    84.  
    85. public:
    86. /*! \brief Property indicating if Marker is attached to a Canvas or not.
    87.  
    88.   \return True if it's currently attached to a Canvas, false otherwise.
    89.   */
    90. bool isAttached( void );
    91.  
    92. /*! \brief Attaches Marker to a Canvas.
    93.  
    94.   When Marker is attached to a Canvas it installs an EventFilter on in
    95.   to intercept mouse and key events.\n
    96.   \n
    97.   If Marker is already attached it will be detached from current canvas
    98.   and attached to a new one.\n
    99.   \n
    100.   If new cavans is the same as currently attached one this function does nothing.\n
    101.  
    102.   \param canvas Canvas for Marker to attach to.
    103.   */
    104. void attach( QwtPlotCanvas* canvas );
    105.  
    106. /*! \brief Detaches Marker from current canvas.
    107.  
    108.   By detaching Marker removes EventFilter from the Canvas and will no longer
    109.   receive any mouse or keyboard events.\n
    110.   \n
    111.   If tracker is not attached this function does nothing.\n
    112.   */
    113. void detach( void );
    114.  
    115. private:
    116. /*! \brief Given X in canvas coordinates it snaps to curve Y at that X.
    117.  
    118.   Finds curve X and Y value for canvas X value and moves tracker there.
    119.  
    120.   \param canvasX X in canvas coordinates.
    121.   */
    122. void snapToCurveAt( int canvasX );
    123.  
    124. /*! \brief Returns current position of the cursor in canvas coordinates.
    125.  
    126.   \return Cursor position translated to canvas coodrinates.
    127.   */
    128. QPoint cursorPos( void ) const;
    129.  
    130. /*! \brief Finds closest point in curve data to the passed world coordinate.
    131.  
    132.   World coordinate value has to be for the X axis as only that axis is searched.
    133.  
    134.   \return Index of the point in the dataset.
    135.   */
    136. int findIndex( double worldX ) const;
    137.  
    138. QwtPlotCanvas* canvas; //!< convenience cache
    139. const QwtPlotCurve& curve; //!< convenience cache
    140. int elipsePosY; //!< position where small ellipse will be drawn on the line (Y only).
    141. };
    142.  
    143. #endif // LINEMARKER_H
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. // implementation
    2.  
    3. #include "linemarker.h"
    4.  
    5. #include <qwt_plot.h>
    6. #include <qwt_plot_curve.h>
    7. #include <qwt_plot_canvas.h>
    8.  
    9. #include <QPainter>
    10. #include <QEvent>
    11. #include <QMouseEvent>
    12.  
    13. LineMarker::LineMarker( const QwtPlotCurve& curve, const QVector< double >& v )
    14. :
    15. QWidget( NULL ),
    16. canvas( NULL ),
    17. curve( curve ),
    18. elipsePosY( -1 )
    19. {
    20. this->setAttribute( Qt::WA_TransparentForMouseEvents );
    21. this->setFixedWidth( 10 ); // TODO: magic number
    22.  
    23. QPalette p = this->palette();
    24. p.setColor( QPalette::Foreground, Qt::black );
    25. this->setPalette( p );
    26. }
    27.  
    28. void LineMarker::move( int x, int y )
    29. {
    30. this->move( QPoint( x, y ) );
    31. }
    32.  
    33. void LineMarker::move( const QPoint& p )
    34. {
    35. QWidget::move( p.x() - this->width()/2, p.y() );
    36. }
    37.  
    38. void LineMarker::snapToCursor( void )
    39. {
    40. if( this->isEnabled() )
    41. {
    42. this->snapToCurveAt( this->cursorPos().x() );
    43. }
    44. }
    45.  
    46. void LineMarker::setEnabled( bool enabled )
    47. {
    48. this->setVisible( enabled );
    49. QWidget::setEnabled( enabled );
    50. }
    51.  
    52. void LineMarker::paintEvent( QPaintEvent* e )
    53. {
    54. int middle = this->width()/2;
    55. QPainter p( this );
    56. p.setBrush( Qt::NoBrush );
    57. p.setPen( this->palette().foreground().color() );
    58.  
    59. p.drawLine( middle, 0, middle, this->height() );
    60.  
    61. p.setBrush( Qt::white );
    62. p.drawEllipse( QPoint( middle, this->elipsePosY ), middle-1, middle-1 );
    63. }
    64.  
    65. bool LineMarker::eventFilter( QObject* o, QEvent* e )
    66. {
    67. bool ret = false;
    68. if( o == this->parent() )
    69. {
    70. switch( e->type() )
    71. {
    72. case QEvent::MouseMove:
    73. {
    74. QMouseEvent* event = static_cast< QMouseEvent* >( e );
    75. QPoint p = event->pos();
    76.  
    77. this->snapToCurveAt( p.x() );
    78. break;
    79. }
    80. case QEvent::Resize:
    81. this->setFixedHeight( this->parentWidget()->height() );
    82. break;
    83. default:
    84. break;
    85. }
    86. }
    87. return ret;
    88. }
    89.  
    90. bool LineMarker::isAttached( void )
    91. {
    92. return this->canvas;
    93. }
    94.  
    95. void LineMarker::attach( QwtPlotCanvas* canvas )
    96. {
    97. if( this->canvas == canvas )
    98. {
    99. return;
    100. }
    101.  
    102. if( this->isAttached() )
    103. {
    104. this->detach();
    105. }
    106.  
    107. this->canvas = canvas;
    108. this->setParent( this->canvas );
    109. this->canvas->installEventFilter( this );
    110. }
    111.  
    112. void LineMarker::detach( void )
    113. {
    114. if( this->isAttached() )
    115. {
    116. this->canvas->removeEventFilter( this );
    117. this->setParent( NULL );
    118. this->canvas = NULL;
    119. }
    120. }
    121.  
    122. void LineMarker::snapToCurveAt( int canvasX )
    123. {
    124. QwtPlot* plot = this->canvas->plot();
    125.  
    126. int index = this->findIndex( plot->invTransform( QwtPlot::xBottom, canvasX ) );
    127.  
    128. QPointF sample = this->curve.sample( index );
    129.  
    130. QPoint newPos( plot->transform( QwtPlot::xBottom, sample.x() ), 0 );
    131.  
    132. this->elipsePosY = plot->transform( QwtPlot::yLeft, sample.y() );
    133.  
    134. this->move( newPos );
    135. }
    136.  
    137. QPoint LineMarker::cursorPos( void ) const
    138. {
    139. return this->canvas->mapFromGlobal( QCursor::pos() );
    140. }
    141.  
    142. int LineMarker::findIndex( double worldX ) const
    143. {
    144. int idx = 0;
    145.  
    146. int low = 0;
    147. int high = this->curve.dataSize() - 1;
    148.  
    149. while( true )
    150. {
    151. int size = high-low;
    152. int mid = low+size/2;
    153. double mid_value = this->curve.sample( mid ).x();
    154.  
    155. if( size <= 1 || worldX == mid_value )
    156. {
    157. idx = mid;
    158. break;
    159. }
    160. else
    161. {
    162. if( worldX < mid_value )
    163. {
    164. high -= size/2;
    165. }
    166. else
    167. {
    168. low += size/2;
    169. }
    170. }
    171. }
    172.  
    173. return idx;
    174. }
    To copy to clipboard, switch view to plain text mode 
    Remember about credits if you end up using it publicly
    demo.png

  5. #5
    Join Date
    Feb 2007
    Posts
    63
    Qt products
    Qt3
    Platforms
    Unix/X11

    Default Re: replot() performance

    Thanx a lot spitfire,
    its great help
    The vertical marker is now slaved to the x axis. And as suggested by you i am able to add a circle , the position of which can be varied using x and y values.
    However there is some problem regarding the size of the circle. The maximum size of the circle can be equal to the width of the Vertical line and to make circle noticeable i have to increase the size of the vertical bar. As a result the vertical bar becomes wider and hides the significant portion of the graph. when i try to just increase the size of the circle without increasing the size of vertical bar, the circle is clipped and only a portion of it is visible on the bar.
    I need to display a thin vertical bar with a noticeable circle as shown in your demo pic.
    Kindly suggest how to achieve this.

    Regards
    Raghav

  6. #6
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: replot() performance

    Look at paintEvent() in my example.
    You get thin line by drawing a line from top to bottom (not by setting a background or anything).
    Then you draw a circle using full width of the widget.
    This way you can adjust size of the circle by changing width of the widget.

    Qt Code:
    1. void LineMarker::paintEvent( QPaintEvent* e )
    2. {
    3. int middle = this->width()/2;
    4. QPainter p( this );
    5. p.setBrush( Qt::NoBrush );
    6. p.setPen( this->palette().foreground().color() ); // change pen width here if you want wider line
    7.  
    8. p.drawLine( middle, 0, middle, this->height() ); // here you draw the thin lne using default pen (about 1px wide)
    9.  
    10. p.setBrush( Qt::white );
    11. p.drawEllipse( QPoint( middle, this->elipsePosY ), middle-1, middle-1 ); // here you draw the circle with radius = width/2
    12. }
    To copy to clipboard, switch view to plain text mode 

  7. #7
    Join Date
    Feb 2007
    Posts
    63
    Qt products
    Qt3
    Platforms
    Unix/X11

    Default Re: replot() performance

    Thanx for the help.
    It worked

    Raghav

Similar Threads

  1. Replot dinamic curve.
    By Zikoel in forum Qwt
    Replies: 2
    Last Post: 24th October 2011, 09:50
  2. replot in Qwt Zoomer
    By ruzik in forum Qwt
    Replies: 2
    Last Post: 22nd September 2011, 18:42
  3. how to get zoomer to replot
    By kja in forum Newbie
    Replies: 3
    Last Post: 17th November 2010, 07:15
  4. how to accelerate the replot?
    By rambo83 in forum Qwt
    Replies: 6
    Last Post: 17th March 2010, 11:11
  5. how to speed up the replot?
    By rambo83 in forum Qwt
    Replies: 4
    Last Post: 16th December 2009, 11:51

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
  •  
Qt is a trademark of The Qt Company.