NPlot にPDF出力機能を追加しました
オリジナルのNPlotは出力先として、ベクタ系の画像をサポートしていないようだったので、
PDFを作成できるライブラリiTextSharpを使って、PDF出力機能を追加しました。
LaTeX用のグラフを出力できるプログラムを作りたいというのが開発動機です。
iTextSharp.text.Document document = new iTextSharp.text.Document(new iTextSharp.text.Rectangle(600.0f, 500.0f), 0,0,0,0);
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document, fs);
document.Open();
iTextSharp.text.pdf.BaseFont bf = iTextSharp.text.pdf.BaseFont.CreateFont(
iTextSharp.text.pdf.BaseFont.EMBEDDED);
s2d.Legend = new NPlot.Legend();
s2d.Legend.AttachTo(NPlot.PlotSurface2D.XAxisPosition.Top, NPlot.PlotSurface2D.YAxisPosition.Right);
s2d.Legend.VerticalEdgePlacement = NPlot.Legend.Placement.Inside;
s2d.Legend.HorizontalEdgePlacement = NPlot.Legend.Placement.Inside;
s2d.Legend.XOffset = -5;
s2d.Legend.YOffset = 0;
s2d.Legend.Font = new Font(FontFamily.GenericMonospace, 30.0f);
s2d.Add(barPlot1);
s2d.Add(line1);
s2d.Add(pointPlot1);
s2d.Refresh();
document.Close();
そこで、NPlotが使っているGraphicsの機能をIGraphicsインタフェースに書き出して、グラフを作成するクラスにGraphicsを渡す代わりに、必要な描画機能をメンバとして持っているIGraphicsインタフェースを渡します。IGraphicsの実装として、Graphicsをほぼそのままラップしたものと、PdfContentByteをラップしたものの2つを用意し、PDF用ではPdfContentByteをラップしたものを使って、それ以外(Windowやビットマップ用、つまり従来からあるもの)ではGraphicsをラップしたものを使うようにしてあります。
Penの属性として、Color、Width、Dash(あと確認してませんがEndCapとLineJoinも一応対応させてみました)が使えます。
BrushはSolidBrushのみ使えます。それ以外のBrushをいれても多分認識しません。
関連
- NPlot で値の表示範囲を設定する方法
- NPlot でマーカー付き折れ線グラフを使いたい!
- NPlot にPDF出力機能を追加しました
- グラフ作成ライブラリNPlot
もっちーの小部屋 自作のソフトを公開してます。
http://www.geocities.jp/mocchi_2003/index.html
グラフ作成ライブラリNPlot
現れてくれました。
| ライセンスは独自のものですが,下の文字列をクレジットやドキュメントに
| 入れることを条件にバイナリのみの配布を認めていますので、
| ほぼBSDライセンスと同じ扱いで問題なさそうです。
| "This product includes software developed as
| part of the NPlot library project available
| from: http://www.nplot.com/"
| (This product の部分は適宜変更してOKだそうです)
[追記]現在、バージョンは0.9.10.0です。0.9.9.2 => 0.9.10.0 の変更の際に、
ライセンスがBSDライセンスに変更された模様です。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
NPlot.PointPlot pointPlot1 = new NPlot.PointPlot();
pointPlot1.DataSource = new int { 3, 1, 2, 3, 4, 3, 5, 2, 1, 1 };
this.plotSurface2D1.Add(pointPlot1);
NPlot.LinePlot linePlot1 = new NPlot.LinePlot();
// Excelの散布図のような使い方もできる
// ☆を描いてみました
linePlot1.AbscissaData = new int { 1, 5, 2, 3, 4, 1}; // 横軸
linePlot1.OrdinateData = new int[] { 3, 3, 1, 4, 1, 3}; // 縦軸
this.plotSurface2D1.Add(linePlot1);
this.plotSurface2D1.Refresh();
関連
- NPlot で値の表示範囲を設定する方法
- NPlot でマーカー付き折れ線グラフを使いたい!
- NPlot にPDF出力機能を追加しました
- グラフ作成ライブラリNPlot
前回作ったライブラリを実際に使ってみた
簡単なサンプルを作ってみました。
↓ライブラリ紹介エントリ
http://blogs.yahoo.co.jp/mocchi_2003/38911375.html
テクスチャのサイズが2のn乗になっていないので、OpenGLのバージョンが古い環境では
動かないかもしれません。
#include <cstdio>
#include <cmath>
#include <GL/freeglut.h>
#include "font_renderer.h"
#define HEIGHT 300
int width, height;
double rad = 0.0, scale = 1.0;
font_renderer fl;
GLuint fonttex;
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)width, (GLdouble)height, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glColor3d(1.0, 1.0, 1.0);
glTranslated*1;
glGenTextures(1, &fonttex);
glBindTexture(GL_TEXTURE_2D, fonttex);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, fl.get_width(), fl.get_height(), GL_RGB, GL_UNSIGNED_BYTE, fl.get_image());
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
window = glutCreateWindow("Hello" );
init();
glutMainLoop();
glDeleteTextures(1 , &fonttex);
関連
- font_rendererバージョンアップ
- 前回作ったライブラリを実際に使ってみた
- ネイティブAPIを用いたマルチプラットフォームフォントレンダラーライブラリ
*1:GLdouble)(width/2), (GLdouble)(height/2), 0.0);
glScaled(scale, scale, 0.0);
glBindTexture(GL_TEXTURE_2D, fonttex);
glBegin(GL_POLYGON);
glTexCoord2d(0.0, 0.0); glVertex2i(-fl.get_width()/4, -fl.get_height()/4);
glTexCoord2d(0.0, 1.0); glVertex2i(-fl.get_width()/4, fl.get_height()/4);
glTexCoord2d(1.0, 1.0); glVertex2i( fl.get_width()/4, fl.get_height()/4);
glTexCoord2d(1.0, 0.0); glVertex2i( fl.get_width()/4, -fl.get_height()/4);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPushMatrix();
glColor3d(1.0, 1.0, 0.6);
glTranslated((GLdouble)WIDTH/2.0,(GLdouble)HEIGHT/2.0,0.0);
glRotated(rad, 0.0, 0.0, 1.0);
glTranslated(-(GLdouble)WIDTH/2.0,-(GLdouble)HEIGHT/2.0,0.0);
glBegin(GL_TRIANGLES);
glVertex2d(150.0, 0.0);
glVertex2d(0.0, 280.0);
glVertex2d(280.0, 280.0);
glEnd();
glPopMatrix();
}
display_3d();
display_2d();
glutSwapBuffers();
glViewport(0, 0, width, height);
display();
rad += 5.0;
scale = 2.0 + std::sin(rad/180.0 * 3.14159265358979);
display();
glutTimerFunc(10, timer, 0);
if (texsize < height) texsize = height;
if (texsize > 0) --texsize;
while(texsize){
++scale;
width = height = (1 << scale);
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(10, timer, 0);
fl.render("☆OpenGLテスト★", 80, false, false, false,
ネイティブAPIを用いたマルチプラットフォームフォントレンダラーライブラリ
文字列(特に日本語などの多バイト文字列)を扱うのがちょっと面倒です。
そのようなことができるライブラリとして有名なものにFreeTypeなどがありますが、
これを利用するためには、適切にフォントを設定する必要があるため、プログラムに
組み込む際にフォントを組み込むか、フォントがある位置を指定する必要があったりする
ため、フォントの設定はどうでもいいからとにかく文字列を描画したい、というときには
面倒だったり実行ファイルのサイズが大きくなりすぎたりしてちょっとオーバースペックになってしまいます。
そこで、ネイティブAPIの機能(WindowsならTextOut、X11ならXmbDrawString)を利用して、
文字列のレンダリングを行うC++用ライブラリを作ってみました。
レンダリングした結果はRGB配列画像データとして取得できるようにしてありますので、
画像ファイルとして扱ったり、3Dプログラミング用テクスチャとして扱ったり、
(ちょっと冗長ですが)ウィンドウに描画したりと色々な用途に使えます。
レンダリングする文字列の特性として
文字高さ(ピクセル)、ボールド、イタリック、プロポーショナル/固定長、文字色、背景色をそれぞれ
指定できるようにしてあります。
サポートしているプラットフォームは Win32 と X11 です。
フォント種類にはさほどこだわらなくて、とにかく文字列を描画したいという方はぜひ!
zlib/libpngライセンスです。
↓ソースはこちら
http://osdn.net/downloads/users/23/23657/font_renderer_v1_20.zip
(または http://osdn.net/downloads/users/23/23656/nativefont_2_00.zip)
(07/08/17更新 バージョンアップのため)
-----
関連
- [http://blogs.yahoo.co.jp/mocchi_2003/50806312.html font_rendererバージョンアップ]
- [http://blogs.yahoo.co.jp/mocchi_2003/38991447.html 前回作ったライブラリを実際に使ってみた]
- [http://blogs.yahoo.co.jp/mocchi_2003/38911375.html ネイティブAPIを用いたマルチプラットフォームフォントレンダラーライブラリ]
------
もっちーの小部屋 自作のソフトを公開してます。
http://www.geocities.jp/mocchi_2003/index.html
WinMagnetバージョンアップ
http://www.geocities.jp/mocchi_2003/soft.html
このソフトは、ウィンドウに貼り付けると、そのウィンドウを常に最前面状態にしたり、本来動かないウィンドウ(最大化状態のウィンドウ、スプラッシュウィンドウなど)を動かすことができたり、半透明化する機能を持っています。
今回のバージョンアップによって、サイズやボタン位置をカスタマイズできるようになりました。
どうぞ、お試しください^^。
LRU コンテナ
LRU (Least Recently Used) な要素を削除する、キャッシュのような働きをする
C++のコンテナを作ってみました。
内部で list と set を保持していて、要素の追加の他に、begin、end、rbegin、rendを
持っています。(といっても、内部で持っているlistのイテレータをそのまま丸投げしている
だけですが)
要素の追加は add メンバ関数で行います。
add メンバ関数は、2引数をとり、boolを返します。
1番目の引数は追加したい要素で、2番目の引数は削除された要素を返すための参照です。
戻り値が true のときに2番目の参照元に削除された要素が入ります。
サンプルの域を出ていない程度の規模のものですが、一応zlib/libpngライセンス
という形で公開します。
https://osdn.net/downloads/users/23/23651/lru.zip
メンバ関数ポインタ同士の比較
下に書いたプログラムを実行すると…
#include <cstdio>
class Test{
public:
void aaa(void){ printf("a");}
void bbb(void){ printf("a");}
};
using namespace std;
int main(void){
typedef void (Test::*func_type)(void);
func_type a = &Test::aaa, b = &Test::bbb;
printf("%d\n", a == b);
}
g++ では 0 が、 VC++ (13.10.3077 と 14.00.50727.42 で試しました) では 1が帰ってきます。
VC++では Test::aaa と Test::bbb の内容が一緒のためにメンバ関数の実体を一つしか用意してない
のかもしれません。しかし、下の例のように普通の関数の場合は、
void gaaa(void){ printf("a");}
void gbbb(void){ printf("a");}
using namespace std;
int main(void){
typedef void (*func_type)(void);
func_type a = &gaaa, b = &gbbb;
printf("%d\n", a == b);
}
どちらも 0 になるみたいです。