#SVG形式
個人的にベクター形式の画像が必要になり,かといってepsをプログラムで出力するのは大変そうだ。と思っていたところ,以下のようなSVGと呼ばれるHTMLのように簡単に書けるベクターフォーマットがあることがわかりました。
なんか簡単そうですね。
C++の簡易ラッパーは以下で見つけることができました。
これにはPolyline関数はなかったのですが、簡単に作れそうだったので、上記を参考にopencvのPoint形式でSVG出力できるクラスを作ってみました。透過色も指定できるようです。とりあえず、僕はPolylineが使えれば十分だったので、それしかないのですが、ほかの描画関数も簡単に追加できると思います。
svg.h
#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を読み込むだけで使えます。
main.cpp
#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に図を張り付けることができます。