gnuplotで描画させるのが一番簡単だろうなーと思ったので,基本的な操作方法をまとめる.
gnuplotを立ち上げて
gnuplot> plot "-"と打つとデータの入力待ちになるので,
gnuplot> plot[-1:1][-1:1] "-" w p ps 7 pt 7 input data ('e' ends) > 0.0 0.0 input data ('e' ends) > eとかしてやると,データを手動で入力することができる.gnuplotを日常的に使っている人ならば直感的に,
gnuplot> plot[-1:1][-1:1] "-" w p ps 7 pt 7,"-" w p ps 7 pt 7 input data ('e' ends) > 0.5 0.0 input data ('e' ends) > e input data ('e' ends) > -0.5 0.0 input data ('e' ends) > eと二つ以上のデータ点を入力することができることに気がつくだろう.
結果は上図の様になる.つまり,cからgnuplotに上記のような命令でデータを入力してやれば,real time にデータを更新しながら描画することが可能になる.
(note:multiplotを利用するとデータ更新毎に再描画してしまうので,ちらつきの原因となる)
さて,ここからが本題.C言語からgnuplotに命令するため,ここではpopen関数をつかう.(多分やり方は色々有るはず)
FILE *gp; gp = popen("gnuplot", "w");でgnuplotにパイプを通すことができる.もちろんgnuplotのPATHが通ってなければならない.絶対PATHでも構わない. もし描画終了後にgnplotのウィンドウ画面が閉じるのが嫌であればgnuplotの起動オプション
gp = popen("gnuplot -persist", "w");を付けてやれば良い.
以下簡単なサンプル
#include <stdio.h> #include <stdlib.h> #include <tmath.h> #include <unistd.h> void gnuplot_config(FILE *gp); void plot2d(FILE *gp,const int num,const double *x,const double *y); void move(const int num, double const t, double *x, double *y); int main(void){ FILE *gp; //gp = popen("gnuplot -persist", "w"); /*プログラムが終了後GnuplotのWindowを閉じない*/ gp = popen("gnuplot", "w"); /*プログラムが終了後GnuplotのWindowを閉じる*/ gnuplot_config(gp); /* gnuplot configuration */ int i; // loop variable int step=100; int sample_num=10; double t; double dt=0.1; double x[sample_num], y[sample_num]; printf("途中で終了する場合は,Ctrl-C をターミナルに入力\n"); for (i=0;i<step;i++){ fprintf(gp,"set title 'animated-%d/%d' font 'Times, 20'\n",i,step); t = i*dt; move(sample_num, t, x, y); plot2d(gp,sample_num, x, y); usleep(30000); //指定された(マイクロ?)秒プログラムを停止させます (Unix system only) // while(getchar() != '\n'); /*Enter keyが入力されるまで,計算停止*/ } printf("計算終了\n"); return 0; } void gnuplot_config(FILE *gp) { /* fprintf(gp,"set terminal gif animate optimize size \n"); fprintf(gp,"set output 'anime.gif'\n"); */ /*アニメーションをgif動画として保存する場合は,上のコメントを解除*/ fprintf(gp,"set xrange [-1.5:1.5]\n"); fprintf(gp,"set yrange [-1.5:1.5]\n"); fprintf(gp,"unset tics\n"); // fprintf(gp,"set xtics 0.5\n"); // fprintf(gp,"set ytics 0.5\n"); // fprintf(gp,"set xlabel 'x' font 'Times, 20'\n"); // fprintf(gp,"set ylabel 'y' font 'Times, 20'\n"); // fprintf(gp,"set grid\n"); fprintf(gp,"set border 0\n"); fprintf(gp,"set size square\n"); } void plot2d(FILE *gp, const int num, const double *x, const double *y) { int i; fprintf(gp,"plot"); for(i=0;i<num;i++){ if (i!=num-1) fprintf(gp,"'-' with p pt 7 ps 10 lc %d tit '',", i);//plotデータの読み込み開始 else fprintf(gp,"'-' with p pt 7 ps 10 lc %d tit ''\n", i);//plotデータの読み込み開始 } for(i=0;i<num;i++){ fprintf(gp,"%f %f\n",x[i],y[i]); fprintf(gp,"e\n"); //データ書き込み終了を知らせる. } fflush(gp); //バッファーに溜まったデーターを吐き出す.これをしないと,real time animation にならない. } void move(const int num, const double t, double *x, double *y) { int i; double init_phase[num]; for (i =0;i<num;i++){ init_phase[i] = i*2.0*M_PI/num; } for (i=0;i<num;i++){ x[i] = cos(t+init_phase[i]); y[i] = sin(t+init_phase[i]); } }計算結果はこんな感じに
HTMLって鍵括弧(<>)を&lt &gtって入力しないと行けないのか・・・プログラムコピペする時めんどくさいな・・・
今回はspleep関数使ってるけど,FPSとかってどうやって制御すれば良いんだ?
0 件のコメント:
コメントを投稿