• ベストアンサー

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

こんにちは、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

  • Excelのグラフの書き方について

    軌道の変化を見るためにグラフを作りたいのですが、別のソフトで出てくるデータをエクセルに移すと、 X1Y1 X2Y2 X3Y3・・・X99Y99 X100Y100といった形で並びます。これは1秒後にXとYがどのように変化していくかといったデータです。 分かりにくいと思いますが、これが横軸で更に縦に200個くらいずつ座標が表示されます。 グラフを作っていたのですが、自分の作り方は まずX1とY1についてのグラフを作り(A1からA200のX座標とB1からB200までのY座標をグラフ化)、その瞬間の軌道を表示させます。 次にそのグラフを右クリックして、オプションでグラフの追加をクリックして、X2Y2に関する軌道を表示させます。 つまりグラフの追加画面でX軸項目にC1からC200まで、Y軸項目にD1からD200と入れます。 これを繰り返すことで、一つのグラフ内にいくつも軌道を表示してます。一定の時間が経過するごとにどのように軌道が変化していくかを一つのグラフで表すためにこの方法をとっています。 非常に説明が分かりづらいかもしれません・・・ でもこの方法だと一度作ってしまえば次回からは数値の部分をコピーアンドペーストで変えるだけでいろんな軌道変化を表示させることが出来るんですが、今回は横軸が200個以上あり、一つずつグラフの追加でインプットするのが非常に大変なのですが、 この方法より簡単に出来る方法を知っている方がいましたら教えていただきたいです。 つまりX1Y1Y2Y3Y4Y5Y6・・・Y100だったらXが固定なので一回で全てのデータを一つのグラフに書き表せると思うのですが、 今回はXもYが変化するに応じて変化していってしまうということで悩んでます。 エクセルでなくてもX1Y1 X2Y2・・・などを簡単に一つのグラフに表せるフリーソフトがあれば教えていただきたいです。 また上記のように一つのグラフにいくつもの散布図を表し、一つのグラフ内に何本も線があるようにした場合、毎回散布図に表すと、一つのデータずつ色が変わってしまいます。 線の太さも色も同じにしたいので、毎回1系列ごとに書式を直しています。 これを一度でやる方法ってありますか?書式設定をグラフ内の全てに適用する方法を知っている方もいましたら教えてください。

  • 二次関数のグラフで

    直線x=-1とx>0とx軸で区切り、右上から半時計回りにA~Dと名付けたとき(境界線は含まない)y=x^2+ax+1(aは定数)のグラフがAとBを通り、CとDは通らないaの範囲を求める問題なんですが、解説お願いします 分かりにくくてすみません…

  • 6次関数のグラフから各係数の符号を知る方法

    6次関数y=f(x)=ax^6+bx^5+cx^4+dx^3+ex^2+fx+g のグラフがxy平面に描かれているとします。そのグラフから各係数の符号を、計算しないで視覚的に知る方法を考えたいのです。 x≒0のとき、y≒ex^2+fx+gなので、(0,f(0))の近傍でのグラフの様子から視覚的にe,f,gの符号を知ることができます。 つまり、y軸との交点がy>0なら、g>0。 グラフが右上がりなら、f>0。 グラフが下に凸なら、e>0。 |x|が十分大きいとき、y≒ax^6+bx^5≒a(x+b/6a)^6なので、グラフの大域的な様子から視覚的にa,bの符号を知ることができます。 つまり、大域的に「U字型」の形なら、a>0。 大域的に、いわゆるグラフの「軸」がy軸より左にあれば、b/6a>0。 c,dの符号を視覚的に知るようなアイデアがありましたら教えてください。

  • 2次関数グラフについて

    2次関数グラフについて お恥ずかしいことですが、以下の問題を解くことが出来ません。 出来る限り易しくお教えください。 (1)2点 A(0,1)とB(1,0)を通る直線上の点C(2,α)を放物線のグラフ y=x2乗+βは通る。αとβを求 めよ。 (2)2点 A(-1,1)とB(1,0)を通る直線上の点C(2,α)を放物線のグラフ y=x2乗+X-βは通る。  αとβを求めよ。 以上よろしくお願い致します。

  • グラフの概形をしめす??

    y=x^3+xのグラフの概形を示せと言う問題の解説に「y’=3x^2+1より、全ての実数xに対してy'>0である。したがってこの関数は増加関数であるがy'=0となることがない。また、この関数のグラフは原点に関して対称である。関数の増減だけからこのグラフの形の細かい点について知ることはできないがx=0のときy'=1であることからグラフが原点で直線y=xに接していることがわかる。」とあったのですが、なぜいきなり「この関数のグラフも原点に関して対称である」ということができるのでしょうか?グラフが原点に関して対象ではなく、値は分からないけどx≠0ではないどこかのxの値に関して対称でグラフが原点で直線y=xに接しているということもありえるのではないか?と思えてしまいます・・  お願いします!教えてください!

  • グラフの問題についてですが

    y=x^2 と y=x+6 の交点をA,C y=x^2 と y=x の交点をBと置いたとき A(-2,4) , B(1,1) , C(3,9) となるグラフで 点Aを通り、△ABCの面積を二等分する直線の式がわかりません。 三平方の定理を使わない解き方でお願いします。

  • グラフ表示

    例えば下記のような式を、グラフ表示してみたいのですが できるフリーソフトはありますか。 f(x,y)=xy/(x*x + y*y),(x,y)≠(0,0),f(0,0)=0

  • 両対数グラフでも通常のグラフでも直線に見える関数

    大学の授業でとあるデータをコンピュータでプロットしたのですが、それがよくわからなくて困っています。 両対数グラフで表示しても通常のグラフで表示しても直線に見えるのです。 通る点のうち二つは(1,9.85)(38,265.99)で、通常のグラフでの式を求めてみるとy=6.9227x+2.9273となりました。 グラフで直線に見えるといってもどちらでも微妙に歪んでいて、それがカギかと思うのですが、まったく分かりません。 どうしてこのデータのグラフはそう見えるのでしょうか。 確証がない説でもいいので、教えてください。

  • 4次多項式のグラフ

    4次多項式のグラフをEXCELで書く問題で困っています。 式と完成したグラフはあるのですが、なぜこのグラフになるのか分かりません。 式:F(t)=t^4/4-2*t^3+11*t^2/3-6*t グラフ:y軸が-100~900まで100目盛りづつ、x軸は0~10まで1目盛りづつ グラフにはF(t)とf(t)、2つのグラフがあります。 F(t)は式が与えられているのでなぜこのグラフになるのか理解できますが、f(t)は式もないしなぜこのグラフになるのかわかりません。 f(t)はF(t)のy軸と同じ値(0)から始まりy軸の200辺りで収まっています。 F(t)を計算すると F(t) x軸 0→y軸 0 x軸 1→y軸 -4.0833 x軸 2→y軸 -9.3333 x軸 3→y軸 -18.75 x軸 4→y軸 -29.333 x軸 5→y軸 -32.083 x軸 6→y軸 -12 x軸 7→y軸 51.916 x軸 8→y軸 186.66 x軸 9→y軸 425.25 x軸10→y軸 806.66 になります。 数学は得意ではないので説明が分かりにくいですが、よろしくお願いいたします。

  • グラフの書き方

    工学部の1年です。 周期的に変化する電場での電子の運動を表す式のグラフの書き方が分かりません。 グラフの書き方なのでこのカテゴリーで質問させて頂きます。 mω^2/eE・x(t)=-sinωt+ωt mω^2/eEやωは定数です。 y=ωtに対して振動する-sinωtのグラフになるのですが、その考え方や書き方が分かりません。 回答よろしくお願いします。