[ create a new paste ] login | about

Link: http://codepad.org/WwhXAuuy    [ raw code | fork ]

hecomi - C++, pasted on Jul 14:
#pragma once

/*! @file
 @brief		gnuplotクラス
 @author	hecomi
 @date		July 12, 2010. ver. 1.02

 10/07/05 完成
 10/07/12 ログプロット/reset/PNG出力追加
 10/07/13 マルチプロット
*/

#include <vector>
#include <fstream>
#include <string>

/*! @brief gnuplotを扱うライブラリ
gnuplotを扱うクラスに関するライブラリです.
pgnuplotへとパイプを繋ぎ,関数やデータをgnuplotを用いてプロットする手助けをします.
pgnuplot.exeが環境変数へと登録されている必要があります.
*/
class CGnuplot {
private:
	//! プロットする要素の開始位置と終了位置
	FILE* Fp;

	//! 初期スタイルセットファイル名
	static const char* InitialStyleFileName;

	//! ファイル書き出し時スタイルセットファイル名
	static const char* OutputStyleFileName;

	/*! @brief 一時ファイル名 */
	const std::string TempFileName;

	//! プロットする要素の開始位置と終了位置
	template <class Container>
	struct PlotInfo
	{
		Container begin;	//!< プロット開始位置
		Container end;		//!< プロット終了位置
	};

	/*!
	@brief プロットタイプ
	PLOT_TYPE_LINES			線のみ
	PLOT_TYPE_POINTS		点のみ
	PLOT_TYPE_LINES_POINTS	線と点
	*/
	enum PLOT_TYPE {
		PLOT_TYPE_LINES,
		PLOT_TYPE_POINTS,
		PLOT_TYPE_LINES_POINTS
	} PlotType;

	//! マルチプロットかどうか
	bool IfMultiplot;

	//! プロットファイル用ナンバー初期値
	static const unsigned int DefaultNo;

	//! プロットファイル用ナンバー(Temp(No).dat)
	unsigned int No;

	//! プロットファイル用ナンバーの最大値
	unsigned int MaxNo;

	//! ファイル名取得
	std::string GetPlotFileName();

	/*!
	@brief 初期化
	*/
	void Ini();

	/*!
	@brief バッファフラッシュ
	*/
	void Flush();

	/*!
	@brief プロットコマンド
	*/
	void Plot();

	/*!
	@brief 1次元要素をプロットする
	@param[in] x プロット情報を格納したxデータ
	*/
	template <class T>
	void PlotX(PlotInfo<T> x)
	{
		T it = x.begin;
		std::ofstream fout(GetPlotFileName().c_str());
		if (fout.fail()) {
			std::cout << "Error! (@PlotX)" << std::endl;
			return;
		}
		while (it != x.end) {
			fout << *it << std::endl;
			it++;
		}
		Plot();
	}

	/*!
	@brief 2次元要素をプロットする
	@param[in] x プロット情報を格納したxデータ
	@param[in] y プロット情報を格納したyデータ
	*/
	template <class T>
	void PlotXY(PlotInfo<T> x, PlotInfo<T> y)
	{
		T itX = x.begin, itY = y.begin;
		std::ofstream fout(GetPlotFileName().c_str());
		if (fout.fail()) {
			std::cout << "Error! (@PlotXY)" << std::endl;
			return;
		}
		while (itX != x.end && itY != y.end) {
			fout << *itX << " " << *itY << std::endl;
			itX++; itY++;
		}
		Plot();
	}

	/*!
	@brief 3次元要素をプロットする
	@param[in] x プロット情報を格納したxデータ
	@param[in] y プロット情報を格納したyデータ
	@param[in] z プロット情報を格納したzデータ
	*/
	template <class T>
	void PlotXYZ(PlotInfo<T> x, PlotInfo<T> y, PlotInfo<T> z)
	{
		T itX = x.begin, itY = y.begin, itZ = z.begin;
		std::ofstream fout(GetPlotFileName().c_str());
		if (fout.fail()) {
			std::cout << "Error! (@PlotXYZ)" << std::endl;
			return;
		}
		while (itX != x.end && itY != y.end && itZ != z.end) {
			fout << *itX << " " << *itY << " " << *itZ << std::endl;
			itX++; itY++; itZ++;
		}
		Plot();
	}

	/*!
	@brief プロットタイプに応じた文字列を取得
	*/
	std::string GetPlotType();

public:
	/*! @brief コンストラクタ */
	CGnuplot();

	/*!
	@brief コンストラクタ
	複数のGnuplotを起動した際に,同名のプロットデータファイルが衝突すると,
	所望のプロット結果が得られないので,プロットデータファイル名を指定しなければならない.
	@param[in] fileName プロット時に生成するデータファイルの名前
	*/
	CGnuplot(const char* fileName);

	/*! @brief デストラクタ */
	~CGnuplot();

	/*! @brief 正常に機能しているかどうか */
	bool Check();
	
	/*!
	@brief printfライクにgnuplotのコマンドを実行
	@param[in] format printfに用いるフォーマット
	@param[in] ... 可変長引数
	*/
	void Command(const char* format, ...);

	/*!
	@brief 関数をプロット
	Ex. DrawFunc("sin (x)")
	@param[in] format プロット対称関数文字列
	*/
	void DrawFunc(const char* func);

	/*!
	@brief 1次元要素をプロットする
	@param[in] cont プロット対称コンテナ
	*/
	template <class T, template <class A, class Allocator = std::allocator<A> > class Container>
	void Plot(Container<T> cont)
	{
		PlotInfo<Container<T>::iterator> pi = { cont.begin(), cont.end() };
		PlotX(pi);
	}

	/*!
	@brief 1次元要素をプロットする(配列)
	@param[in] cont プロット対称配列
	*/
	template <class T, int N>
	void Plot(T (&cont)[N])
	{
		PlotInfo<T*> pi = { &cont[0], &cont[N-1] };
		PlotX(pi);
	}

	/*!
	@brief 2次元要素をプロットする
	@param[in] contX プロット対称コンテナ(x)
	@param[in] contY プロット対称コンテナ(y)
	*/
	template <class T, template <class A, class Allocator = std::allocator<A> > class Container>
	void Plot(Container<T> contX, Container<T> contY)
	{
		PlotInfo<Container<T>::iterator> 
			piX = { contX.begin(), contX.end() },
			piY = { contY.begin(), contY.end() };
		PlotXY(piX, piY);
	}

	/*!
	@brief 2次元要素をプロットする(配列)
	@param[in] contX プロット対称配列(x)
	@param[in] contY プロット対称配列(y)
	*/
	template <class T, int N, int M>
	void Plot(T (&contX)[N], T (&contY)[M])
	{
		PlotInfo<T*> 
			piX = { &contX[0], &contX[N] },
			piY = { &contY[0], &contY[M] };
		PlotXY(piX, piY);
	}

	/*!
	@brief 3次元要素をプロットする
	@param[in] contX プロット対称コンテナ(x)
	@param[in] contY プロット対称コンテナ(y)
	@param[in] contZ プロット対称コンテナ(z)
	*/
	template <class T, template <class A, class Allocator = std::allocator<A> > class Container>
	void Plot(Container<T> contX, Container<T> contY, Container<T> contZ)
	{
		PlotInfo<Container<T>::iterator> 
			piX = { contX.begin(), contX.end() },
			piY = { contY.begin(), contY.end() },
			piZ = { contZ.begin(), contZ.end() };
		PlotXYZ(piX, piY, piZ);
	}

	/*!
	@brief 3次元要素をプロットする(配列)
	@param[in] contX プロット対称配列(x)
	@param[in] contY プロット対称配列(y)
	@param[in] contZ プロット対称配列(z)
	*/
	template <class T, int N, int M, int L>
	void Plot(T (&contX)[N], T (&contY)[M], T (&contZ)[L])
	{
		PlotInfo<T*> 
			piX = { &contX[0], &contX[N] },
			piY = { &contY[0], &contY[M] },
			piZ = { &contZ[0], &contZ[L] };
		PlotXYZ(piX, piY, piZ);
	}

	/*!
	@brief 2次元マルチプロット(STLコンテナ限定)
	@param[in] contX プロット対称配列(x)
	@param[in] contY プロット対称配列(y)
	@param[in] contZ プロット対称配列(z)
	*/
	template <class T, template <class A, class Allocator = std::allocator<A> > class Container>
	void Multiplot(Container<T> x, Container<std::pair<std::string, Container<T> > > ys)
	{
		// 念のため
		No = DefaultNo;

		// プロット開始
		Command("plot \\");

		// ファイルへ書き出し
		std::ofstream fout(GetPlotFileName().c_str());
		if (fout.fail()) {
			std::cout << "Error! (@Multiplot)" << std::endl;
			return;
		}

		// 第2引数の展開
		Container<std::pair<std::string, Container<T> > >::iterator itYs = ys.begin();
		unsigned int i = 1;
		while (itYs != ys.end()) {
			// ペアの展開
			std::pair<std::string, Container<T> > pair = *itYs;
			std::string title = pair.first;
			Container<T> y = pair.second;

			// イテレータ指定
			Container<T>::iterator itX = x.begin(), itY = y.begin();

			while (itX != x.end() && itY != y.end()) {
				fout << *itX << " " << *itY << std::endl;
				itX++; itY++;
			}
			fout << std::endl << std::endl;

			// プロット
			Command("'%s' ind %d w %s ls %d ti '%s'\\", GetPlotFileName().c_str(), i-1, GetPlotType().c_str(), i, title.c_str());
			if (i < ys.size()) {
				Command(",\\");
			} else {
				Command("");
				break;
			}

			itYs++;
			i++;
		}
	}


	/*!
	@brief プロットタイプ(線,点,線と点)をセット
	*/
	void SetPlotType(PLOT_TYPE plotType);

	/*!
	@brief マルチプロット(複数の図をプロット)の切り替え
	@param[in] sw true: マルチプロット false: 解除
	*/
	void SetMultiplot(bool sw = true);

	/*!
	@brief ラベルをセット
	@param[in] title タイトル
	*/
	void SetTitle(const char* title);

	/*!
	@brief ラベルをセット
	@param[in] labelX Xラベル名
	@param[in] labelY Yラベル名
	*/
	void SetLabel(const char* labelX, const char* labelY);

	/*!
	@brief プロット範囲を指定
	@param[in] min x軸プロット範囲最小値
	@param[in] min y軸プロット範囲最小値
	*/
	void SetXRange(const double min, const double max);

	/*!
	@brief プロット範囲を指定
	@param[in] min y軸プロット範囲最小値
	@param[in] min y軸プロット範囲最小値
	*/
	void SetYRange(const double min, const double max);

	/*!
	@brief リプロット
	*/
	void Replot();

	/*!
	@brief 設定全リセット
	*/
	void Reset();

	/*!
	@brief 片対数プロットに変更
	*/
	void SetLogPlotY(bool sw = true);

	/*!
	@brief 現在プロットしているデータをファイルに書き出す
	中身はTempFileNameに保存されているデータをコピーしているだけ
	@param[in] fileName 書き出し先ファイル名
	*/
	void DumpToFile(const char* fileName);

	/*!
	@brief 現在プロットしているデータをEPSで書き出す
	@param[in] fileName 書き出し先ファイル名
	*/
	void DumpToEps(const char* fileName);

	/*!
	@brief 現在プロットしているデータをPNGで書き出す
	@param[in] fileName 書き出し先ファイル名
	*/
	void DumpToPng(const char* fileName);

	/*!
	@brief 外部ファイルからコマンドを読み込み実行
	@param[in] fileName 読み込み元ファイル名
	*/
	void CommandFromFile(const char* fileName);
};


Create a new paste based on this one


Comments: