[Windows] C言語でgnuplotを動かしてアニメーションを作る

このページはそのうち完成させます。上のgifはパワーポイントに貼ってプレゼンでも使えます。


点が動くプログラム


 gnuplotでアニメーションをする方法は色々あるけれど、上の図のように沢山の点が何回も動く場合は

1. 各点の位置情報をテキストファイルに保存。
2. ファイルをgnuplotで読み込んで一気に表示。
 を繰り返すのが早い。

#define _CRT_SECURE_NO_WARNINGS	// visual studioを使うときは#include より前にかく

#include <stdio.h>
#include <windows.h>	// for Sleep
#include <winbase.h>

#define GNUPLOT_PATH "C:/gnuplot/bin/gnuplot.exe"	// gnuplot.exeの場所

void main(){
	FILE *gp, *fp;
	int i,nod;
	// 初期配置
	double X[9][2] = {{0.0,0.0},{0.1,0.0},{0.2,0.0},
			{0.0,0.1},{0.1,0.1},{0.2,0.1},
			{0.0,0.2},{0.1,0.2},{0.2,0.2}};

	// Animation settings
	// gnuplotを動かすためのコマンド
	if ((gp = _popen(GNUPLOT_PATH, "w")) == NULL) {
		printf("gnuplot open error!!\n");
		exit(EXIT_FAILURE);	// エラーの場合は通常、異常終了する
	}

	// Gnuplot操作
	fprintf(gp, "set size square\n");		// figureを正方形に
	fprintf(gp, "set xrange [%f:%f]\n",0.0,3.0); // 範囲の指定
	fprintf(gp, "set yrange [%f:%f]\n",0.0,3.0);
	fprintf(gp, "unset key\n");		// 凡例を表示しない

	// 点の位置を動かす
	for(i=0;i<30;i++){
		fp = fopen("move_point.dat", "w");	// "上書き"モードでファイルを開く。
		fprintf(gp, "set title 't = %d'\n",i); // タイトルを設定
		for(nod=0;nod<9;nod++){			// 9個の点の位置をファイルに保存
			fprintf(fp,"%f %f\n",X[nod][0],X[nod][1]);	// 点nodの位置をファイルに書き込み
			X[nod][0] += 0.1; X[nod][1] += 0.1;		// 点nodの位置を0.1ずつずらす
		}
		fprintf(gp,"plot 'move_point.dat' w p pt 7 ps 0.5\n");	// gnuplotで点を描く
		fclose(fp);	// 位置を書いているファイルを閉じる
		fflush(gp);	// バッファに格納されているデータを吐き出す(必須)
		Sleep(100);	// なくてもよい。
	}
	system("pause");
	
	fprintf(gp, "exit\n"); // gnuplotの終了
	fflush(gp); // バッファに格納されているデータを吐き出す(必須)
	_pclose(gp);
}

 上の解説。
 'move_point.dat'というファイルに各点の位置を書き換えながら保存していく。  初期配置の場合、'move_point.dat'の中身は  

0.0 0.0
0.1 0.0
0.2 0.0
0.0 0.1
0.1 0.1
0.2 0.1
0.0 0.2
0.1 0.2
0.2 0.2
 となっている。点の位置(Xの値)を動かしたら、このファイルを書き換える。追記ではないことに注意。
 つまり、'move_point.dat'の中身は、必ず9行x2列(点の数x次元数)となっている。
  これを、gnuplotで読み込んで描かせる。コマンドは
plot 'move_point.dat' w p pt 7 ps 0.5  # pointsizeは50%
 となる。
 これを繰り返すことで、アニメーションになる。

(推奨)アニメーションをgifファイルで保存

上で作ったアニメーションを、そのままgifファイルとして保存する方法を紹介する。手順としては、

 1.gnuplotの出力ターミナルをanimateオプションを付けたgifとし、
 2.'xxxx.gif'というファイル名で保存する
というだけである。

上の点が動くプログラムで作ったアニメーションをgif形式で保存しよう。
上のプログラム内の、// Gnuplot操作 の直後に、次の2行を追記する。

 fprintf(gp, "set term gif animate\n");	// 出力ターミナルをgif, animateオプションを付ける
 fprintf(gp, "set output 'test.gif'\n");	// 出力ファイル名。

そしてプログラムを実行すると、しばらくしてプログラムは終了し、ソースファイルと同じフォルダに'test.gif'ファイルができている。完成である。

  注意すべきは、実際にプログラム上でアニメーションの動作を確認しながらgifファイルを作ることはできないことである。
 そのようにしたい場合は、プログラムを動かしながらアニメーションを確認する用のターミナル(*gp2など)を別途用意し、
 gif保存用のターミナルと同時に呼び出して、それぞれに指示を与えるプログラムを組む必要がある。例えばこんな感じ(Cファイル)
  また、上記ループ内の

Sleep(100);	// なくてもよい。
 はなくてもよくない。通常、必要である。
 この値が小さすぎると、PCのループ操作にgnuplotの描写がついていけないため、変なgifができる。
 適当な値を指定する必要があることに注意すること。

(非推奨)アニメーションをgifファイルで保存2

 アニメーションをgifファイルアニメーションとして保存する2つ目の方法は、

  1. 各状態の画像をgifファイルで保存。30ステップ分なら30枚。
  2. これらのgifファイルをgiamdでつなげて一つのgifアニメーションにする。
 という手順をふむ。
 つまり、アニメーションするコマ数の枚数分、画像をいちいち保存しておき、別ソフトで連結するという手法である。
 状況によっては山ほどの画像枚数を必要とするのであまり推奨しない。

 具体的には、上のアニメーションのプログラムの、Sleep(100)の一つ上の行に、

  fprintf(gp,"name='move%02d'\n load 'savegif.gp'\n",i+1);
 を追記する。savegif.gpの中身は、
 if (exists("name")){ 
  filename = sprintf("%s.gif",name);
  set terminal gif enhanced # terminalをgifに変更
  set output filename       # ファイル名で保存場所を指定可能
  pause 1                   # 1秒待つ。PCが高速の場合は処理を待つために必要。
  replot                    # 必要
  set output                # 必要。これで、先ほど作ったgifがcloseされる。
  set terminal wxt          # ターミナルをもとに戻す(wxtでなくても良い)
 }else{
  pause -1 "nameを指定して下さい。name='ファイル名'"
}
 とし、適当なフォルダに置いておく。上のコマンドの場合は、.cがあるフォルダと同じ場所。

Back