こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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

こんにちは、C言語においてグラフを表示することで質問があります。

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

すぐに返信できないかもしれませんが。よろしくお願いします。

投稿日時 - 2007-08-26 15:04:20

QNo.3287972

困ってます

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

あぁ、魚の群れの行動というのだから、たとえば、魚一匹ごとに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;
}

投稿日時 - 2007-08-28 04:15:29

補足

すいません。変換ミスです。群行動が正しいです。
私は、VC++を使ってC言語をくんでいますが、
実行すると、#include <unistd.h>がどうもひっかかるみたいでした。
そこで、ヘッダファイルを適当に?どうにかしてみたところ。
(人が作っていたものをコピーして、インクルードフォルダにコピペしてみた)
実行をすることができました!!
ただ、コマンドラインで打ち込む方法がわからなかったので、
myproglam | pgnuplot をできませんでした・・・汗
アクセサリからコマンドプロントを探し、プログラムのあるファイルに移動して、myproglam | pgnuplotとは
入力してみたのですが、うまくいかなかったようです。
実行ファイルはプログラムとは違うところに保存されるのでしょうか。

実行して同じフォルダにできた拡張子をみてみると、
プロジェクトファイル、ncb,,opt,と書いてありました。

そこで、LINUXで動かしたのですが、gccでコンパイルして、
みると、a.out と言うのができたのですが。
myproglam | pgnuplot と打ってもcannot found しかでませんでした。
この↑記述の意味がよくわからないので、、、
a | pgnuplot とか、、、いろいろしてみたのですが、、ダメでした。


今からもう少し調べてみようと思っています。お返事ありがとうございます。

投稿日時 - 2007-08-28 17:19:53

お礼

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

投稿日時 - 2007-08-28 17:47:50

ANo.11

このQ&Aは役に立ちましたか?

10人が「このQ&Aが役に立った」と投票しています

回答(19)

ANo.19

理解できてよかったですね^^

サンプルプログラムの adavance で、次の表示時刻の魚群の位置を設定しておけば、とりあえず、魚一匹を一点で表現した魚群の動いている様子を見せることができると思います。

プレゼンテーションなどで、それっぽい魚を描いたり、水中を再現した背景にしたいなど、もっときれいに見せたいというなら、それ相応のグラフィックライブラリを使うのがいいと思います。Linux 環境などでは、vtk を使うとか、もっと凝りたいなら OpenGL(Mesaなど)で直接コーディングするとか(そこまで凝る必要があるのかとは思いますが…笑)。わたしはグラフィックスはぜんぜん詳しくないので、もし凝りたくて、ご自分で探して見つけられないというのであれば、グラフィック専門のところへ、「どういうツール・ライブラリがいいのか」、質問するのがいいんじゃないかと思います。

gnuplot でも結構いろいろなことができるので、gnuplot の demo フォルダにある all.dem を動かして、どんなことができるのか、一度、見てみるのもいいかもしれません。「じゃあ、こうしよう♪」というインスピレーションが沸くかもしれませんしね。では、研究がんばってください。

投稿日時 - 2007-08-29 16:40:31

補足

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

本当にありがとうございました。

投稿日時 - 2007-08-29 17:12:57

ANo.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 コマンドを発行させないようにするなどの方法を取ればよいでしょう。

投稿日時 - 2007-08-29 00:43:31

ANo.17

もう一つ追加:

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

投稿日時 - 2007-08-28 23:52:46

ANo.16

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

投稿日時 - 2007-08-28 23:49:47

ANo.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 に指示するものです。

投稿日時 - 2007-08-28 23:43:53

お礼

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

投稿日時 - 2007-08-29 13:43:50

ANo.14

ありゃ。。。もううまく言ってた訳ですね。よかったよかった。

プログラムは適当に使えるものは利用して、研究をしっかりとがんばってください(笑)

投稿日時 - 2007-08-28 18:14:44

補足

ありがとうございます!
途中でカレントフォルダから相対パス・・・
と書いてあるところを読んで気づきました!!!

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

投稿日時 - 2007-08-28 20:24:50

ANo.13

あっ、そうそう^^ unistd.h って、Unix 環境のヘッダだから、Windows ではないかもしれません(POSIX 対応のがあればあるのかもしれないけど、詳しくない^^;)。

unistd.h は sleep() を使うために include してるだけなので、もし、sleep() を使うことでリンクエラーになるなら、sleep() のところを削除してもかまいません(点の動きが早くて、描画状態がわからないかもしれませんけどね^^)。

投稿日時 - 2007-08-28 18:12:19

ANo.12

パスの通し方がわからなければ、すべて、カレントディレクトリからの相対パスで書けばいいんじゃないですか?わたしの場合は、たとえば、

 > "..\home\watashi\work\c\myprogram" | "d:\downloads\gnuplot\gnuplot\bin\pgnuplot"

と打つと、うまくいきます。絶対パスで指定してもいいですけど、パスを通しておくのが簡単ですけどね(笑)

投稿日時 - 2007-08-28 18:08:58

ANo.10

> 自分で描画を行う場合には、わざわざ外部ファイルに…

それはそのとおりだと思います。自作の描画機能で、わざわざ外部ファイルに出力するように設計する人は、まれでしょう^^

まぁ、kenpanch7さんは、学生さんで、研究の補助として「動いている」ように見える描画機能がほしいだけみたいで、そこそこ動けばよいようですし、「暇なときに見てみます」って回答なので、そんなにまじめに作るほど重要でもないんでしょう(笑)それに「あるものは使えばいい」し、「自分で探して見つからなければ、人に聞くのもいい」でしょ。

投稿日時 - 2007-08-27 13:05:54

お礼

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

投稿日時 - 2007-08-28 18:07:17

ANo.9

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

投稿日時 - 2007-08-27 06:39:14

補足

Cの開発環境は、今はVC++を使っています。
ただ、今回の件もあり、今後LINUXを入れてみようと思っています。
また、picturebox という単語は初めて聞きました。パイプというのも初めてでしたが・・・・汗

また、研究内容は、(研究というほどのものでもないですが)
魚を三次元で動かし、群行動をさせることを目標としています。
道は長いみたいです。ありがとうございます。
せっかくなのでpictureboxについても調べてみようと思います。
アドバイスありがとうございます!

投稿日時 - 2007-08-28 17:32:55

ANo.8

議論する気はないんですけど^^;

きっちりとした既存のプログラムが使えればOKでしょう。どうせ作っても、大体は自作のものよりすぐれていますよ(笑)それに、仕事でも、その作業がどれくらいの期間・コストでできるかを見積もるのに、どういうものが使えるのか調べるのがほんとのとこでしょう。すべて自作するコストを受注金額に含ませられるとしたら幸せなことですけどね^^

ところで、意味的には「群行動」のほうがぴったり来るような気がするんですが、学問的には「群行動」じゃなく、「郡行動」が正しいんですか?

投稿日時 - 2007-08-27 04:26:01

ANo.7

ご参考:(サンプルプログラム)
以下のプログラムをコンパイル・リンクして実行ファイル(myprogram.exe という名前だったとします)を作成し、
  myprogram | pgnuplot
とコマンドラインで打ち込むと、(0,0)から(9,9)までの y=x のグラフが表示されるます(カレントフォルダとpgnuplot.exeがインストールされているフォルダにパスが通っている仮定して。パスの通し方がわからなければ、カレントフォルダからの相対パスあるいは絶対パスでmyprogramとpgnuplotを指定するといいです)。

・sleep() は経過状況が目で見てわかるように入れているだけです。
・xrange、yrange の設定は、途中で目盛りが変わると見にくいので設定しているだけです。
・グラフ表示させたいデータを一度ファイル(aaa.txt という名前だとします)に保存してから
  plot 'aaa.txt'
として描かせる(再描画の場合は replot と出力する)のでもいいですが、このサンプルでは、gnuplot へ与える指示と表示させたいデータもまとめて標準出力に出力しています(なので、こちらは、replot は使わず plot のみ使う)。
===
#include <stdio.h>
#include <unistd.h>

int main(void)
{
struct Point {
float x, y;
} points[] = {
{ 0.0, 0.0 },
{ 1.0, 1.0 },
{ 2.0, 2.0 },
{ 3.0, 3.0 },
{ 4.0, 4.0 },
{ 5.0, 5.0 },
{ 6.0, 6.0 },
{ 7.0, 7.0 },
{ 8.0, 8.0 },
{ 9.0, 9.0 },
};
const int n = sizeof points / sizeof points[0];
int i, j;

puts("set xrange [0:9]");
puts("set yrange [0:9]");
for (i = 0; i < n; ++i) {
puts("plot \'-\' with linespoint");
for (j = 0; j <= i; ++j) printf("%f %f\n", points[j].x, points[j].y);
puts("e");
fflush(stdout);
sleep(2);
}
return 0;
}

投稿日時 - 2007-08-27 01:18:35

補足

本当に親切にありがとうございます,
いま,あまり深くよんでいないので,また近いうちに熟読してみたいと思います。この掲示板を読んだりしていると,C言語の奥深さに,,
たじたじです。学校の授業のレベルがまだまだだなと感じさせられました。少しがんばってみたいと思います。
本当にありがとうございました。

投稿日時 - 2007-08-27 03:30:16

ANo.6

ANo,3補足
元質問者がどういった事情(趣味、学校の課題、仕事)で
必要としているか判りませんが、少なくとも仕事の場合
であれば、自力(自社内または協力会社を含む)で作成が
可能か否かをまず判断します。
既存の物で利用できる物があるかどうかを探すのはその
後の事になります。
仕事を受けた後になって、「Web検索してみたけれど使え
そうな物がなかったからできません」といった言い訳など
プロの仕事としては通用しません。

....で、どういう事で必要としているのでしょうか?
#趣味、学校の課題、仕事、その他

投稿日時 - 2007-08-26 21:41:36

補足

私は,今,大学の四年生で,学校の課題というか,研究テーマ(郡知能)を与えられ,それに関する論文をよみ,その論文に書いてある式をもとに,魚の郡行動の動きをC言語で作っているところでした。
魚が動く点を求めることはできたのですが,それを魚が動いてるように見せたいなと思い,今回のような質問をいたしました。

というような感じです。たしかに仕事では通用しない世界とわたしも思います。
ご回答ありがとうございます。

投稿日時 - 2007-08-27 03:23:40

ANo.5

C言語でどういった物が作られているかを知ってさえ
いれば、別に自分が作れる必要はないのですが...
#とりあえず、折れ線グラフの逐次表示であれば以前に
#UNIX C(Motif)を使って作成した事が有ります。

折れ線グラフの表示程度であれば、座標軸とデータの
範囲に応じた目盛やデータの表示位置を計算して出力
すれば良いだけです。
その程度の計算であれば、高校数学の知識ぐらいでも
十分に作成可能です。

グラフ表示用ソフトを探すよりも、グラフ自体を表示
するのに必要な計算式、モジュールを探した方が結果
が出るのが早い様に思います。

投稿日時 - 2007-08-26 19:56:52

ANo.4

自分で、ほんとに探して見つけられなければ、人に聞くのはいいことだと思いますよ。ほんとは存在するのに存在しないと思って、自分で作ろうとするのは、車輪の再発明で、労力の無駄でしょう(スキルアップのためなら別ですが)。

自分で全然探しもしないで人になんでも聞くのはどうかとは思いますけど^^

don_go さんって方は、「C言語を使えば大抵の物が作れる」能力の持ち主なんでしょうけどね(笑)

投稿日時 - 2007-08-26 18:56:07

ANo.3

>フリーソフトなどを探したのですが、よくわかりませんでした。
求めている物がなければ、自分で作れば良いだけです。

>C言語では逐次的に表現などできないとか
C言語を使えば大抵の物は作れます。
#作る人の能力・期間しだいですが...

投稿日時 - 2007-08-26 18:34:42

ANo.2

補足:

gnuplot のインストールフォルダの bin フォルダの下に pgnuplot というのがある(wgnuplot とは違う)ので、それを使えばできるでしょう。

> myprogram | pgnuplot

投稿日時 - 2007-08-26 17:08:35

ANo.1

Windows に Unix のパイプ機能みたいなのがあるんでしたっけ?そういうのがあれば、
  % myprogram | gnuplot
Cプログラム(myprogram)の中では、gnuplot へのコマンドを標準術力に出してやるだけでOKですが。。。
  …
  FILE *fp = fopen("aaa.txt", "w");
  fprintf(fp, ...);   /* 表示させる数値を書き込む */
  fflush(fp);
  printf("plot \'aaa.txt\'\n"); /* gnuplot への支持 */
  fflush(stdout);
  fprintf(fp, ...); /* 追加の数値を書き込む */
  fflush(fp);
  printf("replot\n");
  fflush(stdout);
  …

パイプのようなものがなければ(cygwin をインストールしても、Unix 環境を作ってもいいですが(笑))、Cプログラム内で gnuplot と接続するようにプログラムを組んで、上と同様のことをすればいいのではないかと思います。Cから呼べる関数として提供されているグラフアプリケーションがあればもっとやりやすいですけどね。わたしは適当なものを知りません^^;

投稿日時 - 2007-08-26 16:39:16

あなたにオススメの質問