XRS
1. 始めに
1.1 XRSとは
| 一応、XWindow Realtime Simulation の略で、その名の通り、XWindow で
realtime simulation(または単なるグラフィック)をするためのプログラ
ムライブラリです。C++ で書かれていますが、Cプログラムでも利用でき
ます。
XWindow コマンドでいちからプログラムを組むと結構厄介なうえ、させたい
仕事の計算は10行で済んでいてもグラフィックのために数ページのプログ
ラムになってしまうことがあります。
XRS は
*ウィンドウを気楽に開く。
*パラメータの値を表示してプログラム実行中にチューニングする。
*好みの色を用意する。(連続的に変化する色を作ることも可。)
*簡単なマウスイベントの設定。
を個々のプログラムの中で簡単にできるようにするためのライブラリで、
XWindow グラフィックの補助ツールです。
内部の構造を C++ らしく全面改装したため、XRS version 2 との互換性
はなくなってしまいました。(相済みません。) version 3 は
*ウィンドウ、ダイアログのオブジェクト化。
(個別の調節や機能拡張が可能。個数制限がなくなる。)
*すべての設定がプログラムの途中でも変更可能。
*ヘッダファイルが分割されている。
(必要な部分だけをリンクできる。)
*int,Complex 型変数が使える。
*Xリソースによるカスタマイズ。
などなどの特徴があります。XRS ver.2 で何も困らなかった人には迷惑なだ
けかも知れませんが(今まで通り、ver.2 をお使い下さい。)、ちょっと複
雑なことをすると”違いがわかる”と思います。
<今までの歴史>
プログラムの元: 蔵本研の渡辺氏が書いた C のプログラムで、水口さん、
佐々さんを経て私の手に来ました。
初期のころ:そのプログラムからグラフィック関係の部分を取り出して
ヘッダファイルにまとめて個人的に使っておりました。
XRS ver.0〜ver.1: 中身は基本的に C のままで外装に << や多重定義を使
って C++ で書き直しました。
XRS ver.2 (1994.9.18〜) : ライブラリ化して内輪に公開。
XRS ver.3 (1996.4. 〜) : 内部を C++ で改装。オブジェクト化。
その後の変更点は See section バグ、変更点のメモ. を見て下さい。
<今後の予定>
当分、バグとり。(必要に応じて、新種のウィンドウを追加するかも。)
私の周りのワークステーションの性能が上がって、快適なコンパイルができ
るようになったら iostream.h や list.h などの C++ 標準ライブラリを
使って書き換え、dialog クラスなどのテンプレート化をするかもしれない。
今回のような根本的なプログラムの構造の変更は(致命的なバグがない限り)
ないと思います。
<おことわり>
製造物責任は免除してください。
ただし、バグのお知らせ(マニュアルを含む)、改良案、相談、議論(本業
の方も) などなど歓迎です。
|
1.2 インストール
| マニュアルはほぼすべて昔書いたままですが、インストールの部分だけは
あまりにも記述が古いので書き直しました。(2009.12.6)
以下の組合せでコンパイルして無事に動くことは確認済みです。
書いてあるのは一番最近、動作確認した組合せです。手元にない OS では最近
テストしていませんが、XRS の最新のバージョンもバグとりしただけなので
おそらく動くでしょう。
OS XRS compiler X11
Linux(Ubuntu 18.04) 3.3.0 gcc7.3.0 XOrg7.7
Linux(Vine 4.2) 3.2.17 g++3.2.0 XOrg 6.7
Linux(Vine 4.2) 3.2.17 intel_c++8.0 XOrg 6.7
!注意!
まずXWindow(XOrg,Xlib)を使ってプログラムをするための環境が必要です。
以下の手順で必要がコマンドやファイルがないというエラーがでた場合は、
たとえば Ubuntu OS なら xorg-dev,libx11-dev,xutils,xutils-dev
をパッケージマネージャを使ってインストールしてください。
0)XRSver3.2.??.tar.gz をダウンロードして
> tar xzvf XRSver3.2.??.tar.gz [return] で展開。
> cd XRSver3.2.??
1)デフォルトの設定値は <XRS/define.h> で定義されているので必要なら
適当に変えてください。(後でカスタマイズできないのはリソースファイ
ル名の XRS_RESOURCE_FILE だけです。)
Imakefile の中のインストール先ディレクトリ
XRSBINDIR = /usr/local/bin
XRSLIBDIR = /usr/local/lib
XRSHDRDIR = /usr/include
などと g++ のインクルードファイルへのパス
GCCDIR = /usr/include/c++
などを必要に応じて変更してください。
2)> xmkmf
> make all
> make install または sudo make install
3)マニュアル
doc の下にこのマニュアルがあります。
|
2. 使い方
2.1 初泣編(基本)
この節は基本的な使い方と紹介といったところです。これだけ知っていればまずは十分かと思います。
!実際のプログラムを見た方がわかりやすい人は XRS を使ったサンプルプログラムがソースファイル XRSver3.?.tar.gz の中の sample/ の下にあるので御覧下さい。
2.1.1 プログラムのコンパイルの仕方
| miya.C というプログラムをコンパイルするなら、例えば以下のようにしてください。
[Linux-OS の場合]
g++ -O4 miya.C -o miya -lX11 -lXrs -lm
としてください。
!XRSver3.3.0からソースファイルに using namespace XRS; が必要になりました。
システムによっては、
g++ -O4 -I/usr/X11R6/include -o miya.C -o miya -lXrs -L/usr/X11R6/lib -X11 -lm
のようにXWindow 関係のファイルの場所を指定する必要がある場合があります。
※ オプション -lXrs は XRS ライブラリをリンクするオプションで、XRSは
内部で XWindowライブラリ、数学関数ライブラリを使っているので
-lX11,-lm も必要です。オプションの順番にも注意して下さい。
※ C++ライブラリのリンクオプション -lg++, -lstdc++ が gcc のバージョンに
よっては <complex.h> を使う時に必要です。
(-lstdc++ は complex.h 用の cmath.h の中の関数を使う時必要です。)
※ テンプレートを使っている場合(complex型など)、-O 以上の最適化をし
ないととテンプレート展開されずリンクのときにエラーがでます。
|
2.1.2 最も簡単なプログラム(何もしない)
| ——- test0-0.C ————-
#include <XRS/Simple.h>
using namespace XRS;
int main(){
initialize();
while(1) checkevent();
exit(0);
}
—————————–
※このプログラムは実際に走らすとなにもせず走りっぱなしになります。
(Control-C で止めて下さい。)
XRSを使うにはこのように
(1)必要なファイルをインクルードする。(この場合は XRS/Simple.h)
(2)必要に応じて初期設定をしてから initialize();を実行する。
(3)計算ループのなかで checkevent(); を実行して変数の表示やマウス
クリックの処理をさせる。
という手順が必要です。
|
2.1.3 次に簡単なプログラム(ウインドウを開くだけ)
| 幅200pixel、高さ100pixel のウィンドウを1つ開くなら
Simple_Window型の変数を1つ宣言してください。
——- test0-1.C ————-
#include <XRS/Simple.h>
using namespace XRS;
Simple_Window A(200,100);
int main(){
initialize();
while(1) checkevent();
exit(0);
}
—————————–
宣言だけしといてウィンドウの大きさを後で geometry(width,height) 関数
で決めても同じです。
——- test0-2.C ————-
#include <XRS/Simple.h>
using namespace XRS;
Simple_Window A;
int main(){
A.geometry(200,100);
initialize();
while(1) checkevent();
exit(0);
}
—————————–
これだけでは味気ないのでタイトルをつけてみます。タイトルの設定は <<
演算子で行ないます。( <<演算子はふつうC++では左辺に右辺を入力する
という意味で使います。)A.geometry(200,100)<<"How are you?"; のよう
に続けて書くこともできます。
——- test0-3.C ————-
#include <XRS/Simple.h>
using namespace XRS;
Simple_Window A(200,100);
int main(){
A<<"How are you?";
initialize();
while(1) checkevent();
}
—————————–
途中で変更するときもおなじです。
2つ以上のウィンドウを開きたい時も同じように宣言してください。
——- test0-4.C ————-
#include <XRS/Simple.h>
using namespace XRS;
Simple_Window A,B;
int main(){
A.geometry(200,100)<<"I’m not Windows.";
B.geometry(400,50)<<"I’m a window.";
initialize();
while(1) checkevent();
exit(0);
}
—————————–
Control-C で止めるなんてことはせず、ちゃんとスタートと終りがあった方
がいいなら <XRS/Control.h> をインクルードして、 Control_Window型の変
数を宣言してください。
——- test0-5.C ————-
#include <XRS/Control.h>
using namespace XRS;
Control_Window C;
int main(){
initialize();
while(1) checkevent();
}
—————————–
実行すると initialize() でコントロールウインドウに "start" を表示し
て一時停止します。"start" がクリックされると "quit" に表示が変わり
実行を再開します。"pause" 欄をクリックするとプログラムの実行を一時停
止し("cont" を押すと再開)、"quit" をクリックすると終了します。
マウスクリックの検出は while ループの中で checkevent() を実行するた
びに行なわれます。
さきほどのプログラムと組み合わせるとこうなります。
——- test0-6.C ————-
#include <XRS/Control.h>
#include <XRS/Simple.h>
using namespace XRS;
Control_Window C;
Simple_Window A(200,100);
int main(){
A<<"I am A.";
initialize();
A.geometry(100,200);
while(1) checkevent();
exit(0);
}
—————————–
タイトルの設定は "start" クリック前に、リサイズはクリック後に行なわ
れます。
|
2.1.4 ちょっとは仕事をするプログラム
| <XRS/Graphic.h> をインクルードすると Graphic_Window という2次元グラ
フィック専用ウィンドウを使えます。Graphic_Window も geometry関数やタ
イトル設定の<<演算子が使えます。
これはランダムに点を打つプログラムです。( drand48()は 0〜1 の
一様乱数を返す C の関数。)
——- test0-7.C ————-
#include <stdlib.h>
#include <XRS/Graphic.h>
using namespace XRS;
#define RANDOM (int)(200*drand48())
Graphic_Window A;
int main(){
A.geometry(200,200)<<"random plot";
initialize();
while(1){ checkevent(); A.draw_point(1.0,RANDOM,RANDOM);}
exit(0);
}
—————————–
draw_point(double c,int i,int j) は点を打つ関数で、(i,j) の位置に c
の値で決まる色の点を描きます。
A.geometry(200,200) を A.geometry(200,200,2) に変えてみてください。
ウィンドウのサイズが2倍になり 2 x 2 pixel を点とみなして描画します
。(Simple_Window にはこの3番目の引数はありません。)
その他に (i1,j1)から(i2,j2)まで直線を引く
draw_line(double c,int i1,int j1,int i2,int j2) と
(i,j) を中心とする半径 r の円を描く
draw_circle(double c,int i,int j,double r) があり同じように使えます。
c の値をまとめて配列で与えて画面全体を一度に描画する場合は
draw_2D(double **c) が使えます。 c[i][j]に座標(i,j)に描く色を代入し
て与えます。ただし、draw_2D には動的にメモリーを確保したdouble**型の
2次元配列を与えてください。
——- test0-8.C ————-
#include <XRS/Graphic.h>
using namespace XRS;
Graphic_Window A(200,200);
int main(){
A<<"sin";
initialize();
int i,j;
double **c; array(c,200,200);
for(i=0; i<200; i++)
for(j=0; j<200; j++) c[i][j]=sin(M_PI*(double)i/50);
A.draw_2D(c);
while(1) checkevent();
exit(0);
}
—————————–
array 関数は動的2次元配列をとる関数で、double 型だけでなく
任意の型の動的2次元配列をとることができます。(たとえば、int型の配
列をとるなら int **c; array(c,200,100); とする。)
描かれる色はオリジナルに用意して使うことも簡単にできますが、単色で濃
淡(飽和度)が段階的に変わる配色と色相(赤→緑→青→赤)が変わる配色
はそれぞれ <<に続けて MONO(double h,int n) とPHASE(double h, int n)
を書くだけで使えます。( h は色相、nは色数です。n は省略するとデフォ
ルトのままです。)たとえば、上のプログラムの A<<"sin"; を
A<<"sin"<<MONO(0.4); //白→黄緑のmonotone
や A<<"sin"<<PHASE(0.5,10); //水色からはじまるphasetone
と変えるとそれに応じて色が変わります。
引数に与える数値 c と色の対応(グラデーション)は double を返す関数
を定義して << で設定することで変更できます。関数の返り値は 0〜1の
範囲になるようにしてください(デフォルトでは1を越えると黒が0以下な
ら白になります)。例えば、上のプログラムでは -1<=c<=1 なので
double f(double c){ return 0.5*(c+1); }
A<<"sin"<<f;
とすると飽和度が線形に変化するグラデーションが得られます。デフォルト
の状態ではこの関数は double f(double c){ return AMPF*c*c; } (AMPF
はXRS/define.hで定義されている定数)になっています。
同じように << で void (*)(int)型関数を設定するとウィンドウがクリック
された時、引数に押されたマウスボタンの番号を与えてその関数が実行され
ます。(これは Simple_Window でも同様です。)
——- test0-9.C ————
#include <XRS/Simple.h>
using namespace XRS;
void g(int n){ printf("Oh!,%d’th mouse button was clicked.\n",n);}
Simple_Window A;
int main(){
A.geometry(300,100)<<g<<"Please, click a mouse button.";
initialize();
while(1) checkevent();
exit(0);
}
—————————–
Control_Window では << の後に続けて複数の void (*)(int) 関数を登録
して欄を作り、<<"文字列" で欄のタイトルを設定できます。同様に、<<で
double型、int型変数を設定するとその変数値の realtime 表示をする欄を
作ります。
<<PARAMETER の後ろに double 型または int 型変数を設定するとはマウス
クリックで変数の値を変えることができます。(PARAMETER を使うたびに
realtime 表示 ⇔ パラメータチューニング が切り替わります。)
——- test0-10.C ————-
#include <XRS/Control.h>
using namespace XRS;
Control_Window C;
int b=0;
double a=12,answer;
void clear(int){ answer=a=b=0; }
void print(int){ printf("(double)%f+(int)%d=%f\n",a,b,answer);}
int main(){
C<<answer<<clear<<"answer"<<"clear"
<<PARAMETER<<a<<b<<"a"<<"b"<<print<<"print";
initialize();
while(1){ checkevent(); answer=a+b; }
exit(0);
}
—————————–
このプログラムでは answer(=a+b) の値をreal time で表示する欄と a 、
b の値をチューニングする欄ができ、マウスクリックで a や b の値を変え
ると answer の値がそれに応じて変わります。
たとえば実数の変数 a は普通、初めの変化の刻み幅 dx は 1.0 で
┌─────┐
│ a │← タイトル欄を右ボタンでクリックすると dx 増える。
├─────┤
│12.00│← 変数欄を右ボタンでクリックすると dx 減る。
└─────┘
タイトル欄をまん中ボタンでクリックすると 0.1*dx 増える。
変数欄をまん中ボタンでクリックすると 0.1*dx 減る。
タイトル欄を左ボタンでクリックすると dx が10倍になる。
変数欄を左ボタンでクリックすると dx が 1/10になる。
というふうになります。整数型の b は dx=10 が初期値なのが普通で、dxは
10 以下にはなりません。右ボタンで変化する桁は色をかえて表示してあり
ます。(Control_Window は double型とint型の変数を設定できます。Compl
ex型も使いたい人は Complex_Control_Window を使って下さい。)
clear をクリックすると answer=a=b=0; となり answer の表示は0になり
ますが a,b 欄は次に欄がクリックされるまでは前の値を表示し続けます。
これが realtime 表示と普通の表示との違いです。一度 "pause" をすると
変数は正しく表示し直されます。
|
2.1.5 XWindow コマンドでのお絵書き
| XRSについている描画関数はそれほど複雑なことはできません。そのかわ
り、XWindow の豊富なコマンドを簡単に使えるようにしています。
(ただし、XWindow のコマンドを使って書いた絵は XRS とは無関係なので
ウィンドウが隠されたときの再描画などは普通おこなわれません。)
XWindow のコマンドを使うには
(1)ディスプレイID Display*
(2)ウィンドウID Window
(3)グラフィックコンテキスト(色や線幅などの属性)GC
を引数で指定する必要がありますが、XRSではウィンドウ名を W とすると
(1)Display *d=W.disp(); disp()関数の返り値
(2)(Window)W; そのまま使うと型変換される
(3)GC gc=graphic_context("blue"); graphic_context関数で作る
という風にすると使えます。
例えば、(i1,j1)から(i2,j2)への直線を引く XWindow コマンドは
XDrawLine(Display*,Window,GC,int i1,int j1,int i2,int j2);
なので、
——- test0-11.C ————-
#include <XRS/Simple.h>
using namespace XRS;
Simple_Window W(100,100);
int main(){
GC gc;
gc=graphic_context("blue");
initialize();
XDrawLine(W.disp(),W,gc,10,10,90,90);
while(1) checkevent();
exit(0);
}
—————————–
とすると青の直線が引けます。
graphic_context関数は graphic_context(char "色名",int 線幅,
int 線のタイプ,char "フォント名"); を引数で指定できます(省いたら
デフォルトのまま)。たとえば、上の gc を
gc=graphic_context("red",3,LineOnOffDash); //太さ3の赤の点線
などとできます。( LineOnOffDash は #define で定義されているマクロ
で他に LineSolid, LineDoubleDash があります。)
Simple_Window や Graphic_Window では黒と白の GC だけは既に bgc,wgc
という名前でウィンドウごとに持っているので、gc=graphic_context("blac
k");とする代わりに gc=A.bgc; などとしてもいいです。
XWindow コマンドで良く使うものは
(i,j)に点を書く。
XDrawPoint(Display*,Window,GC,i,j);
まとめて N 個点を書く。(早い)
XPoint p[N]; と宣言して
p[i].x、p[i].y に i 番目の点の x、y 座標を代入した後
XDrawPoints(Display*,Window,GC,p,N,CoordModeOrigin);
(i1,j1)から(i2,j2)まで直線を書く。
XDrawLine(Display*,Window,GC,i1,j1,i2,j2);
まとめて N 個直線を書く。(早い)
XPoint p1[N],p2[N]; と宣言して
XDrawPoints(Display*,Window,GC,p1,p2,N,CoordModeOrigin);
左上の隅が(i,j)の幅 width、高さ height の長方形を書く。
XDrawRectangle(Display*,Window,GC,i,j,width,height);
中が塗りつぶされた長方形を書く。
XFillRectangle(Display*,Window,GC,i,j,width,height);
左上の隅が(i,j)の幅 width、高さ height で角度(angle1,angle2)の
範囲の円弧を描く。角度は 1/64 度単位の整数で指定する。ちなみに
円を書きたいなら、arg1=0,arg2=360*64=23040 にする。
XDrawArc(Display*,Window,GC,x,y,width,height,angle1,angle2);
※円を描く関数はないので、
#define XCircle(D,W,G,x,y,r) XDrawArc(D,W,G,x-r,y-r,2*r,2*r,0,23040);
とでもマクロ定義すればいいでしょう。
塗りつぶされた扇型を書く。
XFillArc(Display*,Window,GC,x,y,width,height,angle1,angle2);
ぐらいです。消すときは普通、白で書き直します。Window 全体の
クリアーは XClearWindow(Display*,Window); でできます。
まぁ、もっといろいろやりたい人は XWindow のマニュアルを見て下さい。
|
2.2 中窮編(応用、カスタマイズ)
初泣編の続編です。マニアックなところは適当に飛ばし読みしてください。
2.2.1 ウィンドウ応用編
- ‘どのウィンドウでも使える関数’
例えば W を XRS のどれかのウィンドウの変数としたら、
| Display* d=W.disp(); はディスプレイID
Window w=W; はウィンドウID
を返すのは初泣編で紹介したとおりです。その他に
Window r=W.root(); は親ウィンドウのID
int w=W.width(); はウィンドウの幅(ピクセル)
int h=W.height(); はウィンドウの高さ(ピクセル)
char *s=title(); はウィンドウのタイトル
を返します。また
void W.resize(int width,int height); は(width,height)にリサイズ
void W.move(int i,int j); はウインドウを(i,j)に移動
void W.redraw(); はウィンドウを再描画
void W.title(char* s); はタイトルを s に変更
void W.map(); はウインドウを見えるように
void W.unmap(); はウインドウを見えなく
する関数です。(ただし、redraw は Simple_Window ではなにもしません。
また、resize は Graphic_Window では少し引数の意味が変わります。)
resize(-1,100) などと負の数を与えた場合はその引数は変更されません。
resize や move は先に紹介した geometry 関数を使ってできます。また
title も Simple_Window や Graphic_Window では << を使ってできます。
|
- ‘ウィンドウのスコープと寿命’
宣言されたウィンドウは"ウィンドウ型"の変数なのでスコープや寿命は普通
の変数と同じです。従って、サブルーチンの中で普通に宣言されたウィンド
ウはサブルーチンの実行とともに出来、終了と同時に消滅します。(特に
ループの中で宣言する時は要注意です。)
例えば、
| ------- test1-0.C ------------
#include <XRS/Simple.h>
using namespace XRS;
void change(int n){
Simple_Window B(100,100);
B<<"click!";
while(!B.chev) checkevent();
}
Simple_Window A(200,200);
int main(){
A<<"CLICK!"<<change;
initialize();
while(1) checkevent();
exit(0);
}
-----------------------------
|
などはいい例でしょう。chev は checkevent() のたびにセットされる変数
で、マウスクリックがあればそのボタン番号、なければ0になります。
ウィンドウが幾つもできてしまったひとは最後に開いたものからクリックし
て消していきましょう。
- ‘子ウィンドウの開き方’
これはコントロールウィンドウをシンプルウィンドウの中に開く例です。
| ------- test1-1.C ----------------
#include <XRS/Simple.h>
#include <XRS/Control.h>
using namespace XRS;
Simple_Window A;
Control_Window B(A);
int main(){
double t=0;
A.geometry(300,200)<<"Simple Window";
B<<t<<"t";
initialize();
while(1){ checkevent(); t+=0.01;}
exit(0);
}
-----------------------------
|
このように変数宣言の第一引数に別のウィンドウを与えるとそのウィンドウ
が親ウィンドウになります。
- ‘別のディスプレイに開く’
そんなことをする人がいるかのか疑問ですがやりたければできます。
、別のディスプレイを指定してウィンドウを作り、それを親に指定します。
| ------- test1-2.C -------------
#include <XRS/Simple.h>
using namespace XRS;
window R("haku:0.0");
Simple_Window A(R,200,200);
int main(){
initialize();
while(1) checkevent();
exit(0);
}
-----------------------------
|
普通、何も指定していない時は環境変数 DISPLAY をセットして暗黙のうち
に宣言されているウィンドウ XRS_ROOT が親ウィンドウになっています。
windowというのは XRS の基本的なウィンドウ(すべてのウィンドウは
これをもとにして作られている)で、Simple_Window なども window型の変
数の一種ですが直接プログラムに出てくるのはこういう場合だけでしょう。
- ‘何も開かない方法(バックグラウンドジョブ用)’
ディスプレイに表示するように作ったプログラムをバックグラウンドで走ら
せたい場合、ディスプレイへの表示をやめさせる必要があります。
もっともお手軽なのは initialize(); をコメントアウトすることですがこ
れはウィンドウが見えなくなるだけで X を使っていることには変わりない
ので端末を出た途端( X との接続が切れて )、エラーを出してジョブは停
止します。従って、初めから X を使わないようにする必要があります。
XRS はコンパイル時に -DXRSBG オプション(XRSBGを定義して1にセットす
るオプション)をつけると X との接続をせずデフォルトの親ウィンドウ XR
S_ROOT のディスプレイID が NULL にセットされます。ただし、自分で XWi
ndow のコマンドを使っている場合、そこで Segmentatin Fault が出るので
#ifndef XRSBG 〜 #endif などをつけて対処してください。
| ------- test1-3.C -------------
#include <XRS/Simple.h>
using namespace XRS;
Simple_Window A(400,400);
int main(){
double DT=0.01,t,u=0.1,v=0.1;
initialize();
for(t=0; t<500; t+=DT){
checkevent();
u+=DT*0.5*(-v+u-u*u*u); v+=DT*u;
#ifndef XRSBG
XDrawPoint(A.disp(),A,A.bgc,(int)(100*u+200),(int)(200-100*v));
#endif
}
printf("t=%f (x,y)=(%f,%f)\n",t,x,y);
exit(0);
}
-----------------------------
|
このプログラムでは XWindow の XDrawPoint コマンドを使っているので、
XRSBG が定義されている時 XDrawPoint のある行はコンパイル時に無視され
るようにします。こうしておくと、
gcc -DXRSBG test1-3.C -o test1-3 -lg++ -lXrs -lX11 -lm
などと -DXRSBG をつけてコンパイルして、 test1-3 [return] とすれば
ウィンドウを開かずに計算結果だけを出します。
2.2.2 Simple_Window 応用編
だいたい、必要なことは初泣編で書いてしまったようです。
| あと付け加えるとしたら、(W を Simple_Window型の変数として)
* W.clear(); はウィンドウをクリアーします。
* geometry 関数は正式には4つ引数があって
W.geometry(width,height,i,j); のように (i,j) を与えると位置(i,j)
へウィンドウを移動します。引数が負の値なら現状維持です。
ぐらいです。
|
2.2.3 Graphic_Window 応用編
| イベントやウィンドウの基本操作はだいたい Simple_Window と同じです。
違うのは、大きさの指定に mesh size( draw_point や draw_2D で描画する
時の点の大きさ)が加わっていることです。
( W を Graphic_Window型の変数として)
* geometry 関数は正式には5つ引数があって
W.geometry(i_max,j_max,ms,i,j); とすると、位置(i,j)、メッシュサ
イズ ms ピクセル、幅 ms*i_max ピクセル,高さ ms*j_max ピクセルに変
更されます。これは、W.resize(i_max,j_max,ms); W.move(i,j); とやっ
ても同じです。引数が負の値なら変更されません。
* int W.width(),W.height(); はそれぞれ ms*i_max, ms*j_max を返しま
すが、その他に int W.mesh_size(),W.i_max(),W.j_max(); はそれぞれ
ms,i_max,j_max を返す関数です。
- ‘色サンプルウインドウを作る’
void sample_window(Graphic_Window W) は引数で指定された Graphic_Wind
ow W に W.draw_point、W.draw_2D で使われる配色の簡単な色のサンプルを
描く関数です。
| ------- test1-4.C -------------
#include <XRS/Graphic.h>
using namespace XRS;
Graphic_Window A;
void change_size(int n){ A.geometry(-1,-1,n); }
int main(){
A.geometry(200,100)<<"color sample"<<PHASE(0.6,10)<<change_size;
initialize();
sample_window(A);
while(1) checkevent();
exit(0);
}
-----------------------------
|
このプログラムはマウスがクリックされるとボタンの番号 n を与えて、
A.geometry(-1,-1,n);が実行され、メッシュサイズが n に変更されます。
(同時にウィンドウはリサイズされる。) sample_window(A) や
draw_point ,draw_2D で書いた内容なら同時にリサイズされます。
- ‘色の決まり方’
draw_point(double w,int i,int j); などで与えた数値 w から実際に描か
れる色が決まる方法は次のようになります。
各 Graphic_Window は内部に
"色関数" double f(double);
"色配列" unsigned long color[i]; i=0,,,N+1; (Nは色数)
を持っています。"色配列" は MONO,PHASE などで設定でき、"色関数"は
<< 演算子で設定できるのは初泣編で説明した通りです。
"色配列" に入っているのが実際に表示される色に対応するカラーピクセル
と呼ばれる番号です。w を与えると
n=(int)(f(w)*colornumber);
if(n<0) i=N+1; else if(n>=N) i=N; else i=n;
によって描かれる色 color[i] が決まります。color[N]は黒、color[N+1]
は白が普通ですが変更することもできます。
(カスタマイズでやるのが一番楽)
- ‘オリジナルな色を使う’
「MONO,PHASE などの標準的な配色では使えん」という場合、オリジナルな
配色を作る一番手軽な方法は使いたい色名を並べたテキストファイルを作っ
てCOLOR("ファイル名")で読み込ませることでしょう。
ファイルには1行に1つの色名を書いて並べてください。( ’!’ から始まる
行はコメントとみなされます。)例えば、
| ----- color0 -------
! color resource sample
red
blue
green
--------------------
|
というようなファイルを作ります。色名は XWindow で使える形式すべてで
す。次のファイルは色名をRGB値形式で書いた例です。(#に続いて16進数
2桁ずつで red,green,blue の輝度を書く形式 #rrggbb)
| ----- color1 -------
#ff0000
#2a00ff
#00ff54
#f6ff00
--------------------
|
このファイルは gimp か xcoloredit を利用すると簡単に作れます。
gimp の場合は、gimp を起動して、新規画像を[種類] RGB で [サイズ]を
ピクセルで(幅)欲しい色数 x(高さ)1 と指定して開いてから、拡大表示(16:1な
ど)で見ながら各ピクセルに使いたい色を順に並べてください。
出来たファイルを[保存]で Xpm 形式を選んで適当な名前(例えば gomi.xpm)で
保存してください。あとは、コマンドラインで
perl -nle ’print $1 if /(#\w+)/;’ gomi.xpm > color1 など
と打てばできあがりです。
xcoloreditの場合は、UNIX のコマンドラインで xcoloredit >color1 [return]
として、画面に出てくるパレットに作った色を並べて終了すればファイルが
出来上がります。
プログラム中でこれを読み込ませるには例によって << を使って、
| ------- test1-5.C -------------
#include <XRS/Graphic.h>
using namespace XRS;
Graphic_Window A(200,100);
int main(){
A<<COLOR("color1");
initialize();
sample_window(A);
while(1) checkevent();
exit(0);
}
-----------------------------
|
とします。
自分で色配列 unsigned long color[i]; i=0,,,N-1; を作って直接指定す
ることも可能です。
A<<COLOR(color,N);
欲しい色のカラーピクセルは色の名前を指定して
color[0]=color_pixel("red");
あるいは、色相 h,飽和度 s,明度 v を指定して
color[1]=color_pixel(h,s,v);
のようにして得ることができます。
このようにして取った色の番号を直接指定して描画させるには
point(int c,int j,int j);
line(int c,int i1,int i2,int j1,int j2);
circle(int c,int i,int j,double r);
draw_2D(int **c);
を使って下さい。 c が色の番号であることを除けば、
draw_point(double,,)、draw_line(double,,,,)、
draw_circle(double,,,)、draw_2D(double **)
と使い方は同じです。
- ‘位相を色で振幅を濃淡で表示する’
それ用の色配列を unsigned long* colordisk(int nr,int np) 関数で取
ることができます。 ここで、nr は振幅方向の色の数、np は位相方向の
色の数です。返ってきた配列は nr*np 個の要素を持ちます。
この色配列の中の振幅 r(0<r<1)、位相 phi(2π周期)に対応する色
の番号を返す関数が int diskcolor(double r,double phi,int nr,
int np) です。
この2つの関数を使うと例えば、
| ------- test1-15.C -------------
#include <XRS/Graphic.h>
using namespace XRS;
int main(){
W<<COLOR(colordisk(6,8),6*8);
initialize();
double r,phi;
for(int i=-50; i<50; i++)
for(int j=-50; j<50; j++){
if(i || j){
r=sqrt((double)(i*i+j*j))/50;
phi=atan2((double)i,(double)j);
W.point(diskcolor(r,phi,6,8),i+50,j+50);
}
}
while(1) checkevent();
exit(0);
}
-----------------------------
|
のように色配列が2次元であるかのように色を出せます。
ちなみに、 colordisk と diskcolor の中身は
| unsigned long* colordisk(int ni,int nj){
unsigned long *cp=new unsigned long [ni*nj];
for(int i=0; i<ni; i++)
for(int j=0; j<nj; j++)
cp[i*nj+j]=color_pixel((double)j/nj,(double)i/ni,1);
return cp;
}
int diskcolor(double r,double phi,int ni,int nj){
phi/=2*M_PI; if( phi>=1 || phi<0 ) phi-=floor(phi);
return (int)(nj*((int)(r*ni)+phi));
}
|
という簡単なものです。ただし、関数 diskcolor は変数が振幅と位相な
ので、一々 sqrt とか atan とかを使って振幅、位相の計算を毎回すると
効率が悪すぎます。
用途に応じてもっと効率の良い似たような関数を作って使ってください。
例えば、Complex 変数を使っているなら、実部と虚部から簡単に計算でき
るように色配列を並べると早くなります。以下は、複素平面を一辺
2*Color+1 個の正方格子に区切って各 site にその振幅と位相に対応する
色を与えて並べているものです。
| #define Color 5
unsigned long* colordisk(){
unsigned long *cp=new unsigned long [(2*Color+1)*(2*Color+1)];
double r,phi;
int i,j,k;
for(i=-Color; i<Color+1; i++)
for(j=-Color; j<Color+1; j++){
k=i+Color+(j+Color)*(2*Color+1);
r=sqrt((double)(i*i+j*j))/(double)Color;
if(i==0 && j==0) phi=0;
else phi=atan2((double)i,(double)j)/(2*M_PI);
cp[k]=color_pixel(phi,r,1);
}
return cp;
}
int diskcolor(Complex w){
static int cn=2*Color+1;
w+=Complex(1,1); w*=Color;
return (int)real(w)+(int)imag(w)*cn;
}
これは、
#define ColorNumber (2*Color+1)*(2*Color+1)
W<<COLOR(colordisk(),ColorNumber);
W.point(diskcolor(w[i][j]),i,j);
のように使えます。
|
- ‘メモリーの節約’
Graphic_Window は内部に画面に描いた色を記憶しておく配列を動的に確保
して、描画の高速化や画面の再描画に利用しています。そのため、大きな画
面を何個も開くと各個人が使えるメモリーの限界を越えてしまうことがあり
ます。
特に描画の高速化や再描画が必要でなければ、<<MEMORY を書くことで内部
の配列のメモリーを解放してメモリーを節約できます。(もう一度、
<<MEMORY を書くと再び配列を確保する。)
例えばプログラム test16.C に A<<MEMORY; を加えるとマウスクリックでの
リサイズ後の再描画は行なわれません。(そのかわり、プログラムが使って
いるメモリーは小さくなる。)
|
2.2.4 Plane_Window 応用編
| Plane_Window は Graphic_Window の親戚で、色ごとに仮想的なプレーンを持
っていて重ね書きができます。複数のグラフを1つのウィンドウに重ねて書く
ときなどに便利だと思います。
宣言のし方や色のとり方は Graphic_Window と同じですが、描画関数の使い方
が少し異なり、
draw_point(int plane,int i,int j);
draw_line(int plane,int i1,int j1,int i2,int j2);
draw_circle(int plane,int i,int j,double r);
draw_2D(int **plane);
のように第一引数には描くプレーンの番号(色配列の色の番号)を与えて下さ
い。このように直接、色を指定するので Graphic_Window のような色関数は
ありません。また、Plane_Window には描いた図形を消すための
erase_point(int plane,int i,int j);
erase_line(int plane,int i1,int j1,int i2,int j2);
erase_circle(int plane,int i,int j,double r);
erase_2D(int **plane);
clear(int plane);
関数があります。描かれている図形を消すと下のプレーンに描かれて隠れてい
た図形が現れます。
ただし、Plane_Window で使えるプレーン数(色数)はメモリーの関係上30
色までです。また、仮想的なプレーンのメモリー操作のために描画スピード
(特に図形を消去するスピード)がやや遅いのが欠点です。
| ------- test1-6.C ----------------
#include <XRS/Plane.h>
using namespace XRS;
Plane_Window A(100,100,3);
int main(){
A<<"plane window"<<COLOR();
initialize();
A.draw_line(1,0,0,100,100);
A.draw_circle(2,50,50,40.0);
A.draw_line(3,0,100,100,0);
while(1) checkevent();
exit(0);
}
-----------------------------
|
|
2.2.5 Control_Window、Complex_Control_Window 応用編
| コントロールウィンドウも宣言の時や、geometry 関数で大きさの指定がで
きますが引数の意味が少し違います。
Control_Window A(imax,jmax); あるいは
Control_Window A; A.geometry(imax,jmax);
のように int imax,jmax で大きさが指定されている時、コントロールウィ
ンドウはダイアログを以下のように並べてそれに合わせてウィンドウをリサ
イズします。
[imax > jmax の場合]
1. ダイアログを登録順に縦に並べていき、並べたダイアログの高さの合
計が jmax を越えるなら次の列に移る。
2. ウィンドウの幅が imax を越えるなら、先頭の列に戻る。
3. 1に戻る。(新しい段が足される。)
[imax < jmax の場合]
横に並べて行を足していき、ウィンドウの高さが h を越えたら先頭の行
に戻る。
geometry 関数は正式には4つ引数があって A.geometry(imax,jmax,i,j) と
(i,j) を書くとウィンドウを (i,j) に移動します。
int i_max(),j_max() はそれぞれ上の imax,jmax を返す関数です。
- ‘"start⇔quit、pause⇔cont"ダイアログを作らない。’
"start⇔quit、pause⇔cont" ダイアログは最初に宣言されたコントロール
ウィンドウに自動的に作られます。これをやめたければ、普通の宣言の場合
、3番目の引数に0を指定します。(0を指定せずに宣言した最初のコント
ロールウィンドウに作られる。)例えば、Control_Window A(100,50,0);。
- ‘Complex_Control_Window’
Complex型の変数も登録できることをのぞくと Control_Window と同じです
。使う時は、<XRS/Complex_Control.h> をインクルードしてください。
Complex 型の変数は"実部/虚部表示"か"極座標表示"のどちらかを選べ、デ
フォルトまたは <<RC<< の後に設定した変数は"実部/虚部表示"、<<PC<<の
後に設定した変数は"極座標表示"になります。極座標の角度の値はπで割っ
た値を表示します。
| ------- test1-7.C -------------
#include <XRS/Complex_Control.h>
using namespace XRS;
Complex_Control_Window A;
int main(){
Complex a=0;
A<<PARAMETER<<a<<"re/im"<<PARAMETER<<PC<<a<<"r/arg";
initialize();
while(1) checkevent();
exit(0);
}
-----------------------------
|
このプログラムでは変数 a を実部/虚部表示(デフォルト)して、マウス
クリックで値を変えられるようにし(PARAMETERを前に挟む)、次の欄で極
座標(PC)で値を realtime 表示(もう一度 PARAMETER を入れる)します。
|
2.2.6 gnuplot を使ったグラフィック
| XRS/Exec.h、XRS/DataSocket.h を使えば、gnuplot などのグラフィックソ
フトにデータを送り込んでリアルタイムシミュレーションをすることがで
きます。
class Exec は与えられたコマンドを子プロセスで実行して、その標準入力
との間にパイプを作ります。
例えば、
| ------- test1-8.C -------------
#include <XRS/Exec.h>
using namespace std;
using namespace XRS;
int main(){
Exec cat("/bin/cat","cat","gomi");
cat<<"This is a test."<<endl;
exit(0);
}
-----------------------------
|
は bin/cat の cat を実行し、標準入力に "This is a test.\n"( 自動的に
’\n’ が付け加えられます。)を送り込み、cat の出力をファイル "gomi"
に書き出します。Exec の引数は ( コマンドの path 名、コマンド、
標準出力を書き出すファイル、標準エラー出力を書き出すファイル)です。
ファイル名を省略または NULL にするとリダイレクトをしません。
class DataSocket は与えられた名前のソッケトを開き、ファイルに書き込む
のと同様にそのソケットにデータを出力できます。出力されたデータは専用
のコマンド datasocket で受けっ取って標準出力に書き出すことができます。
(datasocket コマンドが実行されるまでプログラムの実行は中断します。)
例えば、
| ------- test1-9.C -------------
#include <iostream>
using namespace std;
#include <XRS/DataSocket.h>
using namespace XRS;
DataSocket S("gahaha");
int main(){
int i,k;
for(i=1; i<5; i++)
{ S.open(); for(k=0; k<i; k++) S<<k<<endl; S.close();}
return 0;
}
-----------------------------
|
は "gahaha" という名前のソッケト(!注意! 同名のファイルが実行ディ
レクトリに作られるので、既にあるファイルと同じ名前にならないようにして
ください。)を開き、S.open() で datasocket コマンドからの接続要求を待
って datasocket との間に接続を作り、S.close() までに (FILE*)S に出力さ
れたデータを datasocket に送り込みます。
このプログラムを"test" という名前でコンパイルしてコマンドラインで
> test & [return]
とバックグラウンドで走らせた後、
> datasocket gahaha [return]
を4回実行すると順番にデータが書き出されます。
この2つを応用すると、
| ------- test1-10.C -------------
#include <math.h>
#include <XRS/Exec.h>
#include <XRS/DataSocket.h>
using namespace std;
using namespace XRS;
Exec gnuplot("gnuplot","gnuplot",NULL,"/dev/null");
DataSocket S("gomi_socket");
int main(){
double t,x,y;
gnuplot<<"set zrange [-1:1]"<<endl;
gnuplot<<"set style data lines"<<endl;
gnuplot<<"set pm3d"<<endl;
gnuplot<<"set hidden3d"<<endl;
for(t=0; t<20; t+=0.1){
gnuplot<<"splot '< datasocket gomi_socket'"<<endl;
S.open();
for(x=0; x<10; x+=0.5){
for(y=0; y<10; y+=0.5) S<<cos(x+y+t)<<endl;
S<<endl;
}
S.close();
}
return 0;
}
-----------------------------
|
のように3次元シミュレーションもできます。
この例では "xrs_gomi_data" という名前のソケットを開き、gnuplot の
パイプ機能を利用して、"splot ’< datasocket xrs_gomi_data’" という
コマンドを実行させることで、splot に datasocket の出力を渡してい
ます。(S.open() は datasocket の実行を待つので datasocket を実行
する命令を出してから実行する必要があります。)
標準エラー出力を "dev/null" にすると gnuplot からの警告メッセージ
は一切出力しません。パイプ機能を使うと splot をするたびに
Notice: 〜
というメッセージが出てくるので、プログラムにバグがないことを確認
したら "dev/null" を指定した方がいいでしょう。
!日本語バージョンの gnuplot+ はパイプ機能にバグがあって動きません。
使う gnuplot が gnuplot+ でないことを確認してください。
|
2.2.7 個々のダイアログを扱う
| Simple_Window や Graphic_Windowのマウスイベントや、コントロールウィ
ンドウの各ダイアログの動作は XRS では"dialog型"の変数で行なっていま
す。
"dialog型"はダイアログの動作の基本となる関数や変数をセットにした型(
クラス)で、dialog型を元にして作られた型(派生クラス)に void (*)(in
t)関数を扱う"f_dialog型"、double,int,complexをそれぞれ扱う"d_dialog
型","i_dialog型","c_dialog型"が変数の表示やマウスイベント処理を担当
しています。
したがって、これらのdialog型を直接扱うことでダイアログを個々に扱えま
す。ここでは、幾つかの例を上げて説明します。
- ‘Simple_Window のダイアログを表示する。’
Simple_Window や Graphic_Window は1つのダイアログを登録できます。普
通、<< で void (*)(int)関数を登録した時には自動的にその関数に対する
マウスイベント処理をする"f_dialog型"変数が宣言され、ダイアログの大き
さ(=マウスクリックを受け付ける範囲)がウィンドウ全体にリサイズされ
ます。登録されたダイアログは表示(redraw)されないので見えません。
内部で宣言されたダイアログのポインタは dialog *event()関数で取り出せ
るので必要ならリサイズや表示ができます。
| ------- test1-11.C -------------
#include <XRS/Simple.h>
using namespace XRS;
void f(int n){ printf("%d\n",n); }
Simple_Window A(200,200);
int main(){
A<<"drawing a dialog"<<f;
initialize();
dialog *p=A.event();
p->move(50,10);
p->resize(120,40);
p->title("F");
while(1) checkevent();
exit(0);
}
-----------------------------
|
この例では取り出したポインタ p の関数
void move(i,j); ダイアログの移動
void resize(width,height); ダイアログのリサイズ
void title(char *s); タイトルを s に設定して redraw();
void redraw(); ダイアログの描画
を使ってウィンドウの一部にダイアログを表示しています。
- ‘Simple_Window で1つの変数を表示する。’
関数を処理する"f_dialog" の代わりに、別のダイアログを登録すれば変数
表示も可能です。(複数表示したいときはコントロールウィンドウを子ウィ
ンドウで開けばいいでしょう。)
| ------- test1-12.C -------------
#include <XRS/Simple.h>
#include <XRS/d_dialog.h>
using namespace XRS;
Simple_Window A(200,200);
int main(){
double t=0;
A<<"display a variable";
initialize();
d_dialog p(A,t);
p.title("t");
while(1){ checkevent(); p.draw(); t+=0.01;}
exit(0);
}
-----------------------------
|
Simple_Window では普通 f_dialog しか使わないので、d_dialog 型のダイ
アログを使うには <XRS/d_dialog.h> をインクルードする必要があります。
d_dialog p(A,t); はダイアログの宣言です。引数は(登録される親ウィン
ドウ、処理の対象になるdouble変数)という形式です。タイトルを設定、表
示して、ループの中で変数の値を表示する void p.draw(); 関数を実行して
います。
- ‘Control_Window のダイアログの削除。’
コントロールウィンドウは複数の"dialog"を登録できます。普通は自動的に
<< で並べた関数や変数に応じて一つずつダイアログができます。ダイアロ
グへのポインタは
dialog *event(int n); // n 番目の dialog(負なら最後からの順番)
dialog *event(char *s); // タイトルが s の dialog
で取り出せます。
| --------- test1-13.C ---------------------
#include <XRS/Control.h>
using namespace XRS;
Control_Window A;
double x;
void f(int){
dialog *d=A.event("X");
if(d){ delete d; d=NULL; A.redraw(); }else{ A<<x<<"X"; }
}
int main(){
A<<f<<"parameter"<<PARAMETER;
initialize();
while(1) checkevent();
exit(0);
}
---------------------------------------
|
この例では "parameter" 欄がクリックされるたびに "X" 欄があるか調べて
あれば delete で消滅させ(登録が削除されただけなので、コントロールウ
ィンドウを redraw() で書き直す必要がある。)、なければ新しく作ります
。
- ‘タイトルだけのダイアログを作る。’
ダイアログのポインタ dialog *d を取り出した後、変数 d.chev を調べる
とウィンドウがクリックされたときそのダイアログのどの欄がクリックされ
たか(クリックされていなかったら0)がわかります。それで、タイトルだ
けのダイアログも時には役に立ちます。
"f_dialog" 型の変数は通常、f_dialog p(親ウィンドウ,処理する関数); と
いう形で宣言しますが、処理する関数を与えないとタイトルだけのダイアロ
グが作れます。( 残念ながら、<< では作れません。)
| --------- test1-14.C ---------------------
#include <XRS/Control.h>
using namespace XRS;
double a;
Control_Window A(0,0,0);
/*第1、第2引数の大きさは0以下を指定するとデフォルトのまま*/
int main(){
A<<PARAMETER<<a<<"A";
initialize();
f_dialog q(A); /* 第2引数を与えないで宣言 */
q.title("quit");
A.redraw();
while(!(A.chev && q.chev)) checkevent();
exit(0);
}
---------------------------------------
|
この例では Control_Window の宣言時に三番目の引数に0を指定してデフォ
ルトの "start⇔quit"ダイアログ を使うことをやめ、自分で "quit" とい
うタイトルの空ダイアログを作っています。d.chev を調べてその欄がクリ
ックされていたら終了します。
|
2.2.8 カスタマイズの例
| XRS のウィンドウの表示は Xリソース(.Xdefaults など)でいくらか好み
に合わせてカスタマイズできます。(Xリソースの書き方は XWindow のマニ
ュアルに書いてあるのでそっちを見てください。)
スタンダードな方法は各自のホームディレクトリにある".Xdefaults"ファイ
ルを使う方法です。".Xdefaults"ファイルに書いた場合その設定はすべての
プログラムで使われます。
また、プログラムのあるディレクトリの下に ".xrsrc" というファイル(こ
の名前はインストール時に変更されている可能性がある。)を作って書くこ
ともできます。この場合はそのディレクトリで走らせたプログラムでのみそ
の設定になります。
<例>
- ‘ダイアログのフォントをもう少し大きい 10x20 にする。’
| ---------------------------------
Xrs.Window.Control.Height: 60
Xrs.Dialog*Width: 120
Xrs.Dialog*Height: 30
Xrs*Font: 10x20
---------------------------------
|
最初の3行でフォントが収まるようにダイアログの大きさ調節しています。
- ‘ダイアログを縦に並べる。’
| ---------------------------------
Xrs.Window.Control.Width: 240
Xrs.Window.Control.Height: 800
Xrs.Dialog*Width: 120
Xrs.Dialog*Height: 30
Xrs.Dialog*Shape: 1
---------------------------------
|
最初の2行でコントロールウィンドウを縦長にして、
最後の Shape でダイアログに横長の形を指定しています。
|
2.3 上究編
| class window を派生させて作ったウィンドウや class dialog から作った
ダイアログは自動的に XRS の基本的な機能を引き継ぎます。C++の特徴
を生かせば、新しいウィンドウやダイアログを自由に付け加えることができ
ます。
この編では C++使いのために機能拡張編を書こうかと思っていましたが、
* C++使いならプログラムを読んだ方が早い。
* このマニュアル自身がプログラム本体より既に長い。
のでやめることにしました。
|
2.4 XRS version.2 からの移行
| XRSver2 と XRSver3 は中身が全く違い、互換性もなくなってしまったので
、 ver.2 用のプログラムは手直しないと動きません。しかし、あまりマニ
アックなことをしていない限り、以下の書き換えをすれば済むはずです。
書き換えの例を ver.2のプログラム ⇒ ver.3 のプログラム というふうに
示します。
- ‘インクルードファイル’
#include <XRS/XRS.h> ⇒ #include <XRS/Control.h>
#include <XRS/Graphic.h>
※ draw_point() や draw_2D() を使っていない場合は <XRS/Graphic.h> よ
り <XRS/Simple.h> のほうが軽くて便利。
- ‘ウィンドウの宣言’
XRS X; ⇒ Control_Window CW;
Graphic_Window W0,W1,,,;
※ Graphic_Window は必要なウィンドウの数だけ宣言する。
- ‘<<演算子の設定、初期化’
X<<EVENT<<func<<"FUNC"<<PARAMETER<<x<< "X"
<<UNMAP(1)
<<WINDOW(i,j,k)<<"title";
X.initialize(t);
⇒
CW<<t<<"t"<<func<<"FUNC"<<PARAMETER<<x<<"X";
W0.geometry(i,j,k)<<"title"<<MEMORY;
initialize();
※ X.、EVENT はいらない。
※ ウィンドウごと(CW,W0,,,)に設定。
※ X.initialize の引数はコントロールウィンドウ(Control)のPARAMETERの
前に書く(タイトルが必要)。initialize() は引数をとらない。
※ サイズ指定 WINDOW(i,j,k) は (ウィンドウ名).geometry(i,j,k)。
※ <<UNMAP(1) を使っていたら、ウィンドウごとに <<MEMORY を指定。
※ MONO,PHASE の色は xcoloredit コマンドと同じになるように変更されま
した。
MONO(θ,n ) ⇒ MONO(θ/2π-1/6, n)
とすればだいたい同じ色になります。
- ‘関数’
X.checkevent(); ⇒ checkevent();
X.draw_point(w,i,j); ⇒ W0.draw_point(w,i,j);
X.draw_2D(P,0); ⇒ W0.draw_2D(P);
X.clear_window(0); ⇒ W0.clear();
sample_window(X,0); ⇒ sample_window(W0);
gc=X.graphic_context(X.color_pixel("blue"));
⇒ gc=graphic_context("blue");
n=X.graphic_context(gc,"filename");
⇒ n=graphic_context(gc,"filename");
P=array(i,j); ⇒ array(P,i,j);
※ X.は要らない。
※ ウィンドウ番号はなくなり、各ウィンドウごとの変数を使う。
※ X.graphic_context(X.color_pixel("色名")) は graphic_context("色名
") でよい(もとのままも可)。
※ array 関数は返り値が void になり、引数で配列のポインタを渡す。
- ‘変数’
d=X.d; ⇒ d=W0.disp();
black=X.bgc; ⇒ black=W0.bgc;
white=X.wgc; ⇒ white=W0.wgc;
XDrawPoint(d,X.win[0],gc,i,j); ⇒ XDrawPoint(d,W0,gc,i,j);
※ ディスプレイIDは (ウィンドウ名).disp()。(直接、コマンドの中に
W0.disp()と書いても遅くはならない。)
※ black,white のグラフィックコンテキストは Simple_Window か
Graphic_Window の bgc,wgc(または graphic_context関数)を使う。
※ ウィンドウIDを書く場所にはウィンドウ変数をそのまま書く。
|
3. 仕様
3.1 この章の見方
ある程度、仕掛けがわかった方が理解しやすいと思うので XRS の内部構成についてのおおざっぱな解説を ”全体の構成”、”ウィンドウ”、”ダイアログ”、”その他の道具” の各節にまとめました。
しかし、手っ取り早く関数を調べたい時は次のようにしてください。
-
プログラム中で使っている XRS のヘッダファイルの名前と同じ節を見に行
く。(例えば、<Graphic.h> を使っていたら、Graphic Window を見る。)
-
関数の一覧を見て、同名同型のものがあればその仕様を見る。(例えば、MO
NO(double,int) などは Graphic Window の節で見つかる。)
-
なかったら、そのクラスのベースになっているクラスの節に行って同名同型
の関数を探す。
( window → simple window → graphic window → Graphic Window とい
うふうに基本的なクラスから高次のクラスができているので、この順番
を逆にたどって関数を探していく。例えば、関数clear() の頁は simple
window と graphic window の両方の節にあるが、Graphic_Window で使
われる clear() は最初に見つかった graphic window の方になる。)
| +++++++++++++ 各頁の構成 +++++++++++++++++++++++++++++++++++++
仕様の各頁はだいたい次のような構成です。
各頁はそれぞれ1つのインクルードファイルの中身の説明になっています。
たとえば、window の頁の関数、クラスを使うためには始めに書かれている
ように XRS/window.h のインクルードが必要です。
- ‘グローバル変数、関数’
グローバルな変数や関数がそのインクルードファイルで定義されていたら、
その仕様を説明します。(ただし、マニピュレーターの説明は後)
- ‘クラスの宣言’
クラスの説明でははじめにそのクラスの変数の宣言の仕方が書かれています
。クラスの定義というのは新しい型を作ることなので、宣言された変数は d
ouble型変数などと同じようにそのクラスの型をもつ1つの変数として扱わ
れます。従って、スコープや寿命は普通の変数と全く同じです。
- ‘public変数、関数’
プログラム中で使える公開メンバーです。"(宣言したクラスの変数名).(変
数、関数名)"という書式でプログラム中で使うことができます。
基底クラスの public(公開)変数 や public関数は(同名の関数が定義さ
れていない限り)派生クラスの public変数、public関数でもあるので派生
クラスからも同様に使えます。
- ‘マニピュレータ’
マニピュレータは << 演算子の中で使われ、そのクラスに特定の処理をする
特別なグローバル関数です。
- ‘protected変数、関数’
非公開メンバーでプログラム中では使えません。(XRS の仕掛けを知るため
に重要なので "protected" 関数の説明も載せましたが、実際のプログラミ
ングには関係ありません。)
†
各関数の説明の後ろには / に続けて使用例を書いてあります。
†
同名の関数との混乱を避けるために、文章中では別のクラスの関数は ”ク
ラス名::関数名”、グローバル関数は ”::関数名”と表記します。(例え
ば、window::event() と書いてあったら、class window の節に説明のある
event() 関数のことです。)
†
関数の引数で int w=0 などと書かれているものは、その引数は省略可能で
、省略した場合 = の後の値が代入されることを示しています。
(例えば、move(int i=0,int j=0) と書かれていたら、move(100); とする
と move(100,0); が、move(); とすると move(0,0) が実行されます。)
†
デフォルト値とその変更については、”デフォルト値とカスタマイズ” の
節を御覧下さい。
†
戻り値の型の前に virtual がついている関数は仮想関数です。仮想関数は
派生先のクラスで同名同型で関数を定義しなおすことができます。
例えば、virtual int window::redraw() は class window から派生して
いる class graphic_window の int graphic_window::redraw() で上書きさ
れています。従って、
/ graphic_window A(100,100); と graphic_window を宣言し、
/ window *W=&A; class window のポインタに代入し、
/ W->redraw(); window::redraw() 関数を使った時、
実行されるのは graphic_window::redraw() です。
|
3.2 全体の構成
XRS には class window と class dialog という2つの基本的なクラス(関数、変数の集合体)があります。
class window は XRS で開くすべてのウィンドウの原型(基底クラス)で、このクラスに目的に合わせた機能を付け加えていくことで control window や graphic window などの高次のクラス(派生クラス)が作られています。
基底クラスの機能が派生クラスに引き継がれるだけでなく、基底クラスに対して定義された関数は派生クラスに対しても使うことができます。各自のプログラム中で使われる initialize関数や checkevent 関数は class window に対して働くように定義されているので、class window から派生したすべてのウィンドウは自動的に initialize関数、checkevent 関数 の実行の対象になります。
プログラム中で使われる各種のウィンドウは以下のように class window から派生しています。
| window class window
│
├ simple window class simple_window
│ │└Simple Window class Simple_Window
│ │
│ ├graphic window class graphic_window
│ │└Graphic Window class Graphic_Window
│ │
│ └plane window:: class plane_window
│ └Plane Window:: class Plane_Window
│
└ control window class control_window
├ Control Window class Control_Window
└ Complex Control Window class Complex_Control_Window
|
class dialog は control window と simple window に ( 従って graphic window や plane window にも) 登録されて特定の関数や型に対するマウスイベントの処理やパラメータの表示を受け持つクラスです。通常の簡単なプログラミングではプログラム中に出てくることはなく、XRSの内部で活躍しています。各ダイアログは登録されたウィンドウで1つの担当区域を受け持ちます。イベントの処理の仕方の違いに対応して、関数を扱うclass f_dialog、double型の変数を扱う class d_dialog などに派生しています。
| dialog class dialog
│
├ function dialog class f_dialog
├ double dialog class d_dialog
├ int dialog class i_dialog
└ complex dialog class c_dialog
|
XRS にはその他にプログラミングの際に役に立つ道具が幾つかあります。
これらは必要に応じて各ウィンドウで使われていますが、XRS と独立に include して使うこともできます。
-
color.h: グラフィックコンテキストやカラーピクセルを用意する関数群
-
XResource.h: Xリソースデーターベースを扱う関数群
-
List.h: 任意の型に対するリスト型を作れるtemplateクラス
-
Array.h: 任意の型に対する動的配列をとるtemplate関数
-
Exec.h: コマンドを子プロセスで実行するためのクラス
-
Socket.h、DataSocket.h: ソッケトを開くクラス
3.3 ウィンドウ
XRSを使うとまず始めに XRS/window.h が必ず include されて class window が定義されます。同時に、デフォルトのルートウインドウ window XRS_ROOT と class window のポインタのリスト List<window*> XRS_list がグローバル変数として用意されます。
プログラム中で宣言されるウィンドウは特に指定しない限り XRS_ROOT を親ウィンドウとして開かれ、自動的にポインタが XRS_list に登録されます。 XRS_list に登録されているウィンドウは void initialize()関数と void checkevent()関数の処理の対象になります。
initialize 関数はプログラム中で通常1回使われます。initialize() を実行するまえに宣言されたウィンドウはディスプレイに現れる(マップする)のを抑制されます。 initialize() 関数はそれらのウィンドウをマップし、各ウィンドウの描画( window::draw() )と初期化処理( window::startup() )をします。
checkevent 関数は通常ループの中に入れて使われます。checkevent() はwindow::checkevent() 関数を実行し各ウィンドウのイベント処理を行ないます。
※ C++では class window から派生したクラス( Simple_Window など)のポインタも window のポインタに代入できるので、class window から作られたすべてのウィンドウを XRS_list で一括管理しています。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
XRS では関数や変数などに対するイベント処理は class dialog が専門に受け持っています。class window は 1つのイベント (class dialog) を登録できる simple_window と 複数のイベントを登録できる control_window に派生します。simple_window はさらに描画関数を備えた graphic_window や plane window に派生しています。
大文字から始まる Simple Window, Graphic Window, Plane_Window, Control Window, Complex Control Window は プログラミングをしやすいように演算子<< など追加して派生させたクラスで 小文字のもとのクラスと基本的な機能は同じです。
※ Complex Control Window は complex型のダイアログ(c_dialog)に対するインターフェイスをもった Control Window です。内部で <complex.h> を include するため、これを使うとファイルサイズがかなり大きくなります。
3.3.1 window
class window は XRS で使われるすべての ウィンドウの基底クラスです。
つまり、「XRSのウィンドウとは〜 」という定義みたいなもので、どのウィ
ンドウも class window を土台にして作られています。
†#include <XRS/window.h> が必要
†<XRS/window.h>の中で <XRS/XResource.h>,<XRS/List.h>,<XRS/Array.h>
がincludeされる。
- ‘グローバル変数’
-
-
window XRS_ROOT(NULL);
デフォルトの親ウィンドウ。環境変数 DISPLAY のディスプレイを
オープンする。もし、XRSBG がマクロ定義されていたら、かわり
に window XRS_ROOT("&"); を実行し、ディスプレイとの接続、
描画をしないようにする。
-
List<window*> XRS_list;
ウィンドウのリスト。宣言されたwindowのポインターが自動的
に登録される。
(※ XRS_list の要素は自由に変更できます。See section List.h.)
-
int XRS_map=0;
ウィンドウのマップ(可視化)を initialize() まで抑制するた
めの変数。XRS_map=1 なら宣言された window はすぐに見えるよ
うになる。
- ‘グローバル関数’
-
void initialize(void);
XRS_listに登録されたウィンドウをマップし( window::map() )、
window::startup()関数を実行する。XRS_map=1 にする。
-
void checkevent(void);
XRS_listに登録されたウィンドウのイベント処理
( window::checkevent() )をする。
- ‘class window 変数の宣言’
-
ルートウィンドウRを作る。[通常不要]
window R(disp_name,rc_name);
char * disp_name ディスプレイ名 "haku:0.0" など。
char * rc_name=NULL; リソースファイル名
指定されたディスプレイを開き、リソースデーターベース rDB、
デフォルトカラーマップ cm、カラーピクセルblack,white を確保
する。ルートウィンドウのIDを持ち、親ウィンドウのIDには 0が
セットされる。
disp_name==NULL ⇒ disp_name=DISPLAY(環境変数)
disp_name=="&" ⇒ ディスプレイを開かない。
rc_name ==NULL ⇒ rc_name=XRS_RESOURCE_FILE
(see XRS/define.h)
†disp_name=="&"で作った window とその子ウィンドウではディ
スプレイへの描画は一切おこなわれません。バックグラウンド
ジョブなどのために XRS の機能を停止したいときに使います。
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
window A(W,h,w,i,j,bw,ms);
window &W; 親ウィンドウ
int w; 幅。 0以下は1と同じ。
int h; 高さ。0以下は1と同じ。
int i=0; x座標 ( 親ウィンドウの左上隅が原点)
int j=0; y座標
int bw=-1; ボーダーの幅。負ならディフォルト値。
int ms=1; 可視状態にするなら0以外の値にする。
rDB 、cm、black,white は親ウィンドウのものを引き継ぐ。
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
window B(w,h,ms);
int w=0; int h=0; int ms=1;
window B(XRS_ROOT,h,w,0,0,-1,ms); と同じ。
- ‘class window の public(公開)変数’
-
XEvent ev; イベント構造体 / B.ev;
-
int chev; checkevent() で値がセットされる。/B.chev
-
XrmDatabase rDB; リソースデーターベース / B.rDB;
-
Colormap cm; カラーマップ / B.cm;
-
unsigned long black,white; 黒と白のカラーピクセル / B.black;
- ‘class window の public 関数’
-
Display* disp(); display ID を返す。
-
operator Window(); Window ID への型変換。
/ XClearWindow(B.disp(),B);
-
Window root(); 親ウィンドウのIDを返す。 / Window r=B.root();
-
int width(); 幅を返す。 / int w=B.width();
-
int height(); 高さを返す。 / int h=B.height();
-
void resize(int width=0,int height=0); / B.resize(50,50);
ウインドウのリサイズ。非正値なら現状維持。
-
void move(int i=-1,int j=-1);
ウインドウを(i,j)へ移動。 / B.move(100,200);
親ウィンドウの左上隅が原点で、負値なら現状維持。
-
char* title(); タイトルを返す。 /char *s=B.title();
-
void title(char*); タイトルの変更。 /B.title("NEW TITLE");
-
int eventmask(); イベントマスクを返す /int *m=B.eventmask();
-
void eventmask(int); イベントマスク設定。
/B.eventmask(KeyPressMask);
-
void map(void); ウインドウをマップ(可視化)してredraw()を実行。
† ::initialize()関数から実行される時(XRS_map==0
の時)は redraw() の代わりに draw() が実行され
る。 / B.map();
-
void unmap(void); アンマップ(不可視化)する。 / B.unmap();
仮想関数(派生先で再定義されている可能性がある)
-
virtual void draw(){} ウィンドウの描画。 / B.draw();
-
virtual void redraw(){} ウィンドウの再描画。 / B.redraw();
-
virtual void checkevent(); イベント処理 / B.chekevent();
ウインドウにイベントが発生したかをチェックして、chev
にマウスイベントの時はマウスボタンの番号、それ以外は
0をセットする。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ‘class window の protected 関数(非公開)’
-
以下の関数は仮想関数で、普通、派生先で再定義されます。
-
virtual void add(dialog &){} ダイアログの登録
† class dialog の宣言時に実行される。
-
virtual void remove(dialog *){} ダイアログの削除
† class dialog の消滅時に実行される。
-
virtual void startup(){} 初期化処理
† ::initialize() のなかで実行される。
3.3.2 simple window
class simple_window は class window から派生したクラスです、class dialog を一つ登録して(See section dialog.)、1つのイベント処理をさせることができます。また、XRS/color.h を include しているので color 関係の簡易関数を使えます。See section color.h.
†#include <XRS/simple.h> が必要
†<XRS/simple.h>の中で <XRS/window.h>,<XRS/color.h>,<XRS/dialog.h>が
includeされる。
- ‘class simple_window の宣言’
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
simple_window A(W,w,h,i,j,bw);
window &W; 親ウィンドウ
int w=0; 幅。 0以下は1と同じ。
int h=0; 高さ。0以下は1と同じ。
int i=0; x座標 ( 親ウィンドウの左上隅が原点)
int j=0; y座標
int bw=-1; ボーダーの幅。負ならディフォルト値。
bgc,wgc が用意
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
simple_window B(w,h);
int w=0; int h=0;
simple_window B(XRS_ROOT,h,w,0,0,-1); と同じ。
- ‘class simple_window の public(公開)変数’
-
class window の public(公開)変数
-
GC bgc; 黒のグラフィックコンテキスト / GC black=B.bgc
-
GC wgc; 白のグラフィックコンテキスト / GC white=B.wgc
- ‘class simple_window の public関数’
-
class window の public関数
-
void clear(); ウィンドウのクリアー /B.clear();
-
dialog* event(); 登録されているダイアログへのポインタを返す。
/ dialog *p=B.element();
-
virtual void checkevent();
イベント処理(仮想関数) / B.chekevent();
Exposeイベントが発生していたら redraw() を実行する。
ButtonPressイベントが発生していたら登録されているダイア
ログの dialog::checkevent() を実行する。
chev にマウスイベントの時はマウスボタンの番号、それ以外
は0をセットする。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ‘class simple_window の protected 関数(非公開)’
-
class window の protected 関数
-
void add(dialog &p); 登録 dialogのポインタの変更(仮想関数)
-
void remove(dialog *p); pが登録されていたら削除する(仮想関数)
3.3.2.1 Simple Window
class Simple_Window は class simple_window から派生したクラスです。
基本的な機能は simple_windowと同じですが、<< 演算子を使って大きさ、
位置、タイトルの設定、関数の登録が簡単にできます。
†#include <XRS/Simple.h> が必要
†<XRS/Simple.h>の中で <XRS/simple.h>,<XRS/f_dialog.h> が includeされる。
- ‘class Simple_Window の宣言’
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
Simple_Window A(W,w,h,i,j,bw);
引数は simple_window A(W,w,h,i,j,bw); と同じ。
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
Simple_Window B(w,h);
int w=0; int h=0;
Simple_Window B(XRS_ROOT,h,w,0,0,-1); と同じ。
- ‘class Simple_Window の public(公開)変数’
-
class simple_window の public変数
- ‘class Simple_Window の public関数’
-
class simple_window の public関数
-
Simple_Window& geometry(int w=0,int h=0,int i=-1,int j=-1)
ウィンドウのリサイズ(幅 w、高さ h)と移動(x座標 i、
y座標 j)。 w,hは非正値、i,jは負値なら現在値を変更しない。
返り値は自分自身へのポインターなので、<< を続けて書くこ
とができる 。
( simple_window::resize(w,h) と window::move(i,j) を
実行する。)
/ B.geometry(100,200);
-
Simple_Window& operator<<(char *name);
タイトルの変更。( window::title(name)関数を実行する。)
/ B<<"How are you?";
-
Simple_Window& operator<<(void (*f)(int));
add(void (*)(int)) を << 演算子でできるようにしたもの。
代入された void (*f)(int)型関数のf_dialog を作って登録し、
マウスの n 番目のボタンでウィンドウをクリックしたとき
f(n) が実行されるようにする。
/ void g(int n){ printf("%d\n",n); }
/ B<<g;
3.3.3 graphic window
class graphic_window は class simple_window から派生した2次元グラフィック専用のクラスです。内部に描画用の色の配列と、描画した色を覚えておくメモリーを持ち、描画関数 draw_point() と draw_2D() を備えています。また、色を手軽に作れるように monotone(),phasetone(),color_resource() 関数が用意されています。
†#include <XRS/graphic.h> が必要
†<XRS/graphic.h>の中で <XRS/simple.h> が includeされる。
- ‘グローバル関数’
-
void sample_window(graphic_window &);
色のサンプルを描画する。
/例 graphic window C(100,20); sample_window(C);
- ‘class graphic_window の宣言’
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
graphic_window A(W,i_max,j_max,ms,i,j,bw);
window &W; 親ウィンドウ
int i_max=0; latticeの幅。 0以下はデフォルト値
int j_max=0; latticeの高さ。0以下はデフォルト値
int ms=0; latticeのmesh size。0以下はデフォルト値。
int i=0; x座標 ( 親ウィンドウの左上隅が原点)
int j=0; y座標
int bw=-1; ボーダーの幅。負ならディフォルト値。
幅 i_max*ms、高さ j_max*ms のウィンドウができる。
描画関数は ms x ms の正方形を1単位として描画する。
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
graphic_window B(i_max,j_max,ms)
int i_max=0; int j_max=0; int ms=0;
graphic_window B(XRS_ROOT,i_max,j_max,ms,0,0,-1); と同じ。
- ‘class graphic_window の public(公開)変数’
-
class simple_window の public変数
-
GC gc; 描画関数で使われるグラフィックコンテキスト /GC g=B.gc;
- ‘class graphic_window の public関数’
-
class simple_window の public関数
-
int i_max(); lattice の幅を返す。 / int i_max=B.i_max();
-
int j_max(); lattice の高さを返す。/ int j_max=B.j_max();
-
int mesh_size(); lattice の mesh size を返す。
/ int ms=B.mesh_size();
-
void resize(int i_max=0,int j_max=0,int ms=0);
リサイズ。非正値なら変えない。/ B.resize(0,0,2);
-
void clear(); クリアー。内部メモリーも初期化する。/B.clear();
-
unsigned long** memory(); / unsigned long **c=B.memory();
内部メモリーを用意してポインタを返す。すでにある場合は
ポインタを返すだけ。このメモリーは描画の高速化と画面の
再描画のために使われる。
-
int free_memory(); / int n=B.free_memory();
内部メモリーをなくす。なくしたら1、すでになかったら0
を返す。メモリーを節約したい時は有効。
-
void redraw(); 再描画する。(仮想関数) / B.redraw();
†Exposeイベントに対して実行される。
描画関数
-
void point(int w,int i,int j);
座標(i,j)に w 番目の色の点を描く。
/ B.point(2,10,20);
※ int w の値から色が決まる方法
0<=n<colornumber ⇒ 色配列の n 番目の色 color[n]を描く。
n>=colornumber ⇒ color[colornumber] の色(maxcolor)
n < 0 ⇒ color[colornumber+1] の色(mincolor)
-
void line(int w,int i1,int j1,int i2,int j2);
座標(i1,j1)から (i2,j2) まで w 番目の色の直線を引く。
/ B.line(2,10,20,30,50);
-
void circle(int w,int i,int j,double r);
中心(i,j)、半径 r の w 番目の色の円を描く。
/ B.circle(2,10,20,15);
-
void draw_point(double w,int i,int j);
座標(i,j)に色 w の点を描く。 /B.draw_point(0.5,10,20);
※ double w の値から色が決まる方法
登録されている色関数 double f(double) を使って、
point((int)(f(w)*colornumber),i,j); を実行する。
-
void draw_line(double w,int i1,int j1,int i2,int j2);
座標(i1,j1)から (i2,j2) まで色 w の直線を引く。
※ 登録されている色関数 double f(double) を使って、
line((int)(f(w)*colornumber),i1,j1,i2,j2); を実行。
/ B.line(0.5,10,20,30,50);
-
void draw_circle(double w,int i,int j,double r);
中心(i,j)、半径 r の色 w の円を描く。
※ 登録されている色関数 double f(double) を使って、
circle((int)(f(w)*colornumber),i1,j1,i2,j2); を実行。
/ B.circle(2,10,20,15);
-
void draw_2D(int **w);
すべての座標(i,j)に 二次元配列 w[i][j] 番目の色の点を
描く。ただし、二次元配列 double **w は動的配列とする。
動的2次元配列は 関数 array によってとれる。See section Array.h.
-
void draw_2D(double **w);
すべての座標(i,j)に 二次元配列 w[i][j] によって決まる色
の点を描く。ただし、二次元配列 double **w は動的配列とする。
動的2次元配列は 関数 array によってとれる。See section Array.h.
※登録されている色関数 double f(double) を使って、
(int)(f(w[i][j])*colornumber) 番目の色で draw_2D(int**)
を実行するのと同じことをする。
/ double **w;
/ array(w,B.i_max(),B.j_max());
/ for(i=0; i<B.i_max(); i++)
/ for(j=0; j<B.j_max(); j++)
/ w[i][j]=(double)i/B.i_max();
/ B.draw_2D(w);
色関数 : 描画関数に与えられた double の値から色配列の描画する色番号
を決める double (*)(double) 型の関数。(see draw_point();)
-
void color_function(double (*f)(double));
色関数を登録する。/ double f(double x){ return fabs(x);}
/ B.draw(f);
デフォルトの関数 default_color_function は
double default_color_function(double W){return(W*W*AMPF);}
です。AMPF は XRS/define.h で定義されています。
色配列 :描画する色のカラーピクセルの配列。colornumber+2 個の要素を
持ち、colornumber 番目にmaxcolor、colornumber+1 番目に
mincolorのカラーピクセルを持つ。(see draw_point();)
-
unsigned long *color_pixel();
色配列へのポインターを返す。
/ unsigned long *c=B.color_pixel();
/ c[0]=color_pixel("red");
-
int color_number();
colornumberを返す。/ int n=B.color_number();
-
void color_pixel(c,colornumber,maxcolor,mincolor);
unsigned long *c; カラーピクセルの配列
int colornumber; 色の数
char* maxcolor=NULL; 色番号>=colornumberの時に描く色の名前
char* mincolor=NULL; 色番号<0の時に描く色の名前
自分で作った色配列を登録する。
maxcolor=NULL ⇒ デフォルト値
mincolor=NULL ⇒ デフォルト値
/ unsigned long c[1]; c[0]=color_pixel("red");
/ B.color_pixel(c,1,"green","blue");
-
void free_color_pixel(c,n); / B.free_color_pixel();
unsigned long *c=NULL; カラーピクセルの配列
int n=0; 配列の要素数
カラーマップからカラーセルを解放する。
! 使用中の色配列を解放すると色が変になるので注意。
c=NULL ⇒ 現在の色配列
-
void monotone(h,colornumber); / B.monotone(0.2,5);
double h=-1; 色相(Hue) 0=<h=<1
int colornumber=0; 色数
色相(Hue) h、明度(Value) 1.0 の色を飽和度(Saturation)を連
続的に変えながら、colornumber個用意する。HSVからRGB値への
変換方法はxcoloreditコマンドと同じ。(see See section color.h.)
h<0 || h>1 ⇒ デフォルト値
colornumber <=0 ⇒ デフォルト値
-
void phasetone(h,colornumber); / B.phasetone(0.2,5);
double h=-1; 色相(Hue) 0=<h=<1
int colornumber=0; 色数
明度(Value) 1.0 、飽和度(Saturation) 1.0 の色を色相(Hue)
h の色から連続的に色相を変えながら、colornumber個用意す
る。HSVからRGB値への変換方法はxcoloreditコマンドと同じ。
(see See section color.h.)
h<0 || h>1 ⇒ デフォルト値
colornumber <=0 ⇒ デフォルト値
-
void color_resource(char *filename =NULL);
ファイル filename から色名を読み込んで、色配列を作る。
返り値は色数。
filename =NULL ⇒ デフォルト値
†カラーリソースファイルの書き方
各行には1つの色名を書く。
空行は読み飛ばされ、!で始まる行はコメントとみなされる。
/ —– ファイル "color" の中身 ——-
/ ! color resource sample
/ red
/ blue
/ green
/ ————————————-
/ B.color_resource("color");
†色名は X11R5 で許されるものすべてで、# ではじまるRGB値名、
TekHVC:ではじまる HVC値名でもいい。ただし、HVC値は
monotone, phasetone で使われる xcoloredit のHSV値とは
異なるので注意!。
/ red,#ff0000,TekHVC:0/50/90 など
†リソースファイルは既成のコマンド gimp や xcoloredit を使うと簡単
に作ることができる。(See section Graphic_Window 応用編.)
3.3.3.1 Graphic Window
class Graphic_Window は class graphic_window から派生したクラスです
。基本的な機能は graphic_windowと同じですが、<< 演算子を使って大きさ
、位置、タイトルの設定、関数の登録、描画関数の設定、色の指定が簡単に
できます。
†#include <XRS/Graphic.h> が必要
†<XRS/Graphic.h>の中で <XRS/graphic.h>,<XRS/f_dialog.h> が includeされる。
- ‘class Graphic_Window の宣言’
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
Graphic_Window A(W,i_max,j_max,ms,i,j,bw);
引数は graphic_window A(W,i_max,j_max,ms,i,j,bw); と同じ。
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
Graphic_Window B(i_max,j_max,ms);
int i_max=0; int j_max=0; int ms=0;
Graphic_Window B(XRS_ROOT,i_max,j_max,ms,0,0,-1); と同じ。
- ‘class Graphic_Window の public(公開)変数’
-
class graphic_window の public変数
- ‘class Graphic_Window の public関数’
-
class graphic_window の public関数
-
Graphic_Window& geometry(i_max,j_max,ms,i,j)
int i_max=0,j_max=0,ms=0,i=-1,j=-1;
ウィンドウのリサイズ(幅 i_max、高さ j_max、メッシュサイズ
ms)と移動(x座標 i、y座標 j)。i_max,j_max は非正値、
i,jは負値なら現在値を変更しない。返り値は自分自身へのポイ
ンターなので、<< を続けて書くことができる 。
( graphic_window::resize(i_max,j_max,ms) と
window::move(i,j)を実行する。)
/ B.geometry(100,200);
-
Graphic_Window& operator<<(char *name);
タイトルの変更。( window::title(name)関数を実行する。)
/ B<<"How are you?";
-
Graphic_Window& operator<<(void (*f)(int));
代入された void (*f)(int)型関数のf_dialog を作って登録し、
マウスの n 番目のボタンでウィンドウをクリックしたとき
f(n) が実行されるようにする。
/ void g(int n){ printf("%d\n",n); }
/ B<<g;
-
Graphic_Window& operator<<(double (*f)(double));
色関数の設定。( graphic_window::color_func(f)を実行する。)
/ double f(double x){ return fabs(x);}
/ B<<f;
- ‘マニピュレーター’
-
MONO(h=-1,colornumber=0);
色相(Hue) h、明度(Value) 1.0 の色を飽和度(Saturation)を
連続的に変えながら、colornumber個用意する。
( graphic_window::monotone(h,colornumber) を実行する。)
/ B<<MONO(0.4);
-
PHASE(h=-1,colornumber=0);
明度(Value) 1.0 、飽和度(Saturation) 1.0 の色を色相(Hue)
h の色から連続的に色相を変えながら、colornumber個用意する。
( graphic_window::phasetone(h,colornumber) を実行する。)
/ B<<PHASE(0.4,10);
-
COLOR(char* filename=NULL);
ファイル filename から色名を読み込んで、色配列を作る。
( graphic_window::color_resource(filename) を実行する。)
/ —– ファイル "color" の中身 ——-
/ ! color resource sample
/ red
/ blue
/ green
/ ————————————-
/ B<<COLOR("color");
-
COLOR(unsigned long c[],int n);
自分で作った色配列を登録する。
( graphic_window::color_pixel(c,n) を実行する。)
/ unsigned long c[1]; c[0]=color_pixel("red");
/ B<<COLOR(c,1);
-
MEMORY(Graphic_Window&);
内部メモリーがあれば、メモリーをなくす。
(graphic_window::free_memory() を実行)
内部メモリーがなければ、内部メモリーを用意してポインタを返
す。(graphic_window::memory() を実行)
Graphic_Window は宣言時に自動的に内部メモリーをとるので、
通常は内部メモリーをなくしてメモリーを節約するのに使われる。
/ B<<MEMORY;
3.3.4 plane window
class plane_window は class simple_window から派生したグラフィック専
用のクラスで、色ごとに仮想的なプレーンを持ち独立な描画ができます。宣
言のし方、public変数、関数はほとんど class graphic_window と同じなの
で違うところのみ説明します。
†plane_window で使用できる色は最大30色なので注意して下さい。
†#include <XRS/plane.h> が必要
†<XRS/plane.h>の中で <XRS/simple.h> が includeされる。
- ‘グローバル関数’
-
void sample_window(plane_window &);
色のサンプルを描画する。
/例 graphic window C(100,20); sample_window(C);
- ‘class plane_window の宣言’
-
plane_window A(W,i_max,j_max,ms,i,j,bw);
-
plane_window B(i_max,j_max,ms)
- ‘class plane_window の public(公開)変数’
-
class simple_window の public変数
-
GC gc;
- ‘class plane_window の public関数’
-
class simple_window の public関数
-
int i_max();
-
int j_max();
-
int mesh_size();
-
void resize(int i_max=0,int j_max=0,int ms=0);
-
unsigned long** memory();
-
int free_memory();
-
void redraw();
-
void clear(int p); p 番目のプレーンのクリア(引数を与えなけ
れば全プレーンをクリアする。) / B.clear(2);
描画関数
-
void draw_point(int p,int i,int j); /B.draw_point(5,10,20);
p番目のプレーンの座標(i,j)に点を描く。p番目のプレーンの
描画には色配列の p 番目の色 color[p] が使われる。
p>=colornumber ⇒ p=colornumber;
p < 0 ⇒ p=colornumber+1;
-
void draw_point(int p,int i,int j); /B.draw_point(5,10,20);
p番目のプレーンの座標(i,j)に点を描く。p番目のプレーンの
描画には色配列の p 番目の色 color[p] が使われる。
p>=colornumber ⇒ p=colornumber;
p < 0 ⇒ p=colornumber+1;
-
void erase_point(int p,int i,int j); /B.erase_point(5,10,20);
点を消す。
-
void draw_line(int p,int i1,int j1,int i2,int j2);
p番目のプレーンに座標(i1,j1)から (i2,j2) まで直線を引く。
-
void erase_line(int p,int i1,int j1,int i2,int j2);
直線を消す。
-
void draw_circle(int p,int i,int j,double r);
p番目のプレーンに中心(i,j)、半径 r の円を描く。
-
void erase_circle(int p,int i,int j,double r);
円を消す。
-
void draw_2D(int **p);
二次元配列 p[i][j] によって決まるプレーンの座標(i,j)に点
を描く。ただし、二次元配列 int **p は動的配列とする。
動的2次元配列は 関数 array によってとれる。See section Array.h.)
-
void erase_2D(int **p);
まとめて点を消す。
色配列
plane_window で使用できる色は最大30色(maxcolor,mincolor を
含めて32色)までなので注意して下さい。
-
unsigned long *color_pixel();
-
int color_number();
-
void color_pixel(c,colornumber,maxcolor,mincolor);
-
void free_color_pixel(c,n);
-
void monotone(h,colornumber);
-
void phasetone(h,colornumber);
-
void color_resource(char *filename =NULL);
3.3.4.1 Plane_Window
class Plane_Window は class plane_window から派生したクラスです
。基本的な機能は plane_windowと同じですが、<< 演算子を使って大きさ
、位置、タイトルの設定、関数の登録、色の指定が簡単にできます。
class Graphic_Window とほぼ同じなので説明は省略します。
†#include <XRS/Plane.h> が必要
†<XRS/Plane.h>の中で <XRS/plane.h>,<XRS/f_dialog.h> が includeされる。
- ‘class Plane_Window の宣言’
-
Plane_Window A(W,i_max,j_max,ms,i,j,bw);
-
Plane_Window B(i_max,j_max,ms);
- ‘class Plane_Window の public(公開)変数’
-
class plane_window の public変数
- ‘class Plane_Window の public関数’
-
class plane_window の public関数
-
Plane_Window& geometry(i_max,j_max,ms,i,j)
-
Plane_Window& operator<<(char *name);
-
Plane_Window& operator<<(void (*f)(int));
- ‘マニピュレーター’
-
MONO(h=-1,colornumber=0);
-
PHASE(h=-1,colornumber=0);
-
COLOR(char* filename=NULL);
-
COLOR(unsigned long c[],int n);
-
MEMORY(Plane_Window&);
3.3.5 control window
class control_window は class window から派生したクラスで、マウスクリックによる関数の実行や、パラメータチューニングなどを行なうための専用ウィンドウです。複数のイベント処理をするため、登録される class dialog (See section dialog.)へのポインタリストを内部に持っています。
control_window は登録された dialog の表示位置を決めてダイアログの大きさに合わせてウィンドウをリサイズして表示します( redraw()関数 )。そして、グローバル関数 ::checkevent() が実行されたとき、
-
dialog::draw()関数を実行する。(real time 表示/realtime=1)
-
マウスイベントがあればクリック位置(x,y) を代入して dialog::checkeven
t(x,y) を実行する。(マウスイベント処理/realtime=0)
のいずれかを行ないます。どちらの処理をするかはダイアログの登録(宣言)時の public変数 realtime の値で決まります。
†#include <XRS/control.h> が必要
†<XRS/control.h>の中で <XRS/f_dialog.h> が includeされる。
- ‘class control_window の宣言’
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
control_window A(W,imax,jmax,i,j,bw,st);
window &W; 親ウィンドウ
int imax=0; 幅。 0以下はデフォルト値
int jmax=0; 高さ。0以下はデフォルト値
int i=0; x座標 ( 親ウィンドウの左上隅が原点)
int j=0; y座標
int bw=-1; ボーダーの幅。負ならディフォルト値。
int st=1; st=0 なら start⇔quit, pause⇔continue をするデ
フォルトの dialog の登録を抑制する。
realtime=0 に初期設定する。
†コントロールウィンドウのサイズとダイアログの配置は
以下の手順で決まります。
[imax > jmax の場合]
1. ダイアログ登録順に縦に並べていき、並べたダイアログの
高さの合計が jmax を越えるなら次の列に移る。
2. ウィンドウの幅が imax を越えるなら、先頭の列に戻る。
3. 1に戻る。(新しい段が足される。)
[imax < jmax の場合]
横に並べて行を足していき、ウィンドウの高さが h を越えたら
先頭の行に戻る。
†start⇔quit, pause⇔continue イベントは st=1 のコントロー
ルウィンドウのうち最初に宣言されたものに登録されます。
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
control_window B(imax,jmax,st);
int imax=0; int jmax=0; int st=0;
control_window B(XRS_ROOT,imax,jmax,0,0,-1,st); と同じ。
- ‘class control_window の public(公開)変数’
-
-
class window の public変数
-
int realtime; realtime=1(realtime=0) なら登録されるダイアログ
に対して realtime 表示(マウスイベント処理)が指
定される。
/ B.realtime=0;
/ int a; i_dialog p(C,a); #realtime表示でaをCに登録
/ p.title("A"); B.redraw();
- ‘class control_window の public関数’
-
-
class window の public関数
-
int i_max(); imax を返す。 / int i=B.i_max();
-
int j_max(); jmax を返す。 / int j=B.j_max();
-
void resize(int imax=0,int jmax=0);
ウィンドウをリサイズして redraw() を実行。
非負値は今のまま。 / B.resize(100,50);
-
void draw(); ウィンドウの描画。(仮想関数) / B.draw();
登録されている各 dialog の dialog::redraw()関数を実行する。
-
void redraw(); ウィンドウの再描画。(仮想関数) /B.redraw();
登録されているダイアログのリストが変更されていたら、各
dialog の位置を決め直して描画する。変わっていなかったら、
draw() を実行。
-
virtual void checkevent(); イベント処理(仮想関数)
realtime 表示指定の dialog の dialog::draw() を実行する。
Exposeイベントが発生していたら draw() を実行する。
ButtonPressイベントが発生していたら イベント処理指定の
dialog の dialog::checkevent() を実行する。
chev にマウスイベントの時はマウスボタンの番号、それ以外
は0をセットする。 / B.chekevent();
-
int number(); 登録されているダイアログの総数を返す。
/ int n=B.number();
-
dialog* event(int n); n 番目のダイアログへのポインタを返す。
/ dialog *p=B.element(2);
-
dialog* event(char *title); 登録されているダイアログのうちで
タイトルが title である最初のダイアログへのポ
インタを返す。 / dialog *p=B.element("T");
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ‘class control_window の protected 関数(非公開)’
-
class window の protected 関数
-
void add(dialog &p);
dialog p のポインタをリストに追加する。(仮想関数)
-
void remove(dialog *p);
pが登録されていたらリストから削除する。(仮想関数)
-
void startup(); 初期化処理(仮想関数)
start⇔quit dialog が登録されていたら、"start" を表示し
てマウスイベント待ち状態で停止し、マウスイベントがあっ
たら "quit" を表示する。
3.3.5.1 Control Window
class Control_Window は class control_window から派生したクラスです
。基本的な機能は control_windowと同じですが、<< 演算子を使って大きさ
や位置の指定、関数、double型変数、int型変数の登録が簡単にできます。
†#include <XRS/Control.h> が必要
†<XRS/Control.h>の中で <XRS/control.h>,<XRS/d_dialog.h>,<XRS/i_dialog.h>
が includeされる。
- ‘class Control_Window の宣言’
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
Control_Window A(W,imax,jmax,i,j,bw,st);
引数は control_window A(W,imax,jmax,i,j,bw,st); と同じ。
ただし、realtime=1 に初期設定する。
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
Control_Window B(imax,jmax,st);
int imax=0; int jmax=0; int st=0;
Control_Window B(XRS_ROOT,imax,jmax,0,0,-1,st); と同じ。
- ‘class Control_Window の public(公開)変数’
-
class control_window の public変数
- ‘class Control_Window の public関数’
-
class control_window の public関数
-
Control_Window&
geometry(int imax=0,int jmax=0,int i=-1,int j=-1)
ウィンドウのリサイズ(幅 imax、高さ jmax) と移動(x座標 i、
y座標 j)。i_max,j_max は非正値、i,jは負値なら現在値を変更
しない。返り値は自分自身へのポインターなので、<< を続けて
書くことができる 。
( control_window::resize(i_max,j_max) と
window::move(i,j) を実行する。) / B.geometry(100,200);
-
Control_Window& operator<<(char *name)
ダイアログのタイトルの設定。
-
Control_Window& operator<<(void (*f)(int))
代入された void (*f)(int)関数でf_dialog を作って登録し、
マウスの n 番目のボタンでウィンドウをクリックしたとき
f(n) が実行されるようにする。
/ void g(int n){ printf("%d\n",n); }
/ B<<g<<"G";
-
Control_Window& operator<<(double &s)
代入された double型変数 x で d_dialog を作って登録し、
realtime表示(realtime=1) または パラメータチューニング
(realtime=0) ができるようにする。
登録時の realtime の値で処理のし方を選べる。
/ double x; B<<x<<"X";
-
Control_Window& operator<<(int &s)
代入された int型変数 x で i_dialog を作って登録し、
realtime表示(realtime=1) または パラメータチューニング
(realtime=0) ができるようにする。
登録時の realtime の値で処理のし方を選べる。
/ int x; B<<x<<"X";
- ‘マニピュレーター’
-
-
PARAMETER(Control_Window &s);
realtime表示(realtime=1)⇔マウスイベント処理(realtime=0)の
切替え。
/ double x,y; B<<x<<PARAMETER<<y<<"X"<<Y";
/ この場合は x は reltime表示され、y はパラメータチュー
/ ニングできる。
3.3.5.2 Complex Control Window
class Complex_Control_Window は class control_window から派生したク
ラスです。class Control_Window の機能に加えて、Complex型変数を扱うた
めの << 演算子が備わっています。
※ C++ の <Complex.h> を使うと iostream ライブラリをリンクするため、
実行ファイルがかなり大きくなります。Complex型を使わない時は class Co
ntrol_Window のほうを使うことをお勧めします。
†#include <XRS/Complex_Control.h> が必要
†<XRS/Complex_Control.h>の中で <XRS/c_dialog.h>,<XRS/d_dialog.h>
<XRS/i_dialog.h>,<XRS/control.h> が includeされる。
- ‘class Complex_Control_Window の宣言’
-
親ウィンドウをWとしてウィンドウAを開く。[子ウィンドウを作る時必要]
Complex_Control_Window A(W,imax,jmax,i,j,bw,st);
引数は control_window A(W,imax,jmax,i,j,bw,st); と同じ。
ただし、realtime=1 に初期設定する。
-
親ウィンドウをXRS_ROOTとしてウィンドウBを開く。[普通の開き方]
Complex_Control_Window B(imax,jmax,st);
int imax=0; int jmax=0; int st=0;
Complex_Control_Window B(XRS_ROOT,imax,jmax,0,0,-1,st); と同じ。
- ‘class Complex_Control_Window の public(公開)変数’
-
class control_window の public変数
! Complex型を加えた以外は、class Control_Window と全く同じなので、
class Control_Window と同じ関数が class Complex_Control_Window
でも使えます。以下では class Control_Window にない機能のみを説
明します。
- ‘class Complex_Control_Window の public関数’
-
-
class control_window の public関数
-
Complex_Control_Window& operator<<(Complex &s)
代入された complex型変数 x で c_dialog を作って登録し、
realtime表示(realtime=1) または パラメータチューニング
(realtime=0) ができるようにする。
登録時の realtime の値で処理のし方を選べる。
/ Complex x; B<<x<<"X";
- ‘マニピュレーター’
-
3.4 ダイアログ
XRS の class dialog は 基本的な使い方をしている限りプログラムにはあらわれませんが、関数や変数などに対するイベント処理を受け持つ重要な裏方です。
( Simple_Window, Control_Window などの大文字から始まるウィンドウでは 通常 dialog の宣言は自動的に行なわれるので、プログラム中であらわに宣言する必要はありません。)
class dialog は宣言時に引数で指定されたウィンドウに自動的に登録され、消滅時に登録が削除されます。登録されたウィンドウ上では1つの担当区域を持ち、ウィンドウからの指示に応じてマウスイベントの処理やパラメータの表示をします。
†simple_window ではウィンドウの座標 (x,y) がクリックされると、登録されている dialog の dialog::checkevent(x,y) 関数が実行され、その後の処理は dialog が引き継ぎます。
†control_window の場合は realtime 表示が指定されている dialog に対してはイベントチェックのたびに dialog の dialog::draw() 関数が、マウスイベント処理が指定されている dialog に対しては dialog の dialog::checkevent(x,y) 関数が実行され、その後の処理を引き継ぎます。
class dialog は 関数用の class f_dialog、double型,int型,complex型変数用の class d_dialog, class i_dialog, class c_dialog に派生しています。
3.4.1 dialog
class dialog は関数や変数などに対するイベント処理を受け持つクラスの基底クラスです。すべてのダイアログは class dialog を土台にして作られています。
†#include <XRS/dialog.h> が必要
†<XRS/dialog.h>の中で <XRS/window.h> が includeされる。
- ‘class dialog の宣言’
-
dialog Aを宣言して window W に登録する。
dialog A(W);
window &W; 登録するウィンドウ
幅 w、高さ h、位置 (i0,j0) は0、タイトル name は NULL に初
期化される。ウィンドウ W でのダイアログの担当区域は左上隅
(i0,j0)、右下隅(i0+w,j0+h) の矩形領域になります。
†コンストラクタの中で W の非公開メンバー関数 W.add(*this) が
実行される。(消滅時にはデストラクタで W.remove(this) が実行
され登録が削除される。)
- ‘class dialog の public(公開)関数’
-
int chev; checkevent()で値がセットされる。/B.chev
- ‘class dialog の public(公開)関数’
-
-
int i(); x座標 i0 を返す。 / int i0=A.i();
-
int j(); y座標 j0 を返す。 / int j0=A.j();
-
void move(int i=-1,int j=-1); / A.move(100,20);
位置 (i0,j0) の変更。負値なら変わらない。
-
int width(); 幅 w を返す。 / int w=A.width();
-
int height(); 高さ h を返す。 / int h=A.height();
-
char* title(); タイトルを返す。 / char *s=title();
-
void title(char *name); タイトルをnameに変更 /A.title("wanya");
仮想関数(派生先で再定義されている可能性がある)
-
virtual void resize(int w=0,int h=0,int s=-1);
リサイズ。引数は(幅、高さ、形状のタイプ指定)で省略した時
または負の値の時)は変更なし。 / A.resize(100,50);
-
virtual void draw(){} ダイアログの描画 /A.draw();
-
virtual void redraw(){} ダイアログの再描画 /A.redraw();
-
virtual void checkevent(); イベント処理
マウスクリック位置が担当区域内にあれば、chev=1
なければ chev=0 にする。
3.4.2 f_dialog
class f_dialog は class dialog の派生クラスです。宣言時に引数で与えられたウィンドウに登録され、マウスクリックに対して void (*)(int) 型の関数を実行するイベント処理を担当します。
| ダイアログは表示される( redraw() )と
┌─────┐
│1タイトル│のように描かれます。(幅 width,高さheight)
└─────┘
|
†simple_window では redraw() は実行されません。
1欄がマウスでクリックされるとたマウスボタンの番号 n=W.ev.xbutton.button を調べ、宣言時に引数で渡された関数 F(n)を実行し、chev=1にセットします。欄外がセットされた時は chev=0 になります。
†#include <XRS/f_dialog.h> が必要
†<XRS/f_dialog.h>の中で <XRS/dialog.h> が includeされる。
- ‘class f_dialog の宣言’
-
関数 void F(int) を処理する f_dialog A を宣言して window W に
登録する。
f_dialog A(W,F);
window &W; 登録するウィンドウ
void (*F)(int)=NULL; マウスクリックで実行される関数
ダイアログの幅(width)、高さ(height)、タイトルの文字数の最大
値(string)、フォント(font)、最初の文字の位置(xoffset,
yoffset)にデフォルト値がセットされる。W.black の色を持つ
グラフィックコンテキスト gc が用意される。
- ‘class f_dialog の public(公開)変数’
-
class dialog の public変数
-
GC gc; ダイアログの表示に使うグラフィックコンテキスト
- ‘class f_dialog の public関数’
-
class dialog の public関数
-
int string(); タイトルの文字数の最大値(string)を返す。
-
void string(int n); タイトルの文字数の最大値(string)の変更。
/A.string(8); int n=A.string();
-
int xoffset(); 文字の書き始め位置の x 座標(xoffset)を返す。
-
int yoffset(); 文字の書き始め位置の y 座標(yoffset)を返す。
-
int offset(int xoffset,int yoffset=-1); xoffset,yoffsetの変更。
/A.offset(10,2); int n=A.xoffset(); int n=A.yoffset();
-
void redraw(); ダイアログの再描画。(仮想関数) / A.redraw();
ダイアログの担当区域に枠とタイトルを書く。
-
void checkevent(); イベント処理。(仮想関数)
3.4.3 d_dialog
class d_dialog は class dialog の派生クラスです。宣言時に引数で与えられたウィンドウに登録され、double 型変数の表示/マウスクリックによるパラメータチューニングを実行するイベント処理を担当します。
| 表示は type=0 type=1
┌─────┐
│1タイトル│ ┌─────┬─────┐
├─────┤ │1タイトル│2変数の値│
│2変数の値│ └─────┴─────┘
└─────┘
|
のどちらかを指定できます。(1,2欄はそれぞれ幅 width,高さ height)
パラメータチューニングの場合、マウスクリックされるとクリックされたマウスの位置(1欄か2欄か)とボタン番号 n=W.ev.xbutton.button を調べ、宣言時に引数で渡された double 型変数 x の値 または刻み幅step を以下のように変更します。また、欄の番号を chev にセットします。(欄外がクリックされたときは0)
| 1欄 で n==1 → x+=step;
n==2 → x+=0.1*step;
n==3 → step*=10;
2欄 で n==1 → x-=step;
n==2 → x-=0.1*step;
n==3 → step*=0.1;
|
†#include <XRS/d_dialog.h> が必要
†<XRS/d_dialog.h>の中で <XRS/dialog.h> が includeされる。
- ‘class d_dialog の宣言’
-
double型変数 x を処理する f_dialog A を宣言して window W に登録
する。
d_dialog A(W,x);
window &W; 登録するウィンドウ
double x; double 型変数
ダイアログの形(shape)、幅(width)、高さ(height)、タイトルの
文字数の最大値(string)、フォント(font)、最初の文字の位置
(xoffset,yoffset)、double型変数用の printf の表示フォーマッ
ト(format)、パラメータチューニングの刻みの初期値(step)、桁
表示に使われる色(color)にデフォルト値がセットされる。
W.black の色を持つグラフィックコンテキスト gc と color の
色 の digit_gc が用意される。
- ‘class d_dialog の public(公開)変数’
-
class dialog の public変数
-
double step; メータチューニングの刻み幅
-
GC gc; ダイアログの表示に使うグラフィックコンテキスト
-
GC digit_gc; パラメータチューニングの桁表示に使うグラフィック
コンテキスト。(フォントは gc と同じなほうががよい。)
- ‘class d_dialog の public関数’
-
class dialog の public関数
-
int string(); タイトルの文字数の最大値(string)を返す。
-
void string(int n); タイトルの文字数の最大値(string)の変更。
/A.string(8); int n=A.string();
-
int xoffset(); 文字の書き始め位置の x 座標(xoffset)を返す。
-
int yoffset(); 文字の書き始め位置の y 座標(yoffset)を返す。
-
int offset(int xoffset,int yoffset=-1); xoffset,yoffsetの変更。
/A.offset(10,2); int n=A.xoffset(); int n=A.yoffset();
-
void resize(int width,int height=0,int shape=-1); リサイズ。
引数は(欄の幅、欄の高さ、形の指定)で非正値(shape は負
値)なら変更しない。 / A.resize(100,50);
-
void draw(); パラメータの表示。(仮想関数) / A.draw();
†realtime 表示で使われる。
-
void redraw(); ダイアログの再描画。(仮想関数) / A.redraw();
ダイアログの担当区域に枠とタイトル、変数の値を書く。
-
void checkevent(); イベント処理。(仮想関数)
-
char* format(); 変数表示用のprintf フォーマットを返す。
/char *s=A.format();
-
void format(char *s); printf フォーマットを変更する。
変数表示欄はクリアーされる。 / A.format("%7.7f");
3.4.4 i_dialog
class i_dialog は class dialog の派生クラスです。宣言時に引数で与えられたウィンドウに登録され、int 型変数の表示/マウスクリックによるパラメータチューニングを実行するイベント処理を担当します。
| 表示は type=0 type=1
┌─────┐
│1タイトル│ ┌─────┬─────┐
├─────┤ │1タイトル│2変数の値│
│2変数の値│ └─────┴─────┘
└─────┘
|
のどちらかを指定できます。(1,2欄はそれぞれ幅 width,高さ height)
パラメータチューニングの場合、マウスクリックされるとクリックされたマウスの位置(1欄か2欄か)とボタン番号 n=W.ev.xbutton.button を調べ、宣言時に引数で渡された int 型変数 x の値 または 刻み幅step を以下のように変更します。また、欄の番号を chev にセットします。(欄外がクリックされたときは0)
| 1欄で n==1 → x+=10*step;
n==2 → x+=step;
n==3 → step*=10;
2欄で n==1 → x-=10*step;
n==2 → x-=step;
n==3 → if(step>=10) step/=10;
|
†#include <XRS/i_dialog.h> が必要
†<XRS/i_dialog.h>の中で <XRS/dialog.h> が includeされる。
- ‘class i_dialog の宣言’
-
int型変数 x を処理する i_dialog A を宣言して window W に登録
する。
i_dialog A(W,x);
window &W; 登録するウィンドウ
int x; int 型変数
ダイアログの形(shape)、幅(width)、高さ(height)、タイトルの
文字数の最大値(string)、フォント(font)、最初の文字の位置
(xoffset, yoffset)、int型変数用の printf の表示フォーマット
(format)、パラメータチューニングの刻みの初期値(step)、桁表
示に使われる色(color)にデフォルト値がセットされる。W.black
の色を持つグラフィックコンテキスト gc と color の色の
digit_gc が 用意される。
- ‘class i_dialog の public(公開)変数’
-
class dialog の public変数
-
int step; メータチューニングの刻み幅
-
GC gc; ダイアログの表示に使うグラフィックコンテキスト
-
GC digit_gc; パラメータチューニングの桁表示に使うグラフィック
コンテキスト。(フォントは gc と同じなほうががよい。)
- ‘class i_dialog の public関数’
-
class dialog の public関数
-
int string(); タイトルの文字数の最大値(string)を返す。
-
void string(int n); タイトルの文字数の最大値(string)の変更。
/A.string(8); int n=A.string();
-
int xoffset(); 文字の書き始め位置の x 座標(xoffset)を返す。
-
int yoffset(); 文字の書き始め位置の y 座標(yoffset)を返す。
-
int offset(int xoffset,int yoffset=-1); xoffset,yoffsetの変更。
/A.offset(10,2); int n=A.xoffset(); int n=A.yoffset();
-
void resize(int width,int height=0,int shape=-1); リサイズ。
引数は(欄の幅、欄の高さ、形の指定)で非正値(shape は負
値)なら変更しない。 / A.resize(100,50);
-
void draw(); パラメータの表示。(仮想関数) / A.draw();
†realtime 表示で使われる。
-
void redraw(); ダイアログの再描画。(仮想関数) / A.redraw();
ダイアログの担当区域に枠とタイトル、変数の値を書く。
-
void checkevent(); イベント処理。(仮想関数)
-
char* format(); 変数表示用のprintf フォーマットを返す。
/char *s=A.format();
-
void format(char *s); printf フォーマットを変更する。
変数表示欄はクリアーされる。 / A.format("%7.7f");
3.4.5 c_dialog
class c_dialog は class dialog の派生クラスです。宣言時に引数で与えられたウィンドウに登録され、complex 型変数の表示/マウスクリックによるパラメータチューニングを実行するイベント処理を担当します。
変数表示は(実部、虚部)または極座標の(半径、角度)が指定できます。
†極座標表示の場合の角度は π = M_PI (see <math.h>) で割った値が表示されます。
| 表示は type=0 type=1
┌─────┐ ┌──┬──┐
│1 2 │ │1 │3 │
├──┬──┤ │ ├──┤
│3 │4 │ │2 │4 │
└──┴──┘ └──┴──┘
|
のどちらかで 1、2欄の中央にタイトル、3欄に実部(半径)、4欄に虚部((角度)が表示されます。(1,2,3,4欄はそれぞれ幅 width,高さ height)
パラメータチューニングの場合、マウスクリックされるとクリックされたマウスの位置(1,2,3,4欄)とボタン番号 n=W.ev.xbutton.button を調べ、宣言時に引数で渡された complex 型変数 x の値 または刻み幅step を以下のように変更します。また、欄の番号を chev にセットします。(欄外がクリックされたときは0)
| <実部/虚部表示の場合> (polar_cordinate==0)
1欄 n==1 → f.re+=step.re;
n==2 → f.re+=step.re*0.1;
n==3 → step.re*=10.0;
2欄 n==1 → f.im+=step.im;
n==2 → f.im+=step.im*0.1;
n==3 → step.im*=10.0;
3欄 n==1 → f.re-=step.re;
n==2 → f.re-=step.re*0.1;
n==3 → step.re*=0.1;
4欄 n==1 → f.im-=step.im;
n==2 → f.im-=step.im*0.1;
n==3 → step.im*=0.1;
<極座標表示の場合> (polar_cordinate!=0)
1欄 n==1 → f=polar(abs(f)+step.re ,arg(f));
n==2 → f=polar(abs(f)+0.1*step.re,arg(f));
n==3 → step.re*=10.0;
2欄 n==1 → f=polar(abs(f),arg(f)+M_PI*step.im );
n==2 → f=polar(abs(f),arg(f)+0.1*M_PI*step.im);
n==3 → step.im*=10.0;
3欄 n==1 → f=polar(abs(f)-step.re ,arg(f));
n==2 → f=polar(abs(f)-0.1*step.re,arg(f));
n==3 → step.re*=0.1;
4欄 n==1 → f=polar(abs(f),arg(f)-M_PI*step.im );
n==2 → f=polar(abs(f),arg(f)-0.1*M_PI*step.im);
n==3 → step.im*=0.1;
|
†#include <XRS/c_dialog.h> が必要
†<XRS/c_dialog.h>の中で <XRS/dialog.h> が includeされる。
- ‘class c_dialog の宣言’
-
complex型変数 x を処理する c_dialog A を宣言して window W に登録
する。
c_dialog A(W,x);
window &W; 登録するウィンドウ
complex x; complex 型変数
ダイアログの形(shape)、幅(width)、高さ(height)、タイトルの
文字数の最大値(string)、フォント(font)、最初の文字の位置
(xoffset,yoffset)、printf の double型用のフォーマット
(format)、パラメータチューニングの刻みの初期値(real_step,
imarginary_step)、桁表示に使われる色(color)にデフォルト値が
セットされる。W.black の色を持つグラフィックコンテキスト gc
と color の色の digit_gc が用意される。
- ‘class c_dialog の public(公開)変数’
-
class dialog の public変数
-
int string(); タイトルの文字数の最大値(string)を返す。
-
void string(int n); タイトルの文字数の最大値(string)の変更。
/A.string(8); int n=A.string();
-
int xoffset(); 文字の書き始め位置の x 座標(xoffset)を返す。
-
int yoffset(); 文字の書き始め位置の y 座標(yoffset)を返す。
-
int offset(int xoffset,int yoffset=-1); xoffset,yoffsetの変更。
/A.offset(10,2); int n=A.xoffset(); int n=A.yoffset();
-
void resize(int width,int height=0,int shape=-1); リサイズ。
引数は(欄の幅、欄の高さ、形の指定)で非正値(shape は負
値)なら変更しない。 / A.resize(100,50);
-
int polar_cordinate; polar_cordinate!=0 なら極座標表示。
-
GC gc; ダイアログの表示に使うグラフィックコンテキスト
-
GC digit_gc; パラメータチューニングの桁表示に使うグラフィック
コンテキスト。(フォントは gc と同じなほうががよい。)
-
complex step; メータチューニングの刻み幅
(極座標の時は、実部が半径、虚部が角度の刻み幅になる。)
- ‘class c_dialog の public関数’
-
class dialog の public関数
-
void draw(); パラメータの表示。(仮想関数) / A.draw();
polar_cordinate==0 なら実部/虚部表示、
polar_cordinate!=0なら極座標表示される。
†realtime 表示で使われる。
-
void redraw(); ダイアログの再描画。(仮想関数) / A.redraw();
ダイアログの担当区域に枠とタイトル、変数の値を書く。
-
void checkevent(); イベント処理。(仮想関数)
-
char* format(); 変数表示用のprintf フォーマットを返す。
/char *s=A.format();
-
void format(char *s); printf フォーマットを変更する。
変数表示欄はクリアーされる。 / A.format("%7.7f");
3.5 その他の道具
- ‘color.h’
XDrawPointなどの XWindow のコマンドを使う場合に必要になるグラフ
ィックコンテキストやカラーピクセルを作る簡易関数が入っています。
以下のヘッダファイルは XRS とは独立に単独で使うこともできます。
- ‘XResource.h’
.Xdefaults ファイルなどに書かれたXリソースデータベースからデータを
取り出すための簡易関数です。
- ‘List.h’
線形双方向リストとその反復子のテンプレートクラスです。これを使えば
任意の型を要素とする線形双方向リストを作ることができます。
- ‘Array.h’
動的配列を用意/削除するテンプレート関数です。これを使うと、任意の
型に対する多次元動的配列を作ることができます。
- ‘Exec.h’
コマンドを子プロセスで実行するためのクラスです。
- ‘Socket.h’
ソッケトを開くクラスです。
†テンプレートを使用した List.h、Array.h などのクラス/関数のコンパイ
ルの仕方はまだ統一されておらず、コンパイラや OS によって違うことがあ
るので注意して下さい。
3.5.1 color.h
カラーピクセルやグラフィックコンテキストを作るための簡易関数のセットです。色名、HSV値、リソースファイルなどから対応するカラーピクセル、グラフィックコンテキストを簡単に作ることができます。
- †
ワークステーションのディスプレイの性能上、同時に表示可能な色(カラーピクセル)は最大で256個です。たくさんの色を使い過ぎると表示される色がおかしくなるので注意して下さい。
- †
色名は XlibR5 の形式に従います。つまり、"red"のような英語名、"#ff00dd" のような RGB値名、"TekHVC:0/50/90" のような HVC値名のいずれも使えます。(詳しくは、XWindow のマニュアルを見て下さい。)
- †
カラーリソースファイルは色名を並べて作ります。
| <書き方>
各行には1つの色名を書く。
空行は読み飛ばされ、!で始まる行はコメントとみなされる。
<例>
—— ファイル "color_file" ———
! color resource sample
red
blue
green
————————————–
†リソースファイルは既成のコマンド xcoloredit を使うと簡単に作る
ことができます。(See section Graphic_Window 応用編.)
|
- †
XRSではHSV値からRGB値への変換を xcoloredit コマンドのソースファイルから取ってきた関数を使って行なっています。xcoloredit コマンドで使われている RGB値 ⇔ HSV値 変換や色の合成をする関数のセットは <XRS/xcoloredit_color.h> をインクルードすると使うことができます。(このファイルは xcoloredit のソースファイルの一部です。)
| †#include <XRS/color.h> が必要
†<XRS/color.h>の中で <XRS/window.h> がincludeされる。
- ‘カラーピクセル取得のための関数’
unsigned long color_pixel(W,h,s,v);
window &W; ウィンドウ
double h; 色相(Hue) h<0 || h>1 ⇒ h-=floor(h)
double s=1; 飽和度(Saturation) s<0 ⇒ s=0, s>1 ⇒ s=1
double v=1; 明度(Value) v<0 ⇒ v=0, v>1 ⇒ v=1
ディスプレイID W.disp() とカラーマップ W.cm からHSV値(h,s,v)
の色のカラーピクセルを用意して返す。
unsigned long color_pixel(h,s,v);
上の関数の省略形。color_pixel(XRS_ROOT,h,s,v) と同じ。
/ unsigned long c=color_pixel(0.5);
unsigned long color_pixel(W,name);
window &W; ウィンドウ
const char *name; 色名
ディスプレイID W.disp() とカラーマップ W.cm から name 色
のカラーピクセルを用意して返す。
unsigned long color_pixel(name);
上の関数の省略形。color_pixel(XRS_ROOT,name) と同じ。
/ unsigned long c=color_pixel("green");
int color_pixel(W,color,filename);
window &W; ウィンドウ
unsigned long *&color; カラーピクセルが入る配列へのポインタ
const char *filename=NULL; カラーリソースファイルの名前
ファイル filename の色名に従ってカラーピクセルの配列をとる。
返り値は確保された色の数(配列の要素数)。
filename=NULL ⇒ デフォルトのファイル
int color_pixel(c,filename);
上の関数の省略形。color_pixel(XRS_ROOT,c,filename) と同じ。
/ unsigned long *c; color_pixel(c,"color_file");
unsigned long* colordisk(W,nr,np);
window &W; ウィンドウ
int nr; 半径方向(飽和度)の色数
int np; 角度方向(色相)の色数
色相(角度方向)と飽和度(半径方向)が連続的に変わるディス
ク状のカラーピクセル配列を作って返す。
unsigned long* colordisk(nr,np);
上の関数の省略形。colordisk(XRS_ROOT,nr,np) と同じ。
/ Graphic_Window W(100,100);
/ W<<COLOR(colordisk(6,8),6*8);
int diskcolor(double,double,int,int);
double r; 飽和度(半径、0=<r<1、r=0 は白)
double phi; 色相(角度、2π周期)
int nr; 半径方向(飽和度)の色数
inr np; 角度方向(色相)の色数
colordisk 関数で用意した配列で (r,phi) に対応する色の番号
を返す。
※ phi/=2π; if( phi>=1 || phi<0 ) phi-=floor(phi);
return (int)(nj*((int)(r*ni)+phi)); をしてるだけ。
/ W.point(diskcolor(0.8,0.5,6,8),50,50);
- ‘グラフィックコンテキスト取得のための関数’
GC graphic_context(W,color,line_width,line_style,font);
window &W; ウィンドウ
unsigned long color; 色(カラーピクセル)
unsigned int line_width=0; 線幅
int line_style=LineSolid; 線のスタイル
const char* font=NULL; フォント
色 color, 線幅 lw, ラインスタイル ls, フォント font の
グラフィックコンテキストを作って返す。background色は
W.white になります。
font=NULL ⇒ デフォルト値
GC graphic_context(color,line_width,line_style,font);
上の関数の省略形。graphic_context(XRS_ROOT,color,line_width,
line_style,font); と同じ。
/ GC gc=color_pixel(color_pixel(0.5),0,LineOnOffDash);
GC graphic_context(W,name,line_width,line_style,font);
window &W; ウィンドウ
char *name; 色名
unsigned int line_width=0; 線幅
int line_style=LineSolid; 線のスタイル
const char* font=NULL; フォント
色 color, 線幅 lw, ラインスタイル ls, フォント font の
グラフィックコンテキストを作って返す。background色は
W.white になります。
font=NULL ⇒ デフォルト値
GC graphic_context(name,line_width,line_style,font);
上の関数の省略形。graphic_context(XRS_ROOT,name,line_width,
line_style,font); と同じ。
/ GC gc=graphic_context("red");
int graphic_context(W,gc,filename);
window &W; ウィンドウ
GC *&gc; グラフィックコンテキストが入る配列へのポインタ
const char *filename=NULL; カラーリソースファイルの名前
ファイル filename の色名に従ってグラフィックコンテキストの
配列をとる。返り値は確保された色の数(配列の要素数)。
line_width=0,line_style=LineSolid,font=デフォルト値,
background=W.white になる。
filename=NULL ⇒ デフォルトのファイル
int graphic_context(gc,filename); 上の関数の省略形。
graphic_context(XRS_ROOT,gc,filename) と同じ。
/ GC *gc; graphic_context(gc,"color_file");
|
3.5.2 XResource.h
リソースデータベースからデータを取り出すための簡易関数のセットです。
mergeDatabases関数でXrmDatabase型変数にデータベースを読み込ませてから、extractOpt でデータを取り出して下さい。(Xリソースの書き方については XWindow のマニュアルを御覧下さい。)
データベースの取得(merge)は以下の順番で行なわれます。
-
xrdb コマンドで設定されているデータベースを読む。もしそれが空ならホームディレクトリの .Xdefaults を読み込む。
-
環境変数 XENVIRONMENTで指定されたファイルを読み込む。それが設定されていない場合、ホームディレクトリに.Xdefaults-hostname があればを読み込む。
-
mergeDatabases関数の引数で指定したファイルがあれば読み込む。
- ※
通常のアプリケーションは app-defaultsディレクトリのファイルとコマンドラインオプションも読み込むのが普通ですが、XRS は数値シミュレーションが主な目的なのでバグや誤動作を持ち込みやすいこれらのデータベースは使わないようにしています。
| †#include <XRS/XResource.h> が必要
- ‘定義されている関数’
void mergeDatabases(d,DB,filename);
Display *d; ディスプレイID
XrmDatabase &DB; 確保されるデータベース
char *filename; リソースファイル名
上述の手順にしたがってデータベース DB を作る。
int extractOpt(DB,name,class,opt);
XrmDatabase &DB; データベース
const char *name; インスタンス名
const char *class; クラス名
char *opt; データを書き込む文字列へのポインタ
DB からインスタンス名 name、クラス名 class と一致する最も
優先順位の高いデータを取り出して opt に代入する。
もし一致するものがあれば 1を返し、なければ0を返す。
/ —– ファイル "testrc" の中身 ——
/ miya: Takashi Ichinomiya
/ ————————————-
/ #include <stdio.h>
/ #include <XRS/XResource.h>
/ using namespace XRS;
/ int main(){
/ Display *d=XOpenDisplay(NULL);
/ XrmDatabase DB;
/ mergeDatabases(d,DB,"testrc");
/ char opt[126];
/ if(extractOpt(DB,"miya","Miya",opt)) printf("%s\n",opt);
/ XCloseDisplay(d);
/ exit(0);
/ }
|
3.5.3 List.h
線形双方向リストとその反復子のテンプレートクラスです。これを使えば任意の型を要素とする線形双方向リストを作ることができます。
- †
List class の各関数の引数で要素数に負の整数を与えると末尾からの順番の指定になります。関数の内部で順番の検索に for ループを使っているので、あまり高速ではありません。大きなサイズのリストで []演算子を使うときは注意して下さい。
- †
反復子というのは List型に対して for ループを書けるようにするための補助クラスです。inline 展開される(マクロと同様に直接展開される)ので高速で動きます。
| †#include <XRS/List.h> が必要
- ‘テンプレートクラス List’
List<T> a; T型変数を要素とするリストaの宣言 / List<double> a;
T& operator[](int n); n番目の要素。 / double a[3];
int number(); 要素数を返す。 / int n=a.number();
void splice(int n,T x); リストのn番目にxを追加 /a.splice(3,4.0);
T splice(int n); n番目の要素を取り除いて返す
/double x=a.splice(1);
以下の関数は上のsplice関数の簡易版です。
T pop(); 最後の要素を取り去って返す。/double x=a.pop();
void push(T x); 末尾に x を加える。 /a.push(2.4);
void unshift(T x); 先頭に x を加える。 /a.unshift(3.5);
T shift(); 先頭の要素を取り去って返す。/double x=a.shift();
- ‘反復子クラス ListIter’
ListIter i(a,n); または ListIter i=a;
const List<T> &a; T型リスト
int n=0; 要素の番号
リスト a を与えて反復子を作る。
現在の要素(i.curr())がa[n]になる。
int empty(); 現在の要素が空であれば1、空でなければ0を返す。
void next(); 次の要素に移動。
void prev(); 前の要素に移動。
T& curr(); 現在の要素。
/ for(ListIter i=a; !i.empty(); i.next()) forループ
/ printf("%f\n",i.curr()); 現在の要素
|
3.5.4 Array.h
動的配列を用意/削除するテンプレート関数です。これを使うと、任意の型に対する多次元動的配列を作ることができます。
- ※
いったん作ってしまえば、普通の配列と同じように [] を使って a[100][20]=21.5; などと使えます。
|
†#include <XRS/Array.h> が必要
- ‘定義されている関数’
template <class T> void array(T **&M,int imax,int jmax);
imax x jmax の T 型2次元動的配列を M に確保する。
※ if(i && j){ M=new T* [i]; add_dimension(M,i,j);} と同じ。
/ double **x;
/ array(x,100,50); double型の2次元配列をとる。
template <class T> void delete_array(T **&M);
T 型2次元動的配列 M のメモリーを解放する。
※ delete_dimension(M); delete [] M; M=NULL; と同じ。
/ delete_array(x);
template <class T> void add_dimension(T **M,int imax,int jmax);
全要素数 imax、先頭のアドレス M の配列に要素数 jmax の新しい
次元を加えて行列を作る。
/ 10x20x30x40 の double型 の4次元配列を取る例。
/ double ****x;
/ array(x,10,20);
/ add_dimension(x[0],10*20,30);
/ add_dimension(x[0][0],10*20*30,40);
template <class T> delete_dimension(T **M);
M[0] のメモリーの解放
※ delete [] M[0]; M[0]=NULL; をしているだけ。
/ 4次元配列のメモリーの解放。
/ delete_dimension(x[0][0])
/ delete_dimension(x[0]);
/ delete_array(x);
|
3.5.5 Exec.h
class Exec は与えられたコマンドを子プロセスで実行し、その標準入力との間にパイプを作ります。標準出力や標準エラー出力をファイルに書き出すこともできます。
| †#include <XRS/Exec.h> が必要
- ‘class Exec の宣言’
Exec A(path,command,filename1,filename2);
const char *path; コマンドのパス名
const char *command; コマンド(スペースを含んでもいい)
const char * filename1=NULL; stdout 出力を書き込むファイル名
const char * filename2=NULL; stderr 出力を書き込むファイル名
パス path にあるコマンド command を実行し、その標準入力との間
にパイプを作る。ファイル名が与えられたら、stdout や stderr を
そのファイルにリダイレクトする。
/ Exec A("bin/cat","cat","kuzu");
- ‘class Exec の public 関数’
operator FILE*(); / fprintf(A,"test\n");
作ったパイプに出力するファイル構造体への型変換。
template<class T> Exec& operator<<(const T& s);
Exec& operator<<(std::ostream& (*pf)(std::ostream &));
変数またはマニピュレーターをパイプに出力しバッファリングする。
/ A<<"test"<<endl;
※ver.3.3.0から改行を自動的につけるのをやめました。
|
3.5.6 Socket.h
ソケットを作って異なるプロセス間でデータをやりとりするためのクラスです。class Socket はサーバ側、class ClientSocket はクライアント側のソッケットを作ります。
| †#include <XRS/Socket.h> が必要
- ‘class Socket の宣言’
Socket A(name);
const char *name; ソケットの名前(同名のファイルができる。)
name という名前のソッケト(AF_UNIX,SOCK_STREAM)を作り、bind,listen
システムコールをする。ただし、同名のファイルでソケットでもパイプで
もないものが既に存在していればソケットを開かずにエラー終了する。
- ‘class Socket の public 関数’
const char *title(); name を返す。 / char *s=A.title();
operator int(); ディスクリプタへの型変換。
int open(); accept システムコールを実行し、クライアントからの
接続要求を待つ。接続後ディスクリプタを返す。
/ FILE *fp=fdopen(A.open(),"w");
void close(); accept で作られたディスクリプタを閉じる。
/ A.close();
- ‘class ClientSocket の宣言’
ClientSocket B(name);
const char *name; ソケットの名前
name という名前のソケットと接続し、ディスクリプタを得る。
- ‘class ClientSocket の public 関数’
-
|
3.5.7 DataSocket.h
class DataSocket は class Socket の派生クラスで、ソケットから標準出力へデータを書き出す XRS ライブラリの専用コマンド datasocket にデータを送るためのクラスです。
| †#include <XRS/DataSocket.h> が必要
†内部で <XRS/Socket.h> をインクルードしている。
- ‘class DataSocket の宣言’
DataSocket A(name);
const char *name; ソケットの名前
name という名前のソッケトを作る。
- ‘class DataSocket の public 関数’
FILE *open(); クライアント "datasocket" からの接続要求を待つ。
接続後、そのソケットへの write only のファイル構造体
を返す。 / A.open();
operator FILE*(); ファイルディスクリプタへの型変換。
/ fprintf(A,"test\n");
template<class T> DataSocket& operator<<(const T& s);
DataSocket& operator<<(std::ostream& (*pf)(std::ostream &));
変数またはマニピュレーターをパイプに出力しバッファリングする。
/ A<<"test"<<endl;
※ver.3.3.0から改行を自動的につけるのをやめました。
void close(); データ終了のコントロールコード ’\x44’ を送った後、
バッファリングしてからディスクリプタを閉じる。
/ A.close();
- ‘コマンド datasocket’
UNIX のコマンドラインで datasocket <socketname> とすると、そのソ
ケットからデータを受けとり、標準出力に出します。コントロールコー
ド ’\x44’ を受信すると、’\n’ を出して終了します。
※ 先に、サーバ ( class DataSocket を持つプログラム)を走らせてから
実行しないと、接続するソケットを見つけられずにエラーになります。
|
3.6 デフォルト値とカスタマイズ
関数やクラスの仕様の中でところどころに現れる"デフォルト値"はインストール時の XRS/define.h の値で決まっていますが、各自が Xリソースを使って変更することができます。
|
※
ただし、リソースファイルのデフォルト名 XRS_RESOURCE_FILE だけは変更
できません。(インストール時にdefine.h を変更していない限り XRS_RES
OURCE_FILE = ".xrsrc" です。)
※
Xリソースの書き方は XWindow のマニュアルに載っています。
※
リソースデータベースのでき方と読み込むファイルについては
See section XResource.h. を御覧下さい。
|
3.6.1 Xリソース一覧
- ※
インスタンス名(最も優先順位が高い書き方)はクラス名をすべて小文字に変えたものです。
- ※
<XRS/define.h> 中の対応する変数のデフォルトの定義はクラス名とほぼ同名(すべて大文字)で #define を使って行なわれています。
- ※
下で変数の型 (s) は文字列をあらわします。(プログラムでないので、"で囲む必要はありません。)
| クラス名: 意味(変数の型)
♪
<XRS/color.h> (color_pixel,graphic_context関数)
Xrs.Font: フォント名(s)
Xrs.Color_Resource: カラーリソースファイルの名前(s)
♪
<XRS/window.h> 関係
Xrs.Window.Boder_Width: ウィンドウの境界線の幅(int)
♪
<XRS/control.h> (コントロールウィンドウ)
Xrs.Window.Control.Title: タイトル(s)
Xrs.Window.Control.Width: 幅(int)
Xrs.Window.Control.Height: 高さ(int)
♪
<XRS/graphic.h> (グラフィックウィンドウ)
Xrs.Window.Graphic.Meshsize: 格子サイズ(int)
Xrs.Window.Graphic.Maxcolor: 色番号が大き過ぎた時の色の名前(s)
Xrs.Window.Graphic.Mincolor: 色番号が小さ過ぎた時の色の名前(s)
Xrs.Window.Graphic.Color_Type: 色のタイプ
(monotone/phasetone/color_resourceのいずれか)
Xrs.Window.Graphic.Color_Number: 色数
Xrs.Window.Graphic.Color_H: 色相(double)
†monotone/phasetone で使われる
Xrs.Window.Graphic.Color_Resource: カラーリソースファイルの名前(s)
♪
<XRS/plane.h> (プレーンウィンドウ)
Xrs.Window.Plane.Meshsize: 格子サイズ(int)
Xrs.Window.Plane.Maxcolor: 色番号が大き過ぎた時の色の名前(s)
Xrs.Window.Plane.Mincolor: 色番号が小さ過ぎた時の色の名前(s)
Xrs.Window.Plane.Color_Type: 色のタイプ
(monotone/phasetone/color_resourceのいずれか)
Xrs.Window.Plane.Color_Number: 色数
Xrs.Window.Plane.Color_H: 色相(double)
†monotone/phasetone で使われる
Xrs.Window.Plane.Color_Resource: カラーリソースファイルの名前(s)
♪
<XRS/f_dialog.h> (関数用ダイアログ)
Xrs.Dialog.Function.String: タイトルの最大文字数(int)
Xrs.Dialog.Function.Xoffset: 文字の書き始めの位置のx座標(int)
Xrs.Dialog.Function.Yoffset: 文字の書き始めの位置のy座標(int)
Xrs.Dialog.Function.Width: 欄の幅(int)
Xrs.Dialog.Function.Height: 欄の高さ(int)
Xrs.Dialog.Function.Font: フォント(s)
♪
<XRS/d_dialog.h> (double変数用ダイアログ)
Xrs.Dialog.Double.String: タイトルの最大文字数(int)
Xrs.Dialog.Double.Xoffset: 文字の書き始めの位置のx座標(int)
Xrs.Dialog.Double.Yoffset: 文字の書き始めの位置のy座標(int)
Xrs.Dialog.Double.Width: 欄の幅(int)
Xrs.Dialog.Double.Height: 欄の高さ(int)
Xrs.Dialog.Double.Step: パラメータチューニングの刻み幅(double)
Xrs.Dialog.Double.Format: double型変数用のprintf書式文字列(s)
Xrs.Dialog.Double.Color: インディケータの色(s)
Xrs.Dialog.Double.Shape: 形(0 縦長/1 横長)
Xrs.Dialog.Double.Font: フォント(s)
♪
<XRS/i_dialog.h>(int変数用ダイアログ)
Xrs.Dialog.Int.String: タイトルの最大文字数(int)
Xrs.Dialog.Int.Xoffset: 文字の書き始めの位置のx座標(int)
Xrs.Dialog.Int.Yoffset: 文字の書き始めの位置のy座標(int)
Xrs.Dialog.Int.Width: 欄の幅(int)
Xrs.Dialog.Int.Height: 欄の高さ(int)
Xrs.Dialog.Int.Step: パラメータチューニングの刻み幅(int)
Xrs.Dialog.Int.Format: int型変数用のprintf書式文字列(s)
Xrs.Dialog.Int.Color: インディケータの色(s)
Xrs.Dialog.Int.Shape: 形(0 縦長/1 横長)
Xrs.Dialog.Int.Font: フォント(s)
♪
<XRS/c_dialog.h> (complex変数用ダイアログ)
Xrs.Dialog.Complex.String: タイトルの最大文字数(int)
Xrs.Dialog.Complex.Xoffset: 文字の書き始めの位置のx座標(int)
Xrs.Dialog.Complex.Yoffset: 文字の書き始めの位置のy座標(int)
Xrs.Dialog.Complex.Width: 欄の幅(int)
Xrs.Dialog.Complex.Height: 欄の高さ(int)
Xrs.Dialog.Complex.Real.Step: 実部/半径の刻み幅(double)
Xrs.Dialog.Complex.Imaginary.Step: 虚部/角度の刻み幅(double)
Xrs.Dialog.Complex.Format: double型変数用のprintf書式文字列(s)
Xrs.Dialog.Complex.Color: インディケータの色(s)
Xrs.Dialog.Complex.Shape: 形(0 or 1)
Xrs.Dialog.Complex.Font: フォント(s)
|
4. バグ、変更点のメモ
|
- ‘ver.3 ⇒ ver3.1 (1996 4/13)’
class plane_window,Plane_Window の追加。
class graphic_window に draw_line,draw_circle を追加。
マニピュレータ COLOR,MONO,PHASE の構造を変えてヘッダに分離。
マニュアルの書き直しとバグとり。
- ‘ver.3.1 ⇒ ver3.2 (1996 4/22)’
-
- ‘ver.3.2 ⇒ ver3.2.1 (1996 5/16)’
-
- ‘ver.3.2.1 ⇒ ver3.2.2 (1996 8/2)’
dialog の resize 関数のバグ取り。virtual に変更し、d_dialog,
i_dialog,c_dialog それぞれに resize 関数を追加。
f_dialog,d_dialog,i_dialog,c_dialog に string,xoffset,yoffset,
offset 関数を追加。(細かなカスタマイズ用。)
Makefile 中の gcc のインクルードパスに -nostdinc++ オプションを
付けて g++-include より . が優先されるように変更。
- ‘ver.3.2.2 ⇒ ver3.2.3 (1996 11/11)’
つまらないバグ取り。Graphic.h の中の
inline Graphic_Window& operator<<(Graphic_Window &s,
COLOR_A_Uli m) 関数の定義で return s; が抜けていた。
initialize() 関数を実行する前のウィンドウに不可視状態を指定
(あるいは unmap() 関数の実行)が有効になるように改善。
- ‘ver.3.2.3 ⇒ ver3.2.4 (1996 11/15)’
-
- ‘ver.3.2.4 ⇒ ver3.2.5 (1996 12/24)’
Graphic_Window の描画関数に色番号を直接指定して書かせる関数
point(int,,)、line(int,,,,)、circle(int,,,)、draw_2D(int**)
を追加。
color.h に色相と飽和度が連続的に変わる disk 状の色配列を取
るたの関数 colordisk とその逆関数 diskcolor を追加。
上の変更と合わせると、位相と振幅を同時に表示したいシミュレ
ーションも比較的簡単にできるようになった。
( "使い方" の "Graphic_Window 応用編" を見て下さい。 )
バグ取り:XRS/plane.h の頭が #ifndef XRS_graphic_H だった。
マニュアルのバグ取りと整理
- ‘ver.3.2.5 ⇒ ver3.2.6 (1997 3/25)’
Linux-OS できちんと動作確認したところバグが発覚。慌ててバグ
取り。(かなり重要&なさけないバグだったので、自分で先に見つ
けて助かった。)
また、gcc version 2.6.? でも問題なく動くようになりました。
d_dialog,i_dialog,c_dialog で使っていた Field_Width に
sprintf フォーマットの最小フィールド幅を使っていたため、
書式によっては segmentation fault が起きることがあった。
最小フィールド幅を使用しないように改めた。
ダイアログに表示される文字数は前回の表示文字数と今回の文
字数の大きい方に合わせ、不足分はスペースで補われる。
この改善によって、string_format.C の
関数 field_width() がなくなり、関数 void parameter_string
が文字数 int を返すように変更された。また、各 dialog class
の変数 Field_Width がなくなり、作業用の変数 fw,real_fw,
imag_fw が作られた。
class control_window のデストラクタ内でのダイアログリストの
後始末が重複して行なわれていたので改善する。
(exit 処理のし方によっては segmentation fault となることが
あった。)
class Complex_Control_Window の geometry 関数のリサイズ機能
が引数の書き間違いでうまくいっていなかったので直す。
class DataSocket の close 関数に void の付け忘れがあった。
(-Wall で warning が出ていた。)
Imakefile の INCS 変数に XRS/XRS.color が抜けていた。
サンプルプログラムの -Wall コンパイル時の warning をなくす。
サンプルプログラムのための Imakefile の作成。
サンプルプログラム XRSver3sample2D.C、XRSver3sampleGnuplot.C
中で配列の初期化が完全でなかったので改める。
gcc 2.6.? で問題なくコンパイル出来るように template 宣言をした
ファイル(template.C)を追加。
また、XRS/*.h 中の inline を無くし、-DNOINLINE オプションを
つけると *.C 中の inline を使わないように変更した。
class Exec の中で実行する execv を execvp に変更。shell でコマ
ンドを実行するので full path を与えなくて良くなった。
- ‘ver.3.2.6 ⇒ ver3.2.7 (1997 5/17)’
バグ取り。class graphic_window で char * 型のメンバー関数
の初期化(=NULL)が不十分だった。new なのでウィンドウを動的配列と
して取った時、segmentation fault が出る場合があった。
位相と振幅を同時に表示したいシミュレーションのための色の取
り方についてのマニュアルの記述をもう少し追加。
( "使い方" の "Graphic_Window 応用編" を見て下さい。 )
マニュアルにLinux でのコンパイルの仕方の記述を追加。
- ‘ver.3.2.7 ⇒ ver3.2.8 (1997 6/28)’
FreeBSD、X11R6.3 で試したところいくつか修正しなければいけない所
が発覚。
<X11R6.3 への移植で見つかったバグ>
class window の変数 XrmDatabase rDB; が最初のウィンドウ XRS_ROOT
を作る時に初期化されていなかった。window.C の window のコンスト
ラクタ window:window(char *,char *) に :rDB(NULL) を追加。
<FreeBSDへの移植>
struct sockaddr_un の定義に u_char が使われているため、Socket.C
の中にあった #include <sys/types.h> の行を Socket.h に移す。
また、Socket.C の中で bind,connect 関数に渡す構造体 sockaddr の
長さ int len に +1 が必要。
Imakefile 中の all: を all:: に変更。
また、ライブラリのバージョンを調べられるように中身のない名前だけ
のファイル __version_XX__.o を作って libXrs.a の先頭に追加するよ
うにした。
- ‘ver.3.2.8 ⇒ ver3.2.9 (1997 7/1)’
FreeBSD+XFree68-3.3+X11R6.3 の載ったマシンで Xlib の関数
XDrawPoint がうまく動かないことがわかった(X のバグかどうかは?
??)。 とりあえず、-DWITHOUT_XDRAWPOINT をつけてコンパイルする
と XDrawPoint の代わりに XFillRectangle を使うように改造した。
- ‘ver.3.2.9 ⇒ ver3.2.10 (1998 3/29)’
StataboWare-1.0 の載ったマシンでもコンパイル出来るようにした。
Imakefile を編集して -DStataboWare オプションをつけてコンパイ
ルしてください。
Socket.h と Socket.C で使うインクルードファイルが微妙に違うので、
-DStataboWare オプションを追加して場合分けしました。
c_dialog.C と sample/XRSver3Complex.C の中で使われた、
g++ の複素数ライブラリの polar 関数の多重定義がうまく動かず、
明示的に型指定 polar(double,double) をしなければならなかった。
- ‘ver.3.2.10 ⇒ ver3.2.11 (1998 5/29)’
バグ発見したので修正。f_dialog を << を使わずに直接型宣言して
control_window に登録した時、終了時に記憶領域を解放しようとし
て Segmentation Fault を起こすことがあることがわかった。
これも結構おろかなバグで、プログラミングの素人であることを実感
してしまった。
- ‘ver.3.2.11 ⇒ ver3.2.12 (1998 7/15)’
gcc-2.8.1 に対応。
List.h の最初に必要なテンプレートの宣言を2行忘れていたことが判明。
それを直したら無事に通った。ついでに、Makefile.sample を書きかえ、
DEC-OS でもちゃんと動くことを確認した。
Linux で datasocket.o のリンク時に _IO_putc が未定義だと言われて
失敗する。これは、C の標準ヘッダの stdio.h でなく g++ の stdio.h
をインクルードしている為らしい。とりあえず、Imakefile を変更して、
datasocket.o を作る時には g++ をインクルードパスからはずすように
しておいた。(もっといい方法があるかもしれない。)
- ‘ver.3.2.12 ⇒ ver3.2.13 (1999 4/28)’
libg++ の新しいバージョンに対応。
#include <Complex.h> を #include <complex> に変更。
typedef complex<double> Complex; を追加した。
- ‘ver.3.2.13 ⇒ ver3.2.14 (2000 4/9)’
gcc-2.95.2 に対応。
コンパイル時にエラーが出たので修正。
今はコンパイラがやってくれるのでほとんど必要なくなった register を無くし、すべて int で統一。
いくつかの関数の extern "C" をコメントアウト。
Socket.C の accept関数の3番目の引数を (socklen_t *)&fromlen とした。
- ‘ver.3.2.14 ⇒ ver3.2.15 (2001 1/26)’
-
- ‘ver.3.2.15 ⇒ ver3.2.16 (2002 3/17)’
島氏から報告された xcoloredit_color.C の中の変数 rgb.r, rgb.g, rgb.b の代入文の型変換のバグを修正(short -> unsigned short)。
変数表示のバグを修正: d_dialog.C, f_dialog.C, i_dialog.C で使って
いた f_old を static 変数からメンバー関数に変更した。
xcoloredit が最近使えないので、マニュアルにgimpを使った色ファイルの作り方を追加。
- ‘ver.3.2.16 ⇒ ver3.2.17 (2004 8/12)’
gcc ver.3 にするとコンパイルエラーが出るとの茶碗谷さんの報告を
受け、namespace std の宣言などを修正。ver.3 は標準C++の仕様に忠実です。
Intel C++ コンパイラも通り、サンプルプログラムは無事動くことを
確認(細かなwarning は山ほどでる)。
もう不要と思われる Stataboware 用のコンパイルオプションと、
NOINLINE のオプションを削除。
Imakefile, Makefile などを一部修正。インクルードファイルのデフ
ォルトのインストール先を /usr/include に変更。
- ‘ver.3.2.17 ⇒ ver3.2.18 (2009 12/6)’
Ubuntu 9.10(g++ 4.4.4-1)でコンパイルできるように微修正。
char* と const char* の型変換のせいで warning が大量に出ていたので修正。
特に Color, Socket 関係の関数で引数を const char * に変更したものがあります。
エラーが出る場合は型変換してください。
- ‘ver.3.2.18 ⇒ ver3.3.0 (2018 11/30)’
ソース全体を namespace XRS の中に入れる。このため、このバージョン
以降は XRSを使用する際に using namespace XRS; と最初に宣言するか、関数
の前にXRS::をつける必要があります。以前に作ったプログラムをコンパイルする
際は修正をお願いします。
Exec.h, DataSocket.h で << を型に制限なく使えるように変更。
<<で文字列を出力した後の自動改行をやめました。このため、以前のバージョンで
動いたプログラムをコンパイルする際は、最後に <<endl を追加する必要があります。
ヘッダファイルの名前の変更: simple.h, graphic.h, plane,h, control.h
–> simple_.h, graphic_.h, plane_,h, control_.h とする。
デフォルトで XRS.color を読まない場合があるバグを修正。
Ubuntu 18.04 (gcc 7.3.0) でwarning なくコンパイルできるように微修正。
サンプルファイルを微修正。
|
索引
変数索引
——————————————————-
関数索引
目次
簡略化した目次
この文書について
この文書はkitsuneによって2018年11月月30日にtexi2html 1.82を用いて生成されました。
ナビゲーションパネル中のボタンには以下の意味があります。
ボタン |
名称 |
移動先 |
1.2.3項からの移動先 |
[ < ] |
Back |
Previous section in reading order |
1.2.2 |
[ > ] |
Forward |
Next section in reading order |
1.2.4 |
[ << ] |
FastBack |
Beginning of this chapter or previous chapter |
1 |
[上] |
Up |
Up section |
1.2 |
[ >> ] |
FastForward |
Next chapter |
2 |
[冒頭] |
冒頭 |
Cover (top) of document |
|
[目次] |
目次 |
Table of contents |
|
[見出し] |
見出し |
見出し |
|
[ ? ] |
About |
About (help) |
|
例では、以下に示す構造を持つ文書の1.2.3項を現在位置に仮定しています。
- 1. 第1項
- 1.1 第1.1項
- 1.2 第1.2項
- 1.2.1 第1.2.1項
- 1.2.2 第1.2.2項
- 1.2.3 第1.2.3項
<== 現在位置
- 1.2.4 第1.2.4項
- 1.3 第1.3項
- 1.4 第1.4項
この文書はkitsuneによって2018年11月月30日にtexi2html 1.82を用いて生成されました。