QCustomPlotを使用してアニメーションチャートを作成する

画像



さまざまな分析問題を解決する場合、関数が時間に依存するリアルタイムのグラフ作成が必要になる場合があります。 この記事では、QCustomPlotを使用してQtでグラフをアニメーション化する問題を解決した経験を共有します。



使用済みツール





QCustomPlotについて簡単に説明します



グラフは、replot()メソッドを呼び出した後に(手動で、またはイベントがトリガーされたときに)描画されます。 レンダリングの場合、このウィジェットには、引数の値(x)とこの時点での関数の値(y)を含む2つのデータ配列が必要です。



チャート作成



公式でもっと見る QCustomPlotのチュートリアル

説明のために、引数がミリ秒単位の時間になるグラフを作成します。



QVector<double> x(100), y(100); for(int i = 0; i < 100; i++) { x[i] = 100*i y[i] = x[i]; }
      
      





後でアニメーション化するグラフを作成します。



 customplot->addGraph();
      
      





そして、入力データでベクトルを与えます:



 customplot->graph(0)->setData(x,y);
      
      





グラフの可視部分をxで(0; 10000)、yで(0; 10000)に設定し、グラフ全体が見えるようにします。



 customplot->xAxis->setRange(0, 10000); customplot->yAxis->setRange(0, 10000);
      
      





replotの呼び出しは残ります。



 customplot->replot();
      
      





これは私たちのスケジュールのように見えるはずです




できた! 一貫して直接「描画」するためだけに残っています。



アニメーション



アニメーションの場合、タイムアウト()を通知し、次の値を描画する関数を呼び出すQTimerを作成します。

また、レンダリングの開始からの経過時間に関するデータを格納するグローバル変数と、x、yを格納するための2つの追加配列が必要です。その目的を以下に示します。



 int TimeElapsed = 0; QVector<double> x2, y2; ... QTimer* playBackTimer = new QTimer(this); //   connect(playBackTimer, SIGNAL(timeout()), this, SLOT(PlaybackStep())); //    PlaybackStep()
      
      





QTimerは、dミリ秒後にQTimer-> start(int d)を呼び出した後、timeout()を通知し、その後QTimer-> stop()で停止するまで再起動するように動作します。 かなり滑らかな画像を得るには、d = 50(20 fps)に設定します。



 playBackTimer->start(50);
      
      





そして、タイマーからイベント処理関数の実装に直接渡します。



 void PlaybackStep() { TimeElapsed+=50; // 50 -    ( ) for(int i = 0; i < x.size(); i++) { if(TimeElapsed >= x[i]) { x2.push_back(x[i]); y2.push_back(y[i]); x.pop_front(); y.pop_front(); i = 0; //       "",   pop_front()   //  . i = 0   ,   " " } } customplot->graph(0)->setData(x2, y2); //end of playback check if(x.size() == 0) playBackTimer->stop(); // customplot->replot(); }
      
      





アニメーションメカニズムでは、タイマーからの各信号で、経過したミリ秒数を格納する変数の値以下の要素を取得します。



また、入力データの配列全体を毎回実行しないように、それらを新しいx2、y2配列に追加した後、pop_front()を使用して削除します。



各「フレーム」で、setData(x2、y2)を呼び出してグラフデータを更新し、qcustomplotの再描画も要求します。



レディアニメーションの例


この例は、開発中のプロジェクトから取られています。



replot()は1秒間に20回以上呼び出すのに十分な高価な関数であるように思えますが、プロットのレンダリング速度を測定しました。 20個から30個の値が画面上にある10個のスケジュールがある場合、replot()の実行時間は1ミリ秒を超えず、PlaybackStep関数全体に費やされる時間は10ミリ秒未満であり、理論的には〜100 fpsの頻度でスケジュールを更新できます。



PSこの例は、グラフ関数への引数が時間であるリアルタイムレンダリングに適しています。 ただし、時間依存性のない他のグラフのレンダリングにも同じメカニズムを適用できます。



UPD。 アニメーショングラフ(gif)の例を追加しました。



All Articles