第9回

C プログラミング
8
$ cp eggx procall.pdf ˜/CPR2/EGGX 簡易グラフィックライブラリ EGGX
8
簡易グラフィックライブラリ EGGX
gnuplot はデータをグラフ化するのに,たった数行の命
令で済む,実用的で便利なツールです.かなり無理をして
8.1.2
アニメーションなども作成してみました.もっと自由にグ
お試し
今後はディレクトリ˜/CPR2/EGGX で作業をします.した
ラフィックを操作したいならば,もう一段低位のレベルで
がって,そこにカレントディレクトリを移します.
$ cd ˜/CPR2/EGGX 調整が必要となります.Unix 系では X Window System が
グラフィックシステムを提供しています.今流行のデスク
トップ環境 Gnome や KDE も全て,X11(X Window System
サンプルファイルをコピーして,お試しコンパイル,実行
Ver.11) の上に構築されています.また将来 X11 に取って
代わるグラフィックシステムが登場することは考えにくい
をしてみてください(図19).
$ cp ˜/CPR2/eggx-0.83/sample/* ./ $ ./egg -o mousetst mousetst.c gcc -O2 -Wall -o mousetest mousetest.c
-I/usr/local/include -L/usr/local/lib
-I/usr/X11R6/include -L/usr/X11R6/lib -leggx
-lX11 -lm
$ ./mousetst です.従って,X11 の最低位のライブラリの関数群がグラ
フィックのシステム(成立ち)を理解するのに最も適して
いることは間違いないのですが,それは専門家になる場合
のお話です.我々は,CG の教科書にあるような事柄を実
現している最上位のライブラリがある程度使えるようにな
ることで満足しましょう.
規模の大きなグラフィックライブラリはこの講義 2 回分で
サンプルファイルの内,rupin.c は,大きなサイズの日
はとても扱えませんので,簡素かつ厳選された機能に絞っ
本語文字列を表示するデモですが,フォント設定が適切で
たものをとりあげます.EGGX は,Plamoという Linux の
ないと表示されないかもしれません.
配布パッケージで X11 周りを担当されていた山内氏が開
発されたもので,コンパクトでたいへん使い易いライブラ
リです.
+ 参考ウェブサイト:EGGX/ProCALL
• EGGX/ProCALL:作者のページ
• EGGX/ProCALL でグラフィックス
8.1
8.1.1
EGGX/ProCALL のインストール
ユーザーインストール
システムに EGGX が導入されてない場合には,ユーザー
毎に導入する必要があります.EGGX は規模が小さいので,
必要なファイル数が少なく,とても簡単にインストールで
きます.配布文書 INSTALL に記された通りにインストー
ルを進めます.概要は,ソースから tar で展開されたトッ
プディレクトリに移りリンクで Makefile を作成し,make
で出来あがったヘッダファイルとライブラリとコンパイル
コマンド egg を,作業用のディレクトリにコピーするだけ
です.
$ tar -zxvf eggx-0.83.tar.gz $ cd eggx-0.83 $ make -f Makefile.linux $ mkdir ˜/CPR2/EGGX $ cp egg egg*.h libeggx.a /CPR2/EGGX 図 19 EGGX に含まれるサンプルプログラム mousetest
EGGX という作業ディレクトリを CPR2 の下に作成していま
す.ついでに,説明文書もコピーしておきましょう.
34
目次へ
の実行画面:下の画面でマウスをクリックすると,カーソ
ル線と座標値が表示されます.
C プログラミング
基本的な機能
8.2
簡易グラフィックライブラリ EGGX
8
8.2.2
基本図形と文字列
以下に述べる説明の詳細については,開発者の山内氏が
画面の背景を黒以外に変更し,楕円・長方形・文字列な
提供している簡易マニュアル eggx procall.pdf を参照して
どを描いてみましょう.オープンした画面の左下点と右上
ください.
点の描画時の座標値を設定しなければなりません.これも
簡単にできます.
window( int wn,
ウィンドウのオープン
8.2.1
xs,
float
ys,
float
xe,
float
ye)
(win,0,0,width,height) とするのが一番わかり易いで
それでは早速ウィンドウを開いてみましょう.それはと
す.背景色を変更するには,
ても簡単にできて,
gsetbgcolor( int wn,
int win;
...
win = gopen( int xsize,
float
int
constant char ∗
argsformat, ...)
とします.argsformat には色の名前(例えば “slate blue”)
ysize);
や RGB 記法(例えば “#993366”)などの文字列を与えま
この一行だけで,幅 xsize 高さ ysize の窓が,ルートウィ
す.この命令の後に,gclr() で初期化しないと変更には
ンドウに現れます.fopen や popen と同様に,open したら
なりません.前景色を変更するには,以下のコマンドを使
close するという決まりは守りましょう.
います.
newpen( int wn,
gclose( int wn);
newcolor(
int
int
wn,
cn)
cn = 0,1,· · · ,15
constant char ∗
argsformat, ...)
楕円を描くには,
例題 28
アスペクト比が 4:3 のウィンドウを開いてみな
circle( int wn,
float
yrad)
さい.
[解] 次のような簡単なソースで実現できます.15 行目は
お約束.14 行目の ggetch(win) はオープンしたウィンド
の役割を持たせています.これがないと,一瞬のうちにプ
ログラムが終了してしまいます.
2
3
xcen,
float
ycen,
float
xrad,
です.座標値の変数の型は float ですが,double 型や int
ウの上でキー入力を待ちます.つまり,一時中断(pause)
1
float
型の変数を与えても正常に動作します.他の図形について
は,マニュアルを参照してください.
例題 29
背景色を黒以外に変更して,楕円などの基本図
リスト 40 eggx00.c
形を描いてみなさい.
//# include <stdio .h>
//# include <stdlib .h>
# include "eggx.h"
[解] ”old lace” という名前の白色の背景に,楕円と長方
形と文字列を描いた例を示します.
4
5
6
# define WD 384
# define HT 256

/usr/lib/X11/rgb.txt を眺めてみましょう.英語の色の名前が判って
7
8
9
10
11
X Window System では色を名前で使うことができます.その一覧
面白いです.
int main(int argc , char ** argv)
{
int win;
12
win = gopen (WD , HT );
ggetch (win );
gclose (win );
13
14
15
16
return 0;
17
18
}
次のようにコンパイルしてください.
./egg -o eggx00 eggx00.c 実行すると,384 × 256 の黒い(default の背景色)画面
が表示されます.何かキーを入力すると,終了して画面が
消えます.
問題 18
図 20 eggx01 の実行画面
起動時にウィンドウサイズをオプション指定で
きるように改変しなさい.
35
目次へ
C プログラミング
8
リスト 41 eggx01.c
1
2
3
21
6
24
25
27
28
29
30
31
8
10
11
12
s r a n d 4 8 ( t i m e s (NULL ) ) ;
imax = IMAX ;
i f ( argc > 1) {
imax = a t o i ( a r g v [ 1 ] ) ;
}
26
# define WD 384
# define HT 256
7
9
i n t win , imax , i ;
double x , y ;
struct timeval ts , t f ;
23
4
5
{
22
# include <stdio .h>
# include <stdlib .h>
# include "eggx.h"
簡易グラフィックライブラリ EGGX
g s e t i n i t i a l b g c o l o r ( "white " ) ;
win = gopen (WD+2∗MG, HT+2∗MG) ;
window ( win , −MG, −MG, WD+MG, HT+MG) ;
winname ( win , " Drawing %d lines " , imax / 2 ) ;
32
int main(int argc , char ** argv)
{
int win;
double x = 3.14159;
33
34
35
36
g e t t i m e o f d a y (& t s , NULL ) ;
f o r ( i = 0 ; i < imax ; i ++) {
x = d r a n d 4 8 ( ) ∗WD; y = d r a n d 4 8 ( ) ∗ HT ;
l i n e ( win , x , y , PENUP ) ;
x = d r a n d 4 8 ( ) ∗WD; y = d r a n d 4 8 ( ) ∗ HT ;
newpen ( win , i % 16 ) ;
l i n e ( win , x , y , PENDOWN) ;
}
g e t t i m e o f d a y (& t f , NULL ) ;
difftime msec ( ts , t f ) ;
g g e t c h ( win ) ;
g c l o s e ( win ) ;
37
13
38
win = gopen (WD , HT );
gsetbgcolor (win , "old lace");
gclr(win );
window (win , 0, 0, WD , HT );
14
15
16
17
39
40
41
42
43
18
newpen (win , 12);
circle (win , WD/2, HT/2, WD/4, HT /4);
newpen (win , 11);
fillrect (win , 0, 0, WD/3, HT /3);
newpen (win , 13);
drawstr (win , WD/4, 7* HT/8, 16, 0,
" displacement x = %f", x);
19
20
21
22
23
24
25
44
45
46
47
48
49
return 0;
50
51
}
26
32 行 目 で 画 面 の 背 景 色 の 既 定 値 を 変 更 す る コ マ ン
ggetch (win );
gclose (win );
27
28
ド gsetinitialbgcolor() を使いました.この関数は,
gopen() よりも前に呼ぶ必要があります.
29
return 0;
30
31
}
gsetinitialbgcolor( constant
問題 19
char ∗
argsformat, ...);
起動時に背景色をオプション指定できるように
改変してみなさい.
問題 20 長方形や円などの描画速度を測定するプログラム
を作成しなさい.すなわち,大きさや位置が異なる長方形
8.2.3
描画速度テスト
や円などを多数描画し時間を計測するプログラムを作成し
なさい.
EGGX のようなグラフィックライブラリを用いれば,外
部コマンド gnuplot を起動するのに比べて,細かいレイア
ウト調整が可能なだけでなく,描画の速いことが期待でき
8.2.4
画像の表示:putimg24()
ます.
EGGX は画像を表示すること(あるいはウィンドウを画
例題 30
像ファイルとして保存すること)も可能です.画像は内容
多数の線分(10000 本位)を描画するのに要す
る時間を計測プログラムを作成しなさい.
を EGGX の仕様に合わせた配列としてヘッダファイルな
[解] 多項式の評価(p.13)の例題と同様に,gettimeofday
どに保存しておかなければなりません.コマンドは以下の
を利用してみましょう.
ようなものです.
putimg24( int wn, float x, float y,
int
height, unsigned char ∗ buf)
リスト 42 eggx03.c
1
2
3
4
5
6
# include
# include
# include
# include
# include
# include
< s t d l i b . h>
<math . h>
< s y s / t i m e . h>
< s y s / t i m e s . h>
< u n i s t d . h>
<eggx . h>
9
10
11
# define
# define
# define
# define
WD
HT
MG
IMAX
ません.buf が配列名です.また (x, y) は左下の位置を指
します.
400
400
20
20000
なお ppm 画像形式を配列に変換するツール ppmtoh が
sample に含まれています.ppm 画像への変換ツールはいろ
12
13
14
15
16
17
18
いろとありますが,歴史あるNetpbmを利用するといいで
void d i f f t i m e m s e c ( s t r u c t t i m e v a l s , s t r u c t t i m e v a l f )
{
p r i n t f ( "%f [ms]\n" ,
1000∗( f . t v s e c − s . t v s e c )
+ 0 . 0 0 1 ∗ ( double ) ( f . t v u s e c − s . t v u s e c ) ) ;
}
しょう.
例題 31
19
20
球と床の ppm 画像を使って,方物運動の軌跡を
ストロボ撮影したような画面を表示するプログラムを考え
i n t main ( i n t a r g c , char ∗ a r g v [ ] )
36
目次へ
width,
画像の幅(width)と高さ(height)が判っていないといけ
7
8
int