SVG形式
個人的にベクター形式の画像が必要になり,かといってepsをプログラムで出力するのは大変そうだ。と思っていたところ,以下のようなSVGと呼ばれるHTMLのように簡単に書けるベクターフォーマットがあることがわかりました。
なんか簡単そうですね。
C++の簡易ラッパーは以下で見つけることができました。
これにはPolyline関数はなかったのですが、簡単に作れそうだったので、上記を参考にopencvのPoint形式でSVG出力できるクラスを作ってみました。透過色も指定できるようです。とりあえず、僕はPolylineが使えれば十分だったので、それしかないのですが、ほかの描画関数も簡単に追加できると思います。
# include <fstream>
# include <iostream>
# include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class svg_drawer {
	std::ofstream fout;
	int width, height;
public:
	svg_drawer(char *filename, int w, int h) {
		fout.open(filename);
		width  = w;
		height = h;
		
		fout << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width= \"" << width << "\" height=\"" << height << "\">" << std::endl;
	}
	~svg_drawer(void) {
		fout << "</svg>" << std::endl;
		return;
	}
	void drawPolyLine(const vector<Point2d> & pts, Scalar col, int stroke_width, Scalar fcol, int dash = 0, double opacity = 1.0) {
		char stroke_color[255];
		char fill_color[255];
		sprintf(stroke_color, "rgb(%d,%d,%d)", (int) col[2], (int) col[1], (int) col[0]);
		sprintf(fill_color,   "rgb(%d,%d,%d)", (int)fcol[2], (int)fcol[1], (int)fcol[0]);
		fout << "<polyline points=\"";
		int N = pts.size();
		for (int i = 0; i <= N; i++) {
			double vx = pts[i%N].x;
			double vy = pts[i%N].y;
			fout << vx << "," << vy << " ";
		}
		fout << "\"";
		if (dash > 0) fout << " stroke-dasharray=\"" << dash << "\"";
		fout << " stroke-width=\"" << stroke_width << "\" stroke=\"" << stroke_color << "\" fill=\"" << fill_color << "\" fill-opacity=\"" << opacity << "\"/>" << std::endl;
		return;
	}
	void drawLine(const double x0, const double y0, const double x1, const double y1, int stroke_width, Scalar col, int dash = 0, double opacity = 1.0) {
		char stroke_color[255];
		sprintf(stroke_color, "rgb(%d,%d,%d)", (int)col[2], (int)col[1], (int)col[0]);
		
		fout << "<line x1=\"" << x0 << "\" y1=\"" << y0 << "\" x2=\"" << x1 << "\" y2=\"" << y1 << "\"";
		if (dash > 0) fout << " stroke-dasharray=\"" << dash << "\"";
		fout << " stroke-width=\"" << stroke_width << "\" stroke=\"" << stroke_color << "\" stroke-opacity=\"" << opacity << "\"/>" << std::endl;
		return;
	}
};
サンプル
上のクラスを使って適当な図形を描画します。svg.hを読み込むだけで使えます。
# include <stdio.h>
# include "svg.h"
int main(){
	
	svg_drawer sd("test.svg", 500,500);
	int div = 360;
	for (int n = 0; n < 50; n++) {
		vector<Point2d> pts;
		int   dx = rand() % 500;
		int   dy = rand() % 500;
		float dr = (rand() % 100) / 100.0;
		float dt = rand() % 30 + 3;
		for (int i = 0; i < div; i++) {
			float t = 2 * 3.14159 * i / float(div);
			float x, y, r;
			r = dr * (50 + sin(dt * t) * 20);
			x = dx + r * cos(t);
			y = dy + r * sin(t);
			pts.push_back(Point2d(x, y));
		}
		sd.drawPolyLine(pts, CV_RGB(rand() % 255, 0, 0), 1, CV_RGB(rand() % 255, rand() % 192, rand() % 32), 0, 0.5);
	}
	return 0;
}
実行するとtest.svgというファイルができます。ファイルをダブルクリックしてブラウザなどで開けます。ブラウザ上でCtrを押しながらマウスホイールすると拡大できます。ベクター形式なので拡大してもきれいです。イラストレータなどのペイントツールで開いて、epsに変換すればパワーポイントやlatexに図を張り付けることができます。

