EPSグラフィック直書き入門
EPS (Encapsulated PostScript) 画像をテキストエディタで直書きする変態のためのチュートリアルです。EPSとは何か
ぐぐれEPSをテキストエディタで書くメリット
- マウスより正確に書けるし、微調整がしやすい
 - 数値データを図形に変換できる
 - PerlやRubyなどのスクリプトから図を出力できるようになる
 - 描いたあとでIllustrator等に取り込んで編集できる
 - SSHでリモートアクセスしてその場で図が書ける
 - 周囲の人に変態認定される
 
基本的な書き方
EPSはJPEGやGIFなどのいわゆる画像ファイルとは異なり、「ページ記述言語」と呼ばれるプログラミング言語の一種です。 基本は「キャンパスの上で仮想的な筆を動かして図を描く」という考え方をします。
試しに、以下のようなソースを書いて test.eps という名前で保存すれば、「点(100,100)を起点とした、1辺が100の正方形」を描くことができます。
			
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 200 100 lineto % (200,100)まで直線を引く 200 200 lineto % (200,200)まで直線を引く 100 200 lineto % (100,200)まで直線を引く 100 100 lineto % (100,100)まで直線を引く stroke % このパスの輪郭を描く %%EOF
線の色を設定する
線の描写を指示するstrokeより前に、色を指定するコマンドであるsetrgbcolorを入れると、線の色をRGB形式で指定できます。
			RGB (赤、緑、青) の値はそれぞれ0〜1の範囲です。
			
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 200 100 lineto % (200,100)まで直線を引く 200 200 lineto % (200,200)まで直線を引く 100 200 lineto % (100,200)まで直線を引く 100 100 lineto % (100,100)まで直線を引く 1 0 0 setrgbcolor % 赤色に設定 stroke % このパスの輪郭を描く %%EOF
線の太さを指定する
太さは色と同様にsetlinewidthコマンドで
			
3 setlinewidthこのように指定します。 デフォルトの太さは1です。
塗りつぶし
「パスの輪郭を描写」を意味するstrokeの代わりにfillを使えば塗りつぶしができます。
			線と塗りつぶしを両方使いたいときは、gsaveを使ってパスを一旦保存し、塗りつぶしを行ったあとでgrestoreで保存したパスを開いて輪郭の描写を行います。
			(順番を逆にすると、輪郭の一部が潰れてしまいます。)
			
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 200 100 lineto % (200,100)まで直線を引く 200 200 lineto % (200,200)まで直線を引く 100 200 lineto % (100,200)まで直線を引く 100 100 lineto % (100,100)まで直線を引く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く %%EOF
正三角形を描く
次に正三角形を描いてみましょう。
正三角形の座標を指定するためには、sinやcosを使ってあらかじめ計算してもいいのですが、 せっかくなのでEPSの計算機能を使用してみましょう。
EPSでは、100 100 addと書くと、200と同じ意味になります。
			20 30 mulならば600と同じです。
			通常のプログラミング言語ならば100 + 100と書くところですが、
			EPSは演算子が最後に来ます。このような記法を逆ポーランド記法といいます。
			
さて本題に戻りますが、三角形を書くためには「ある点から、120度の方向に、距離100だけペンを進める」という表記を使います。
			これは数式にすると、x座標が100*cos(120), y座標が100*sin(120)という値になります。
			100*cos(120)をPostScriptの記法で描くと、
			100 120 cos mul
			となり、100*sin(120)は
			100 120 sin mul
			となります。よって、上述の「120度の方向に、距離100だけペンを進める」というコマンドは
			
100 120 cos mul 100 120 sin mul rlinetoと書きます。 これを解釈すると、まず
120 cosの部分が計算されて-0.5に、
			120 sinは0.866となるので、このコードは
			100 -0.5 mul 100 0.866 mul rlinetoと同じ意味になります。 次に、
100 -0.5 mulは掛け算なので-50、100 0.866 mulは86.6となるので
			-50 86.6 rlinetoとなります。 最後の
rlinetoは、linetoと違って「現在のペンの位置から、指定された座標だけ移動する」という相対座標を表しています。
			以上のことを踏まえて、三角形を描くEPSは以下のようになります。
			%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 300 300 newpath % 新しいパスを生成 100 100 moveto % ペンを(100,100)に移動 100 0 rlineto % 相対座標(100,0)だけ線を引く 100 -0.5 mul 100 0.866 mul rlineto % 相対座標(100cos(120),100sin(120))まで直線を引く closepath % パスを閉じる stroke % パスの輪郭を描く %%EOF
円を描く
円弧を描くときはarcというコマンドを使います。
			角度の範囲が指定でき、0から360までにすると円になります。
			
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 50 50 150 150 newpath % 新しいパスを生成 100 100 20 0 360 arc % (100,100)を中心に、0度から360度へ半径20の円弧を描く stroke % パスの輪郭を描く %%EOF
変数・関数の使用
上に描いた方法で、この円を塗りつぶすことができます。 試しに、赤で塗りつぶし、黒で輪郭をつけた円を、x座標だけ変えて3個書いてみます。
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 50 200 150 newpath % 新しいパスを生成 50 100 20 0 360 arc % (50,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く newpath % 新しいパスを生成 100 100 20 0 360 arc % (100,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く newpath % 新しいパスを生成 150 100 20 0 360 arc % (150,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く %%EOFやたら同じコードの繰り返しで嫌になってしまいますね。 こういう場合は、プログラミング言語的な考え方として、変数・関数を使います。
EPSでは変数に値を代入するときはdefというコマンドを使います。
				たとえばxに200という値を代入するときは
			
/x 200 defと書きます。これを用いて
/x 200 def /y 100 def x y 20 0 360 arcと書けば、
200 100 20 0 360 arcと同じ意味になります。 代入時には
/x、参照時にはxと書くので注意しましょう。
			
			またEPSでは、数値だけでなく「図形そのもの」を変数に代入することができます。
/fig { (図形の描写) } def
			このように書けば、変数figに図形を代入できる(つまり参照した時に図形の描写が行われる)ことができます。
			
			たとえば、circleという変数に円の描写を代入すると
			
%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 50 200 150 /circle { newpath % 新しいパスを生成 100 100 20 0 360 arc % (100,100)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く } def circle % 定義した変数を呼び出し、円を描写 %%EOFこのようにして円を描くことができます。 しかし、これでは最初に指定した(100,100)の位置にしか円が出せません。 そこで、座標を引数で指定できるようにします。これには
exchコマンドを使います。
			
			%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 50 200 150 /circle { /y exch def % 引数の値を変数yに代入 /x exch def % 引数の値を変数xに代入 newpath % 新しいパスを生成 x y 20 0 360 arc % (x,y)を中心に、0度から360度へ半径20の円弧を描く gsave % パスを保存 1 0 0 setrgbcolor % 赤色に指定 fill % パスを塗りつぶす grestore % 保存したパスを開く 0 0 0 setrgbcolor % 黒色に指定 stroke % パスの輪郭を描く } def 50 100 circle % 引数(50,100)を指定してcircleを呼び出す 100 100 circle % 引数(100,100)を指定してcircleを呼び出す 150 100 circle % 引数(150,100)を指定してcircleを呼び出す %%EOFこれで先ほどと同じ画像を描写することができます。
おまけ
こないだ(2012/12/02)書いた第五使徒ラミエル。
ソースコードはこちら。
製作時間は30分。