• ベストアンサー

逐次的なグラフ表示の方法

こんにちは、C言語においてグラフを表示することで質問があります。 いま、時間で変化していくある値を(x、y)をfprintfで出力し、datファイルに保存しました。それをwgnuplotで表示すると、きちんと表示することができました。そこで質問なんですが、 時間T=0のときに、X=1、Y=1。 T=1のときに、X=2、Y=2とY=Xの関係で変化していったとすると、直線であらわされますよね? それを、グラフ上で時間が経過していくと、点として右上に動いて行くように、視覚的に見ることはできるんでしょうか? いろいろとフリーソフトなどを探したのですが、よくわかりませんでした。。何か知っていたらお願いします。あるいは、C言語では逐次的に表現などできないとか、そういったアドバイスもあればお願いします。 すぐに返信できないかもしれませんが。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.11

あぁ、魚の群れの行動というのだから、たとえば、魚一匹ごとに3次元の点であらわして、それを gnuplot で描画してみようってことですよね、たぶん^^ 以下のプログラムをコンパイル・リンクして実行ファイル(myprogram.exe という名前だったとします)を作成し、   myprogram | pgnuplot とコマンドラインで打ち込むと、点のかたまりが3次元で動いていくように見えると思います。 === #include <stdio.h> #include <unistd.h> typedef struct Point { float x, y, z; } Point; void advance(size_t n, Point points[], Point *v) { size_t i; for (i = 0; i < n; ++i) { points[i].x += v->x; points[i].y += v->y; points[i].z += v->z; } } int main(void) { Point points[] = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 1.0 }, }; size_t n = sizeof points / sizeof points[0]; const int m = 90; int i, j; Point v = { .1, .1, .1 }; puts("set xrange [0:10]"); puts("set yrange [0:10]"); puts("set zrange [0:10]"); for (i = 0; i < m; ++i, advance(n, points, &v)) { puts("splot \'-\' with point"); for (j = 0; j < n; ++j) printf("%f %f %f\n", points[j].x, points[j].y, points[j].z); puts("e"); fflush(stdout); sleep(1); } return 0; }

kenpanch7
質問者

お礼

すいません。 myprogram.exeの実行ファイルは簡単に、みつかりました。 debugフォルダの中にありました。 ただ、myprogram | pgnuplotとうったんですが、 pgnuplotは内部コマンド、または、外部コマンド、操作可能なプログラムまたは、パッチファイルとして認識されません。と表示されてしまいました。 どのようにしたらいいでしょうか。

kenpanch7
質問者

補足

すいません。変換ミスです。群行動が正しいです。 私は、VC++を使ってC言語をくんでいますが、 実行すると、#include <unistd.h>がどうもひっかかるみたいでした。 そこで、ヘッダファイルを適当に?どうにかしてみたところ。 (人が作っていたものをコピーして、インクルードフォルダにコピペしてみた) 実行をすることができました!! ただ、コマンドラインで打ち込む方法がわからなかったので、 myproglam | pgnuplot をできませんでした・・・汗 アクセサリからコマンドプロントを探し、プログラムのあるファイルに移動して、myproglam | pgnuplotとは 入力してみたのですが、うまくいかなかったようです。 実行ファイルはプログラムとは違うところに保存されるのでしょうか。 実行して同じフォルダにできた拡張子をみてみると、 プロジェクトファイル、ncb,,opt,と書いてありました。 そこで、LINUXで動かしたのですが、gccでコンパイルして、 みると、a.out と言うのができたのですが。 myproglam | pgnuplot と打ってもcannot found しかでませんでした。 この↑記述の意味がよくわからないので、、、 a | pgnuplot とか、、、いろいろしてみたのですが、、ダメでした。 今からもう少し調べてみようと思っています。お返事ありがとうございます。

その他の回答 (18)

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.19

理解できてよかったですね^^ サンプルプログラムの adavance で、次の表示時刻の魚群の位置を設定しておけば、とりあえず、魚一匹を一点で表現した魚群の動いている様子を見せることができると思います。 プレゼンテーションなどで、それっぽい魚を描いたり、水中を再現した背景にしたいなど、もっときれいに見せたいというなら、それ相応のグラフィックライブラリを使うのがいいと思います。Linux 環境などでは、vtk を使うとか、もっと凝りたいなら OpenGL(Mesaなど)で直接コーディングするとか(そこまで凝る必要があるのかとは思いますが…笑)。わたしはグラフィックスはぜんぜん詳しくないので、もし凝りたくて、ご自分で探して見つけられないというのであれば、グラフィック専門のところへ、「どういうツール・ライブラリがいいのか」、質問するのがいいんじゃないかと思います。 gnuplot でも結構いろいろなことができるので、gnuplot の demo フォルダにある all.dem を動かして、どんなことができるのか、一度、見てみるのもいいかもしれません。「じゃあ、こうしよう♪」というインスピレーションが沸くかもしれませんしね。では、研究がんばってください。

kenpanch7
質問者

補足

そうですか!!ありがとうございますw せっかくなので凝ったものにしてみたいとおもいます。 ただ、まだ魚たちがうまく、群行動してくれないのでそこを直す必要がありますが・・・汗 本当にありがとうございました。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.18

あぁ、あとそれから、splot コマンドの間に sleep() を入れていないというのならば、gnuplot へ splot コマンド が間断なく指示されるので、描画が一瞬で終わって、動いているように見えないかもしれません。 もし、そちらの環境で、sleep() のようなものがなければ(sleep(n)を実行するというのは n秒間お休みするみたいなもの)、たとえば、  fprintf(stderr, "input something: ");  do { int c; while ((c = getchar()) != EOF) if (c == '\n') break; } while (0);  を、sleep(1) の代わりに入れて、実行時に splot コマンド発行ごとに、端末から何か入力するまで、次の splot コマンドを発行させないようにするなどの方法を取ればよいでしょう。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.17

もう一つ追加: サンプルプログラムをコンパイル・リンクして(myprogram.exe とする)、コマンドプロンプトから実行したときに、コマンドプロンプト上に出力されるものがすべて gnuplot への入力となります。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.16

それから、gnuplot と C言語は別のものなので、C言語の本に gnuplot のことは書いてないのが普通です。gnuplot のことは、gnuplot のヘルプなどを見て勉強するか、検索エンジンで gnuplot というキーワードで検索すると、簡単な使い方が書いてあるHPなどはすぐに見つかるでしょう。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.15

n は points の配列長になります。sizeof points で配列全体のバイト数が出ます。sizeof points[0] で配列要素のバイト数が出ます。なのでsizeof points / sizeof points[0] で、配列の長さが計算できます。配列数は、初期値の個数で決まるようにしていて、初期値を付け足したり、間引いたりしても、sizeof points や sizeof points[0] などは、コンパイラが処理しますから、他の部分のコードを修正しなくてよいので、配列の長さを数字そのままで扱っているより便利だから書いているだけです。配列サイズを直接指定したいというなら、  Point points[10] = { { 0, 0, 0 }, .... };  size_t n = 10; としてもかまいません。m は何回か描画させるために適当に決めた数字をいれているだけです。この場合は、90 回 gnuplot が描画します。 あとは、gnuplot のコマンドの文法ですね。。。  splot '-'  0.0 0.0 0.0  1.0 1.0 1.0  e というのは、  === ここから、data.txt  0.0 0.0 0.0  1.0 1.0 1.0  === ここまで、data.txt というファイル data.txt があるとすると、  splot 'data.txt' と同じ意味です。文字 "e" は入力データの終了を splot に指示するものです。

kenpanch7
質問者

お礼

やっと理解することができました!! 今までポインタから逃げてきた人間だったので、 今回再勉強によりだいぶ進化したような気がします。 おかげさまで、毎日C言語三昧ですw size tを使った方法はとても便利ですね!! たいへん参考になりました!

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.14

ありゃ。。。もううまく言ってた訳ですね。よかったよかった。 プログラムは適当に使えるものは利用して、研究をしっかりとがんばってください(笑)

kenpanch7
質問者

補足

ありがとうございます! 途中でカレントフォルダから相対パス・・・ と書いてあるところを読んで気づきました!!! 実行することはできたのですが、プログラムの解釈が難しいです。 ためしに、似たようなプログラムを作ったりしているのですが、 どうも違います。うまく表示されなかったり、一つの点しか表示されなかったりといったことがあります。 puts("")の中で直接、pgnuplotに指示を出しているんですよね? 自分の持っている、C言語の本にはあまり深く書いてないので、 少し理解が難しいです。for文の回す範囲や、nの導出の仕方が特にです。 もしよろしければ解説していただけないでしょうか?

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.13

あっ、そうそう^^ unistd.h って、Unix 環境のヘッダだから、Windows ではないかもしれません(POSIX 対応のがあればあるのかもしれないけど、詳しくない^^;)。 unistd.h は sleep() を使うために include してるだけなので、もし、sleep() を使うことでリンクエラーになるなら、sleep() のところを削除してもかまいません(点の動きが早くて、描画状態がわからないかもしれませんけどね^^)。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.12

パスの通し方がわからなければ、すべて、カレントディレクトリからの相対パスで書けばいいんじゃないですか?わたしの場合は、たとえば、  > "..\home\watashi\work\c\myprogram" | "d:\downloads\gnuplot\gnuplot\bin\pgnuplot" と打つと、うまくいきます。絶対パスで指定してもいいですけど、パスを通しておくのが簡単ですけどね(笑)

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.10

> 自分で描画を行う場合には、わざわざ外部ファイルに… それはそのとおりだと思います。自作の描画機能で、わざわざ外部ファイルに出力するように設計する人は、まれでしょう^^ まぁ、kenpanch7さんは、学生さんで、研究の補助として「動いている」ように見える描画機能がほしいだけみたいで、そこそこ動けばよいようですし、「暇なときに見てみます」って回答なので、そんなにまじめに作るほど重要でもないんでしょう(笑)それに「あるものは使えばいい」し、「自分で探して見つからなければ、人に聞くのもいい」でしょ。

kenpanch7
質問者

お礼

連続投稿すいません、、、 実行ファイルとpgnuplotを同じフォルダにおけばできました。 本当にありがとうございました!!やっとみれたのでけっこう感動しました!!! ただ、次は自分のプログラムにどうつかうかですね。 ありがとうございます。

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.9

Cの開発環境が不明ですが... PictureBox等に軸線、点を描画する事で自作でも容易に 実現可能の様に思います。 画面上で点が動いている様にみせるには、PictureBoxを 2画面分用意しておいて 1つの画面を表示している間に もう 1つの画面に移動後の点を描画しておいて画面を切 替える方法や、移動前・移動後の点の位置を個別に消去 ・表示するのを全ての点に対して順に行う方法等が有り ます。 自分で描画を行う場合には、わざわざ外部ファイルに出力 する必要もありません。

kenpanch7
質問者

補足

Cの開発環境は、今はVC++を使っています。 ただ、今回の件もあり、今後LINUXを入れてみようと思っています。 また、picturebox という単語は初めて聞きました。パイプというのも初めてでしたが・・・・汗 また、研究内容は、(研究というほどのものでもないですが) 魚を三次元で動かし、群行動をさせることを目標としています。 道は長いみたいです。ありがとうございます。 せっかくなのでpictureboxについても調べてみようと思います。 アドバイスありがとうございます!

関連するQ&A