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 件のコメント:
コメントを投稿