読者です 読者をやめる 読者になる 読者になる

凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

C++からgnuplotを使って複数グラフをプロット

gnuplot C++

(追記: 11/1/19)
最新版はこちらになります:d:id:hecomi:20101209:1291888423

                                                                                                            • -

C++からgnuplotをパイプをつなげて使用するクラス,CGnuplotを作成しましたが(id:hecomi:20100709:1278686045),マルチプロットも出来るようにしたのでご紹介します.
gnuplot.h:   http://codepad.org/WwhXAuuy
gnuplot.cpp:  http://codepad.org/5v7DKGaM
NYSLライセンスなので,気が向いたらどうぞ.

マルチプロットするための2つの手法

gnuplotには,複数のグラフをプロットする為に2つの方法が用意されています.

multiplotの使用

1つは,set multiplotを使用する方法です.

gnuplot > set multiplot
gnuplot > set xrange[-1:1]
gnuplot > set yrange[-1:1]
multiplot > plot x*x
multiplot > plot x*x*x
multiplot > unset multiplot
gnuplot >


ただ,完全にグラフを重ねあわせるだけですので,縦軸がずれる場合はグラフが汚くなってしまいますので,rangeをセットしておく必要があります.
これをCGnuplotを用いると次のように書けます.コードは数値計算を前提に,vectorに代入したものを用いています.makeVectorとsetVectorはid:hecomi:20100712:1278892595に書いてあります.

vector<double> x, y1, y2;

// -1〜1を100等分したベクトルを作成
makeVector(x, -1.0, 1.0, 100);

// boost::lambdaを用いて,x^2とx^3のベクトルを作成
setVector(y1, x, _1*_1);
setVector(y2, x, _1*_1*_1);

// CGnuplotによるマルチプロット
CGnuplot gp;
gp.SetMultiplot();
gp.SetXRange(-1.0, 1.0);
gp.SetYRange(-1.0, 1.0);
gp.Plot(x, y1);
gp.Plot(x, y2);
gp.SetMultiplot(false);


となります.ただし凡例に付いては重なって汚くなってしまうため,機能に追加しておりません.凡例を付けたい場合は,次のMultiplotメンバ関数を使用してください.簡単にプロットしたい場合はsetMultiplotを利用することをお勧めします.

plot A, B, C...

2つ目は,plotをカンマ区切りで利用する方法です.こちらではタイトルを重ねずに表示できることから,凡例を表示したい場合におすすめです.

gnuplot > set xrange[-1:1]
gnuplot > set yrange[-1:1]
gnuplot > plot x*x ti "y = x^2", x*x*x ti "y = x^3"

これをC++で書くと次のようになります.ちょっと手間がかかります.

vector<double> x, y1, y2;

// -1〜1を100等分したベクトルを作成
makeVector(x, -1.0, 1.0, 100);

// boost::lambdaを用いて,x^2とx^3のベクトルを作成
setVector(y1, x, _1*_1);
setVector(y2, x, _1*_1*_1);

// std::pairにfirst: 凡例名, second: vectorで入れる
pair<string, vector<double> >
	pair1("y = x^2", y1),
	pair2("y = x^3", y2);

// std::vector<std::pair>に格納
vector<pair<string, vector<double> > > plotData;
plotData.push_back(pair1);
plotData.push_back(pair2);

// CGnuplotによるマルチプロット
CGnuplot gp;
gp.SetXRange(-1.0, 1.0);
gp.SetYRange(-1.0, 1.0);
gp.Command("set key right bottom");
gp.Multiplot(x, plot Data);


となります.もっと良いプロット方法無いですかね….ちょっとpairの入ったvectorが気持ち悪いので….
ちなみにPNG/EPS出力も以下のようにすれば可能です.

// とりあえずラベルをつけておく
gp.SetLabel("x", "y");

// EPS出力
gp.DumpToEps("plotData");
// gp.DumpToPng("plotData"); // PNG出力

補足:初期化ファイル

コンストラクタで「macro\initial.txt」,EPS出力時に「macro\output_line.txt」を読み込むようにしています.これは次のようなファイルを読み込んでいます.

initial.txt

set style line  1 linetype  1 linewidth 2
set style line  2 linetype  2 linewidth 2
set style line  3 linetype  3 linewidth 2
set style line  4 linetype  4 linewidth 2
set style line  5 linetype  5 linewidth 2
set style line  6 linetype  6 linewidth 2
set style line  7 linetype  7 linewidth 2
set style line  8 linetype  8 linewidth 2
set style line  9 linetype  9 linewidth 2
set style line 10 linetype 10 linewidth 2

output_line.txt

set style line  1 linetype  1 linewidth 6
set style line  2 linetype  2 linewidth 6
set style line  3 linetype  3 linewidth 6
set style line  4 linetype  4 linewidth 6
set style line  5 linetype  5 linewidth 6
set style line  6 linetype  6 linewidth 6
set style line  7 linetype  7 linewidth 6
set style line  8 linetype  8 linewidth 6
set style line  9 linetype  9 linewidth 6
set style line 10 linetype 10 linewidth 6

最後に

興味が向いたら,使って頂けると嬉しいです.フィードバックも頂ければ幸いです.
マニュアルについてはDoxygenを通せば生成されると思いますので,メンバ一覧を見たい方はインストールしてマニュアルを生成してみてください.

追記 10/07/16

これだと,x軸のベクトルが同じでない場合のプロットが出来ないですね.
新たなダウンロード先は以下になります.
gnuplot.h : http://codepad.org/TrefNHjy