[ 前へ | 目次 | 次へ ]
Japanese English
ダウンロード
PC (※スマートフォンでは動きません) でダウンロードし、ZIPファイルを右クリックメニューから展開して、できたフォルダ内の「 VCSSL.bat(バッチファイル) 」をダブルクリックすると起動します。 Linux等では「 VCSSL.jar 」をコマンド実行してください。
» 詳しい使用方法や、エラーで展開できない際の対応方法などはこちら

GraphFileAnimator2D - 連番ファイルから2Dグラフをアニメーション描画するツール

このプログラム「 GraphFileAnimator2D 」は、 フォルダ内の連番データファイルを読み込み、2次元グラフを連続で高速描画して、 アニメーションさせるツールです。 グラフを連番の画像ファイルに保存する事もできます。

» 3次元グラフ版はこちら!

使用方法

ダウンロードと展開(解凍)

まず、PC(スマホは未対応)で上の画面の「 ダウンロード 」ボタンを押してください。 するとZIP形式で圧縮されたファイルがダウンロードされます。

Windows をご使用の方は、ここでまずZIPファイルを右クリックし、「プロパティ」を選んで開かれる画面で、 下の方にあるセキュリティ項目の「許可する」にチェックを入れて「OK」で閉じてください。 これを行わないと、ZIP展開やソフト起動時に、警告メッセージが出て展開完了/起動できない場合があります。

その後、ZIPファイルを右クリックして「すべて展開」や「ここに展開」などで展開(解凍)してください。 展開が成功すると、ZIPファイルと同じ名前のフォルダができ、その中にZIPファイルの中身が入っています。

» 展開がエラーで止まってしまう場合や、ファイル名が文字化けしてしまう場合は…

プログラムの起動

Windows をご使用の場合

上記でZIPファイルを展開したフォルダ内にある、以下のバッチファイルをダブルクリック実行してください:

VCSSL__ダブルクリックでプログラム実行.bat

もしプログラムを書き変えながら使いたい場合は、代わりに「 VCSSL_Editor__プログラム編集はこちら.bat 」を実行してください。

正常に起動できると、初回のみ、Java実行環境を入手するか等を尋ねられるので、適時答えて済ませると、プログラムが起動します。 2回目以降はすぐに起動します。

» うまく起動できずにエラーになってしまう場合は…

Linux 等をご使用の場合

ZIPファイルを展開したフォルダ内へコマンドライン端末で cd して、以下の通り入力して実行してください:

java -jar VCSSL.jar
(プログラムの内容を書き変えながら使いたい場合は、代わりに VCSSL_Editor.jar を実行)

» javaコマンドが使用できない等のエラーが表示される場合は…

起動後

連番データファイルの読み込み先フォルダの指定

起動すると、まず連番データファイルを読み込むフォルダを指定するかどうか尋ねられます:

フォルダ指定画面

もし既に、プロットしたい連番ファイルを格納したフォルダを用意できている場合は、ここで「はい」を選択します。 「いいえ」を選択すると、プログラムと同じ場所にある「 input 」という名前のフォルダが、読み込み先フォルダになります。 この中には最初からサンプルファイルが格納されているため、 とりあえず初回は「いいえ」を選択しましょう。

ファイル名と拡張子の入力

続いて、ファイル名と拡張子を尋ねられるので、それぞれ入力してください:

ファイル名入力画面

なお、ファイル名は、連番の番号を除いた部分のみを入力します(下図参照)。

入力ファイル名と拡張子

これも、標準ではサンプルコードの内容があらかじめ入力されているため、 とりあえず初回はそのまま「OK」を押して次に進みましょう。

※「 拡張子なんて見た事ないけど…? 」という方は…
最近の多くのPCでは、拡張子は標準では表示されないように設定されています。 表示するには、「 拡張子 表示 」などのキーワードでWeb検索してみてください。 なお、たまに本当に拡張子の無いファイルも存在します。その場合は拡張子の指定内容を空にして「OK」を押してください。

連番ファイルの番号の検索(自動)

すると、読み込みフォルダ内にある連番ファイルが検索され、開始番号と終了番号が自動で判断されます。

ファイル番号検索の結果

ここでは特に何もする必要はなく、勝手に次に進みます。

画面の起動

いよいよ画面が起動します。合計で3つのウィンドウが立ち上がります。 左がグラフのプロット範囲やアニメーション速度などの入力画面、右上がアニメーション操作画面、 そして右下がグラフ画面です。

入力画面(左)とアニメーション操作画面(右上)とグラフ画面(右下)
※ 画面のデザインや項目名などは、バージョンにより多少異なる場合があります。

アニメーションの再生/停止

アニメーション操作画面の「 PLAY 」ボタンを押すと、 連番ファイルが次々とグラフに描画されて、アニメーションとして再生されます。

アニメーション中は、「 PLAY 」ボタンは表示が変わって「 STOP 」ボタンになり、押すとアニメーションが一時停止します。 アニメーション停止中は、ボタン横のスライダーで、時間を手動で自由に動かす事ができます。

プロットオプションの選択やその他の設定など(任意)

グラフ画面のメニューバーから「 オプション 」をクリックし、プロットオプションを自由に選択できます。 下図のように色々なオプションが選べます(※下図で描画しているデータは、今回のサンプルとは別のものです)。

プロットオプション

メニューバーからは、他にも色々な設定を行えます。 設定は、「ファイル」 > 「設定の保存」メニューから保存できます。

このプログラムのグラフソフトを単体で使用したい場合は…
このプログラムで起動されるグラフ画面は、 「 リニアングラフ2D( RINEARN Graph 2D ) 」というデータ解析用のグラフソフトで、 単体でも入手・利用できます。操作感などが気に入った方は、ぜひご利用ください。

グラフを連番の画像ファイルに保存

アニメーションの各コマのグラフを、連番の画像ファイルに保存したい場合は、入力画面の「 画像保存 」ボタンを押してください。 標準では「 output 」フォルダ内に保存されます。保存先フォルダを変えたい場合は、「 画像保存 」ボタンの下にある「 選択 」ボタンでフォルダを選択してください。 なお、画像形式はPNGで保存されます。

出力される連番の画像ファイルは、GIMPなどの画像編集ソフトでGIFアニメーションに変換したり、その他ソフトで動画形式のファイルなどに変換する事ができます。 詳細は「 連番画像   動画 」などのキーワードでWeb検索してみてください。

または、このコーナーの以下のページで、連番画像をそのままアニメーションとして再生するツールも公開しています。併せてご利用ください:

連番画像をアニメーション再生する簡易ツール
フォルダ内の連番画像ファイルを、動画への変換不要で、そのままアニメーションとして再生できる簡易ツールです。

読み込むデータファイルの書式

このツールは、単純にデータファイルを1枚読んではグラフを描いて…を高速にくり返すだけの仕組みなので、 個々のデータファイルの書式は、普通にリニアングラフ2Dで1枚のグラフを描く場合と同じです。 従って書式の詳細は、リニアングラフ2Dの取扱説明書の、以下のページをご参照ください:

また、特にプログラムでデータファイルを作成したい場合などは、VCSSLスタートアップガイドの以下の回も参考になるかもしれません。

以下では、簡単に書式の概要を説明します。

1行の中での数値の区切りは、カンマ記号「 , 」か空白(タブでもOK)で

データファイルには、すぐ後に述べるように、1行に複数の数値を記述する必要があります。 この区切りには、カンマ記号「 , 」と空白(タブでもOK)のどちらかを使用できます。 なお、空白は複数連続させても構いません。

- 例:カンマ記号で区切る場合 -
1.0,2.0
...

- 例:空白で区切る場合 -
1.0    2.0
...

以下では、Webページ上で見やすいため、空白を区切りに使用します。

単系列のデータ

基本となるのが、単系列のデータのグラフです。 これは要するに、1色で、線プロットなら線1本のグラフの事を指します。

これは本当に単純で、データファイルの1行に1点ずつ座標値、つまりX値とY値を記述していきます。

x1    y1
x2    y2
x3    y3

※ x1 などの箇所には、実際には数値を記載してください。

上の例では、1行目に点1の座標値 (x1,y1) が、2行目に点2の座標値 (x2,y2) が、そして3行目に点3の座標値 (x3,y3) が記載されています。

このようなデータファイルを読み込むと、点プロット時には、記載した全ての座標値の位置に点が描画されます。 線プロット時には、各点が線で繋がれます。

複数系列のデータ

続いて複数系列のデータの書式です。 これは、複数の色でデータを色分けしたい場合に使用します。 線プロットを使用している場合は、それぞれ色ごとに別の線が引かれます。

複数プロットのデータ書式も先ほどと基本的には同じで、1行に1点ずつの座標値を書いていきます。 ただし、系列の区切りの箇所に、空白行を挟みます:

x11    y11
x12    y12

x1N    y1N
(空白行)
x21    y21
x22    y22

x2M    y2M

上の例では、1行目からN行目までが系列1のデータで、デフォルトでは赤色で描画されます。 そこから空白行を挟んでM行が系列2のデータで、デフォルトでは青色で描画されます。

系列の色については、グラフ上部のメニューバーから「 編集 」 > 「 色の設定 」メニューを選択すると設定できます。

コード解説

コード全体

このプログラムのコードはVCSSLで記述されています。 VCSSLはC言語系のシンプルな文法を持っているので、C系の言語に触れられた事のある方なら、 コメントを参考にしながらコード内容を比較的簡単に追う or 改造する事ができると思います。

今回のコードは、基本的なグラフ描画の処理に、GUIの画面などを組み合わせて、ツールとして仕上げたものです。 グラフの描画処理の基本については以下の回で解説していますので、そちらをご参照ください:

- 前提となる処理の記事 -

また、VCSSLでのGUI画面の構築については、「 VCSSL GUI開発ガイド 」をご参照ください。

今回のコードは、サンプルコードというよりは実際に使うためのツールなので、 細部を細かくピックアップしながらの解説は割愛し、コード全体の掲載に留めておきます。 今回のコードの全体は、以下の通りです:


coding UTF-8;  // 文字コードの明示(文字化け予防)

// ライブラリの読み込み
import tool.Graph2D;
import File;
import GUI;


/** デフォルトのファイル読み込みフォルダです。 */
const string DEFAULT_INPUT_DIRECTORY_PATH = "./input";

/** デフォルトのファイル保存先フォルダです。 */
const string DEFAULT_OUTPUT_DIRECTORY_PATH = "./output";

/** デフォルトの読み込みファイル名(番号部分や拡張子は除く)です。 */
const string DEFAULT_INPUT_FILE_NAME_HEAD = "sample2d_";

/** デフォルトの読み込みファイルの拡張子です。 */
const string DEFAULT_INPUT_FILE_EXTENTION = ".txt";

/** グラフのX範囲の最大値のデフォルト入力値です。 */
const string DEFAULT_X_MAX = "1.0";

/** グラフのX範囲の最小値のデフォルト入力値です。 */
const string DEFAULT_X_MIN = "-1.0";

/** グラフのY範囲の最大値のデフォルト入力値です。 */
const string DEFAULT_Y_MAX = "1.0";

/** グラフのY範囲の最小値のデフォルト入力値です。 */
const string DEFAULT_Y_MIN = "-1.0";

/** アニメーション速度のデフォルト値です。 */
const string DEFAULT_ANIMATION_SPEED = "1.0";

/** アニメーション速度が 1.0 の時のアニメーションウェイト値です。 */
const int BASE_ANIMATION_WAIT = 33;

/** 連番の開始番号を探す上限です。 */
const int FILE_NUMBER_SEARCH_LIMIT = 1000;



// 以下、内部状態関連の変数

/** ファイル読み込みフォルダのパスを保持します。 */
string inputDirectoryPath = NULL;

/** 読み込みファイル名(番号部分や拡張子は除く)を保持します。 */
string inputFileNameHead = NULL;

/** 読み込みファイルの拡張子を保持します。 */
string inputFileExtention = NULL;

/** 連番の開始番号を保持します。 */
int inputFileNumberBegin = -1;

/** 連番の終了番号を保持します。 */
int inputFileNumberEnd = -1;

/** メインループの継続状態を保持します(falseにすると脱出)。 */
bool mainLoopState = true;

/** アニメーションの状態を保持します(true=アニメーション中、false=待機状態)。 */
bool animationState = false;

/** 時刻が1つ進む際の待ち時間(アニメーションウェイト)を保持します。 */
int animationWait = (int)( BASE_ANIMATION_WAIT / (float)DEFAULT_ANIMATION_SPEED );

/**
 * フレームカウンタ(アニメーションの描画回数の中で、何回目かを保持するカウンタ)です。
 * inputFileNumberBegin から inputFileNumberEnd まで変化します。 */
int frameCounter = 0;

/** アニメーションを終了する最終フレームカウンタ値を保持します。inputFileNumberEnd-inputFileNumberBegin に一致します。 */
int frameCounterMax = -1;

/** グラフをプロットするリクエストフラグ(trueにするとメインループでプロットされ、falseに戻される)です。 */
bool plotRequest = false;

/** メインループで連番画像出力処理を行うためのフラグです。 */
bool animationExportRequest = false;



// 以下、グラフやGUIコンポーネントIDを格納する変数

/** グラフのIDを格納します。 **/
int graph = NULL;

/** 入力画面のウィンドウのIDを格納します。 */
int inputWindow = NULL;

/** X軸の範囲を自動調整するかどうかを選択するチェックボックスのIDを格納します。 */
int xAutoRangeBox = NULL;

/** X軸の最大値を入力するテキストフィールドのIDを格納します。 */
int xMaxField = NULL;

/** X軸の最小値を入力するテキストフィールドのIDを格納します。 */
int xMinField = NULL;

/** Y軸の範囲を自動調整するかどうかを選択するチェックボックスのIDを格納します。 */
int yAutoRangeBox = NULL;

/** Y軸の最大値を入力するテキストフィールドのIDを格納します。 */
int yMaxField = NULL;

/** Y軸の最小値を入力するテキストフィールドのIDを格納します。 */
int yMinField = NULL;

/** アニメーション速度を入力するテキストフィールドのIDを格納します。 */
int animationSpeedField = NULL;

/** セットボタンのIDを格納します。 */
int setButton = NULL;

/** 画像出力ボタンのIDを格納します。 */
int outputButton = NULL;

/** 終了ボタンのIDを格納します。 */
int exitButton = NULL;

/** 画像出力フォルダ指定フィールドのIDを指定します。 */
int outputPathField = NULL;

/** 画像出力フォルダ選択ボタンのIDを指定します。 */
int outputPathSelectButton = NULL;

/** アニメーション操作ウィンドウのIDを格納します。 */
int animationWindow = NULL;

/** アニメーションの「PLAY」/「STOP」ボタンのIDを格納します。 */
int animationButton = NULL;

/** アニメーションの時間操作スライダーのIDを格納します。 */
int animationSlider = NULL;

/** アニメーションの時間表示ラベルのIDを格納します。 */
int animationLabel = NULL;



/**
 * 最上階層の全体的な処理です。この関数は起動時に自動で実行されます。
 */
void main() {
	
	// ユーザー入力による設定処理を実行
	configure();
	
	// システム側で標準接続されている2DグラフソフトがあればIDを取得(無ければnewGraph2D関数同様、新規に立ち上がる)
	graph = getGraph2D();
	
	// 取得したグラフ画面が他のウィンドウよりも後ろにある場合は、最前面に持ってきたいため、一旦非表示にして再表示する
	hideGraph2D(graph);
	showGraph2D(graph);
	
	// このプログラムでは、既存のグラフ内容に重ね描きする用途は考えにくいので、最初に内容をクリアしておく
	clearGraph2D(graph);
	
	// ※ 普通に newGraph2D 関数で新規生成しないのは、このプログラムがリニアングラフ2Dにも同梱される事を見込んだツールであり、
	//    リニアングラフ2D上でメニューからこのプログラムを実行した際に、そのグラフ自身を制御対象とするためです。
	
	// グラフ画面の位置とサイズを設定
	setGraph2DLocation(graph, 330, 120);
	setGraph2DSize(graph, 720, 600);
	
	// 設定画面とアニメーション操作画面を起動
	createInputWindow();
	createAnimationWindow();
	
	// 最初のファイルをプロット
	plotGraph(inputFileNumberBegin);
	
	// メインループ ― プログラム終了までずっと繰り返し、必要なら処理を行い、何も無ければ待機する
	while( mainLoopState ){
		
		// アニメーションの連番画像出力がリクエストされている場合は、その処理を行う
		if ( animationExportRequest ) {
			string outputDirectoryPath = getComponentText(outputPathField);
			if (!exists(outputDirectoryPath)) {
				alert("指定された保存先フォルダ「" + outputDirectoryPath + "」が存在しません。");
			} else if (!isdir(outputDirectoryPath)) {
				alert("指定された保存先フォルダ「" + outputDirectoryPath + "」はフォルダではありません。");
			} else {
				outputDirectoryPath = getFilePath(outputDirectoryPath);
				outputImages(outputDirectoryPath);
			}
			frameCounter = 0;
			plotRequest = true;
			animationExportRequest = false;
		}

		// アニメーション再生時の状態更新処理
		if( animationState ){
			if( frameCounter < frameCounterMax ){
				setComponentValueInt( animationSlider, frameCounter+1 );
			}else{
				setComponentValueInt( animationSlider, 0 );
			}
		}

		// グラフのプロット
		if( plotRequest ){
			int fileNumber = inputFileNumberBegin + frameCounter;
			plotGraph(fileNumber);
			plotRequest = false;
		}
		
		sleep( animationWait );
	}
	
	// メインループを脱出すれば終了
	exit();
}


/**
 * ユーザー入力による設定処理を行います。
 */
void configure() {
	
	// ファイル読み込みフォルダの選択(スキップすると input フォルダを使用)
	inputDirectoryPath = DEFAULT_INPUT_DIRECTORY_PATH;
	if (confirm("ファイルを読み込むフォルダを指定しますか?", "(「いいえ」を選択すると「 " + DEFAULT_INPUT_DIRECTORY_PATH + " 」フォルダを使用)")) {
		inputDirectoryPath = choose("ファイルを読み込むフォルダを選択", ".");
	}
	println("ファイル読み込みフォルダ = " + inputDirectoryPath);
	
	// 画像ファイル名(番号部分や拡張子は除く)の入力
	inputFileNameHead = input("ファイル名(番号部分や拡張子は除く)を入力", DEFAULT_INPUT_FILE_NAME_HEAD);
	println("ファイル名 = " + inputFileNameHead);
	
	// 拡張子の選択
	inputFileExtention = input("拡張子を入力", DEFAULT_INPUT_FILE_EXTENTION);
	
	// フォルダ内のファイルを検索し、連番の始点を inputFileNumberBegin、終点を inputFileNumberEnd に設定
	scanFileIndex();
	
	// 連番の始点と終点から、フレームカウンタの最大値を求めて設定
	frameCounterMax = inputFileNumberEnd - inputFileNumberBegin;
}


/**
 * 指定されたファイル番号のファイルを、グラフにプロットします。
 */
void plotGraph(int fileNumber) {
	string fileName = inputFileNameHead + fileNumber + inputFileExtention;
	string filePath = getFilePath(fileName, inputDirectoryPath);
	setGraph2DFile(graph, filePath);
	setComponentText( animationLabel, "ファイル番号 = " + fileNumber );
}


/**
 * 現在の入力内容に基づいて、グラフの範囲設定を行います。
 */
void setGraphRange() {

	// 範囲の自動調整機能の有無を取得して反映させる
	bool xAutoRangeEnabled = getComponentValueBool(xAutoRangeBox);
	bool yAutoRangeEnabled = getComponentValueBool(yAutoRangeBox);
	setGraph2DAutoRange(graph, xAutoRangeEnabled, yAutoRangeEnabled);

	// X軸の範囲設定
	if (!xAutoRangeEnabled) {
		if ( !evaluable( getComponentText( xMaxField ), 0.0 ) ) {
			alert("x-max の入力内容に誤りがあります。");
			return;
		}
		if ( !evaluable( getComponentText( xMinField ), 0.0 ) ) {
			alert("x-min の入力内容に誤りがあります。");
			return;
		}
		float xMax = feval(getComponentText( xMaxField ), 0.0);
		float xMin = feval(getComponentText( xMinField ), 0.0);
		setGraph2DRangeX(graph, xMin, xMax);
	}

	// Y軸の範囲設定
	if (!yAutoRangeEnabled) {
		if ( !evaluable( getComponentText( yMaxField ), 0.0 ) ) {
			alert("y-max の入力内容に誤りがあります。");
			return;
		}
		if ( !evaluable( getComponentText( yMinField ), 0.0 ) ) {
			alert("y-min の入力内容に誤りがあります。");
			return;
		}
		float yMax = feval(getComponentText( yMaxField ), 0.0);
		float yMin = feval(getComponentText( yMinField ), 0.0);
		setGraph2DRangeY(graph, yMin, yMax);
	}
}


/**
 * ファイルを検索し、連番の始点と終点を判定します。
 */
void scanFileIndex() {
	
	println("ファイル検索中...");
	
	// 始点番号を検索し、fileNumberBegin に設定
	inputFileNumberBegin = 0;
	while (true) {
		
		// 以下、inputFileNumberBegin を0から1ずつ増やしながら、
		// その値を連番部分とする名前のファイルが存在するか検査し、
		// 最初に存在したものを開始番号としてループ脱出
		
		string fileName = inputFileNameHead + inputFileNumberBegin + inputFileExtention;
		string filePath = getFilePath(fileName, inputDirectoryPath);
		if (exists(filePath)) {
			println("開始ファイル: " + filePath);
			break;
		}
		
		if(inputFileNumberBegin >= FILE_NUMBER_SEARCH_LIMIT) {
			pop("連番ファイルを" + FILE_NUMBER_SEARCH_LIMIT + "番まで探しましたが、見つかりませんでした。");
			exit();
		}
		
		inputFileNumberBegin++;
	}
	
	
	println("開始番号 = " + inputFileNumberBegin);
	
	// 終点番号の検索し、inputFileNumberEnd に設定
	inputFileNumberEnd = inputFileNumberBegin;
	while (true) {
		
		// 以下、inputFileNumberBegin を inputFileNumberBegin から1ずつ増やしながら、
		// その値を連番とする名前のファイルが存在するか検査し、
		// 「最初に存在しなくなった番号-1」を終了番号としてループ脱出
		
		string fileName = inputFileNameHead + inputFileNumberEnd + inputFileExtention;
		string filePath = getFilePath(fileName, inputDirectoryPath);
		if (!exists(filePath)) {
			inputFileNumberEnd--;
			break;
		}
		inputFileNumberEnd++;
	}
	
	println("終了番号 = " + inputFileNumberEnd);
}


/**
 * 現在の入力内容に基づいて、アニメーションのウェイト値を設定します。
 */
void setAnimationWait() {
	if ( !evaluable( getComponentText(animationSpeedField), 0.0 ) ) {
		alert("「速度」の項目の入力内容に誤りがあります。");
	}
	
	// 入力内容からアニメーション速度の値を取得
	float speed = feval(getComponentText(animationSpeedField), 0.0);
	
	// 負の場合はおかしいので弾く
	if (speed < 0) {
		alert("「速度」の項目には正の値を設定してください。");
	}
	
	// スピードが小さすぎると、ウェイト値が大きくなりすぎて、メインループの応答間隔が著しく悪化するので弾く
	if (speed < 0.01) {
		alert("「速度」の項目の値が小さすぎます。");
	}
	
	// アニメーション速度をアニメーションウェイトに変換
	animationWait = BASE_ANIMATION_WAIT / speed;
}


/**
 * アニメーションのON/OFF状態を切り替えます。
 * 
 * @param state アニメーションのON/OFF状態(ONならtrue)
 */
void setAnimationState( bool state ){
	animationState = state;
	if( state ){
		setComponentText( animationButton, "STOP" );
	}else{
		setComponentText( animationButton, "PLAY" );
	}
}


/**
 * グラフを連番画像として保存します。
 * 
 * @param outputDirectoryPath 保存フォルダのパス
 */
void outputImages(string outputDirectoryPath) {
	setComponentText(outputButton, "保存中...");
	hideGraph2D(graph);
	hideComponent(animationWindow);
	hideComponent(inputWindow);
	setAnimationState(false);
	plotRequest = false;

	popup(
		"全ての入力ファイルのグラフを、連番の画像ファイルとして保存します。" + EOL + 
		"これには少し時間がかかる事があります。" + EOL + 
		"「 OK 」を押した後は、操作せずに完了までしばらくお待ちください。"
	);

	// ファイルをプロットして画像に保存、を全ての入力ファイルに対してくり返す
	for (frameCounter=0; frameCounter<=frameCounterMax; frameCounter++) {
		int fileNumber = inputFileNumberBegin + frameCounter;
		plotGraph(fileNumber);
		string outputFileName = inputFileNameHead + fileNumber + ".png";
		string outputFilePath = getFilePath(outputFileName, outputDirectoryPath);
		println("画像保存(" + frameCounter + "/" + frameCounterMax + "): " + outputFilePath);
		exportGraph2D(graph, outputFilePath, "PNG");
	}

	showGraph2D(graph);
	showComponent(animationWindow);
	showComponent(inputWindow);

	setComponentText(outputButton, "画像保存");
	popup("保存しました。保存先フォルダ: " + EOL + outputDirectoryPath);

	frameCounter = 0;
	setComponentValueInt( animationSlider, 0 );
}


/**
 * 入力画面を起動します。
 */
void createInputWindow(){
	
	int leftWidth = 110;
	int rightX = leftWidth + 10;
	int rightWidth = 160;
	int buttonWidth = 270;
	int fontSize = 20;

	inputWindow = newWindow( 0, 0, 320, 530, "入力画面" );


	xAutoRangeBox = newCheckBox( 10, 10, 500, 20, "X範囲を自動設定", true );
	mountComponent( xAutoRangeBox, inputWindow );

	int xMaxLabel = newTextLabel( 10, 40, leftWidth, 25, "x-max =" );
	setComponentFontSize(xMaxLabel, fontSize);
	mountComponent( xMaxLabel, inputWindow );

	xMaxField = newTextField( rightX, 40, rightWidth, 25, DEFAULT_X_MAX );
	setComponentFontSize(xMaxField, fontSize);
	mountComponent( xMaxField, inputWindow );

	int xMinLabel = newTextLabel( 10, 70, leftWidth, 25, "x-min =" );
	setComponentFontSize(xMinLabel, fontSize);
	mountComponent( xMinLabel, inputWindow );

	xMinField = newTextField( rightX, 70, rightWidth, 25, DEFAULT_X_MIN );
	setComponentFontSize(xMinField, fontSize);
	mountComponent( xMinField, inputWindow );



	yAutoRangeBox = newCheckBox( 10, 110, 500, 20, "Y範囲を自動設定", true );
	mountComponent( yAutoRangeBox, inputWindow );


	int yMaxLabel = newTextLabel( 10, 140, leftWidth, 25, "y-max = " );
	setComponentFontSize(yMaxLabel, fontSize);
	mountComponent( yMaxLabel, inputWindow );

	yMaxField = newTextField( rightX, 140, rightWidth, 25, DEFAULT_Y_MAX );
	setComponentFontSize(yMaxField, fontSize);
	mountComponent( yMaxField, inputWindow );

	int yMinLabel = newTextLabel( 10, 170, leftWidth, 25, "y-min = " );
	setComponentFontSize(yMinLabel, fontSize);
	mountComponent( yMinLabel, inputWindow );

	yMinField = newTextField( rightX, 170, rightWidth, 25, DEFAULT_Y_MIN );
	setComponentFontSize(yMinField, fontSize);
	mountComponent( yMinField, inputWindow );


	int animationSpeedLabel = newTextLabel( 10, 220, leftWidth, 25, "速度 =" );
	setComponentFontSize(animationSpeedLabel, fontSize);
	mountComponent( animationSpeedLabel, inputWindow );

	animationSpeedField = newTextField( rightX, 220, rightWidth, 25, DEFAULT_ANIMATION_SPEED );
	setComponentFontSize(animationSpeedField, fontSize);
	mountComponent( animationSpeedField, inputWindow );


	setButton = newButton( 10, 260, buttonWidth, 50, "セット" );
	setComponentFontSize(setButton, fontSize);
	mountComponent( setButton, inputWindow );


	outputButton = newButton( 10, 320, buttonWidth, 50, "画像保存" );
	setComponentFontSize(outputButton, fontSize);
	mountComponent( outputButton, inputWindow );

	int outputPathLabel = newTextLabel( 10, 375, 80, 24, "保存場所 =");
	mountComponent( outputPathLabel, inputWindow );

	outputPathField  = newTextField( 90, 375, 120, 24, DEFAULT_OUTPUT_DIRECTORY_PATH);
	mountComponent( outputPathField, inputWindow );

	outputPathSelectButton = newButton( 210, 375, 70, 24, "選択" );
	mountComponent( outputPathSelectButton, inputWindow );


	exitButton = newButton( 10, 420, buttonWidth, 50, "終了" );
	setComponentFontSize(exitButton, fontSize);
	mountComponent( exitButton, inputWindow );
	
}


/**
 * アニメーション操作画面を起動します。
 */
void createAnimationWindow(){

	animationWindow = newWindow( 330, 0, 500, 120, "アニメーション操作画面" );

	animationButton = newButton( 10, 10, 100, 50, "PLAY" );
	mountComponent( animationButton, animationWindow );

	animationSlider = newHorizontalSlider( 120, 10, 300, 30, 0, frameCounterMax, 0 );
	mountComponent( animationSlider, animationWindow );

	animationLabel = newTextLabel( 125, 40, 300, 20, "" );
	mountComponent( animationLabel, animationWindow );
}


/**
 * ボタンが押された際にコールされます(イベントハンドラ)
 * 
 * @param id 押されたボタンのID
 */
void onButtonClick( int id ){

	// 「セット」ボタンが押された場合
	if( id == setButton ){
		setAnimationWait();
		setGraphRange();
		plotRequest = true;
		return;
	}

	// 「終了」ボタンが押された場合
	if( id == exitButton ){
		mainLoopState = false;
		return;
	}

	// 「画像保存」ボタンが押された場合
	if( id == outputButton ){
		// このフラグを有効化すると、メインループが連番画像出力処理を行う
		animationExportRequest = true;
		return;
	}

	// 画像保存先フォルダの選択ボタンを押した際
	if ( id == outputPathSelectButton ) {
		string path = choose();
		while (!isdir(path)) {
			alert("選択されたものがフォルダではありません。" + EOL + "画像を保存するフォルダを選択してください。");
			path = choose();
		}
		setComponentText(outputPathField, path);
		return;
	}

	// 「PLAY/STOP」ボタンが押された場合
	if( id == animationButton ){
		if( animationState ){
			setAnimationState( false );
		}else{
			setAnimationState( true );
		}
		return;
	}
}


/**
 * チェックボックスが選択された際にコールされます(イベントハンドラ)
 */
void onCheckBoxClick( int id, bool value ) {
	if (id == xAutoRangeBox || id == yAutoRangeBox) {
		bool xAutoRangeEnabled = getComponentValueBool(xAutoRangeBox);
		bool yAutoRangeEnabled = getComponentValueBool(yAutoRangeBox);
		setGraph2DAutoRange(graph, xAutoRangeEnabled, yAutoRangeEnabled);
	}
}


/**
 * スライダーが動かされた際にコールされます(イベントハンドラ)
 * 
 * @param id 動かされたスライダーのID
 */
void onSliderMove( int id, int value ){
	if( id == animationSlider ){
		frameCounter = value;
		plotRequest = true;
	}
}


/**
 * ウィンドウが閉じられた際にコールされます(イベントハンドラ)
 * 
 * @param id 閉じられたウィンドウのID
 */
void onWindowClose( int id ){
	
	if( id == inputWindow || id == animationWindow ){

		// このプログラムでは、場合によっては範囲の自動調整を無効化するので、終了時に戻しておく
		setGraph2DAutoRange( graph, true, true );

		// メインループを脱出、プログラムを終了させる
		mainLoopState = false;
	}
}


/**
 * グラフが閉じられた際にコールされます(イベントハンドラ)
 * 
 * @param id 閉じられたグラフのID
 */
void onGraph2DClose( int id ){
	if( id == graph ){
		animationState = false; // アニメーション状態を解除して待機状態に移行
	}
}
download/GraphFileAnimator2D.vcssl

コード内容は以上です。

ライセンス

このVCSSL/Vnanoコード( 拡張子が「.vcssl」や「.vnano」のファイル )は実質的な著作権フリー(パブリックドメイン) である CC0 の状態で公開しています。 記事中にC言語/C++/Java言語などでのサンプルコードが掲載されいてる場合は、それらについても同様です。 そのままでのご利用はもちろん、改造や流用などもご自由に行ってください。

※ ただし、このコードの配布フォルダ内には、ダウンロード後すぐに実行できるように、 VCSSLの実行環境も同梱されており、そのライセンス文書は「 License 」フォルダ内に同梱されています (要約すると、商用・非商用問わず自由に使用できますが、使用の結果に対して開発元は一切の責任を負いません、といった具合の内容です)。 配布フォルダ内の各構成物の一覧やライセンスについては「 ReadMe_使用方法_必ずお読みください.txt 」をご参照ください。

※ Vnano の実行環境については、別途スクリプトエンジンのソースコードも一般公開しており、 何らかのソフトウェア内に組み込んでご利用いただく事も可能です。詳細はこちらをご参照ください。

この記事中の商標などについて

  • OracleとJavaは、Oracle Corporation 及びその子会社、関連会社の米国及びその他の国における登録商標です。文中の社名、商品名等は各社の商標または登録商標である場合があります。
  • Windows は、米国 Microsoft Corporation の米国およびその他の国における登録商標です。この記事は独立著作物であり、Microsoft Corporation と関連のある、もしくはスポンサーを受けるものではありません。
  • Linux は、Linus Torvalds 氏の米国およびその他の国における商標または登録商標です。
  • その他、文中に使用されている商標は、その商標を保持する各社の各国における商標または登録商標です。

Japanese English
[ 前へ | 目次 | 次へ ]
Vnano版 | 積分値のグラフ描画用データを出力するプログラム

数値的に積分を行い、結果の関数をグラフに描くためのデータを出力するコードです。
3Dグラフを回転アニメーションさせるツール

3Dグラフを、Z軸まわりにゆっくりと回転アニメーションさせるツールです。全角度のグラフを、連番の画像ファイルに保存する事もできます。
連番ファイルから3Dグラフをアニメーション描画するツール

フォルダ内の連番データファイルを読み込み、3Dグラフを高速で連続描画して、アニメーションさせるツールです。グラフを連番の画像ファイルに保存する事もできます。
連番ファイルから2Dグラフをアニメーション描画するツール

フォルダ内の連番データファイルを読み込み、2Dグラフを高速で連続描画して、アニメーションさせるツールです。グラフを連番の画像ファイルに保存する事もできます。
z = f(x,y,t) の形の数式を3Dグラフとしてアニメーション描画するツール

入力欄に z = f(x,y,t) の形の数式を入力すると、それを3次元のグラフにアニメーション描画してくれる簡易ツールです。
y = f(x,t) の形の数式を2Dグラフとしてアニメーション描画するツール

入力欄に y = f(x,t) の形の数式を入力すると、それを2次元のグラフにアニメーション描画してくれる簡易ツールです。
t を媒介変数とする x(t), y(t), z(t) の数式を3Dグラフに描画し、アニメーションもできるツール

入力欄に x(t), y(t), z(t) の形の数式を入力すると、それを t を媒介変数として3次元のグラフに描画し、アニメーションもできる簡易ツールです。
t を媒介変数とする x(t), y(t) の数式を2Dグラフに描画し、アニメーションもできるツール

入力欄に x(t), y(t) の形の数式を入力すると、それを t を媒介変数として2次元のグラフに描画し、アニメーションもできる簡易ツールです。
z = f(x,y) の形の数式を3Dグラフとして描画するツール

入力欄に z = f(x,y) の形の数式を入力すると、それを3次元のグラフに描いてくれる簡易ツールです。
y = f(x) の形の数式を2Dグラフとして描画するツール

入力欄に y = f(x) の形の数式を入力すると、それを2次元のグラフに描いてくれる簡易ツールです。
配列を3Dグラフにアニメーションプロットする(曲面/メッシュグラフ)

座標値配列の内容を、3次元の曲面/メッシュグラフに連続でプロットし、アニメーションさせるサンプルプログラムです。
配列を3Dグラフにアニメーションプロットする(点/線グラフ)

座標値配列の内容を、3次元の点/線グラフに連続でプロットし、アニメーションさせるサンプルプログラムです。
配列を2Dグラフにアニメーションプロットする

座標値配列の内容を、2次元グラフに連続でプロットし、アニメーションさせるサンプルプログラムです。
配列を3Dグラフにプロットする(曲面/メッシュグラフ)

座標値配列の内容を、3次元の曲面/メッシュグラフにプロットするサンプルプログラムです。
ファイルを3Dグラフにプロットする(曲面/メッシュグラフ)

座標値ファイルの内容を、3次元の曲面/メッシュグラフにプロットするサンプルプログラムです。
ユーザーが入力した数式を2Dグラフにプロットする

実行時にユーザーが入力した数式の値を、2次元グラフにプロットするサンプルプログラムです。
配列を3Dグラフにプロットする(点/線グラフ)

座標値配列の内容を、3次元の点/線グラフにプロットするサンプルプログラムです。
配列を2Dグラフにプロットする

座標値配列の内容を、2次元グラフにプロットするサンプルプログラムです。
ファイルを3Dグラフにプロットする(点/線グラフ)

座標値ファイルの内容を、3次元の点/線グラフにプロットするサンプルプログラムです。
ファイルを2Dグラフにプロットする

座標値ファイルの内容を、2次元グラフにプロットするサンプルプログラムです。
この階層の目次
[ 前へ | 目次 | 次へ ]
RINEARN からのお知らせ
※ VCSSL は RINEARN が開発しています。

VCSSLの最新版をリリース: 外部プログラムとの連携機能を少し強化、他
2025-05-25 - VCSSL 3.4.52をリリースしました。外部プログラム(C言語製の実行ファイル等)との連携機能を少し強化し、文字化け対策やOS判別などを可能にしました。他にも細かい機能追加があります。詳細をお知らせします。

VCSSLの最新版をリリース、Java 24上での非互換な挙動を対処
2025-04-22 - VCSSL 3.4.50をリリースしました。Java 24環境上でのネットワークドライブ関連のファイルパス解決で、従来環境とは異なる挙動が生じていたのを解消しました。詳細をお知らせします。

リニアングラフやVCSSLの最新版をリリース、目盛りの位置や内容を自由に指定可能に!
2024-11-24 - リニアングラフ3D/2Dを更新し、自由な位置に、自由な表記内容の目盛りを描けるようになりました! 併せて、Java言語やVCSSLでの、プログラム制御用APIも拡張しています。詳細をお知らせします。

Exevalator 2.2 をリリース、TypeScript 対応によりWebブラウザ上で動作可能に
2024-10-22 - オープンソースの式計算ライブラリ「Exevalator(エグゼバレータ)」の2.1をリリースしました。新たに TypeScript に対応し、Webブラウザ上での式計算にも使えるようになりました。詳細を解説します。

アシスタントAI作成の舞台裏(その2、作成編)
2024-10-12 - アシスタントAIの作成方法解説の後編です。実際にChatGPTの「GPTs」機能を用いて、アシスタントAIを作成する手順や、独自の知識をもたせたり、精度を出すためのノウハウなどを解説しています。

アシスタントAI作成の舞台裏(その1、基礎知識編)
2024-10-07 - アシスタントAI作成方法解説の前編です。今回はまず、アシスタントAIを作る前に抑えておきたい、基礎知識を延々と解説しています。そもそもLLM型AIとはどんな存在か? RAGとは何か? 等々です。

ソフトの利用をサポートしてくれるアシスタントAIを提供開始!
2024-09-20 - RINEARN製ソフトの使い方の質問応答や、一部作業のお手伝いをしてくれる、アシスタントAIを提供開始しました。ChatGPTアカウントさえあれば、誰でも無料で使用できます。使い方を解説します。

Exevalator 2.1 をリリース、新たに Visual Basic に対応
2024-07-28 - オープンソースの式計算ライブラリ「Exevalator(エグゼバレータ)」の2.1をリリースしました。今回から、新たに Visual Basic(VB.NET)でも使用できるようになりました。詳細を解説します。

関数電卓 RINPn(りんぷん)、Esc キーで計算式の一発クリアが可能に
2024-07-20 - 関数電 RINPn の Ver.1.0.2 をリリースしました。今回から、キーボードの「 Esc 」キーを押すと、入力中の計算式を一発でクリアできるようになりました。詳細を解説します。

Exevalator 2.0 をリリース、互換性に注意が必要なバグ修正が 1 件
2024-07-14 - オープンソースの式計算ライブラリ「Exevalator (エグゼバレータ)」の2.0をリリースしました。今回の更新では、互換性に注意を要する 1 件のバグ修正があります。詳細を解説します。