コンピュータ基礎II 通信授業課題2C 参考ページ



4. 繰り返し、条件分岐

○サンプル11

サンプル11では円を描画しています。
次のサンプル12では円を描く命令を独自の手続きとして定義します。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

newpath
300 150 15 0 360 arc
stroke
showpage

**********************************************************************

PostScriptサンプル11



a b c d e f arc
点 ( a, b ) を中心として半径15pointの円弧をe(開始角)からf(終了角)まで描きます(反時計回り)。

a b c d e f arcn
点 ( a, b ) を中心として半径15pointの円弧をe(開始角)からf(終了角)まで描きます(時計回り)。

開始角を0度、終了角を360度とすると正円が描かれます。

○サンプル12

サンプル12では、円の描画をcircleという手続きにまとめています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

/circle { newpath 0 360 arc } def

300 150 15 circle

stroke
showpage

**********************************************************************

PostScriptサンプル12



/手続きの名前 { 定義したい処理 } def

/に続けて任意の手続き名、{}内に定義したい処理内容を記述し、最後にdefと書くと独自の手続きを定義できます。

変数も同様に、
/変数名 値 def
の形式で定義することができます。

/i 0 def
とすれば、変数iの値を0にするという意味です。
変数に値を代入し直す時も同様です。
また
/i i 1 add def
と記述すれば、iの値を1増加するという意味になります。

実行の際には/は不要で、手続き名、変数名だけ記述します。

○サンプル13

サンプル13では、直線をrepeatオペレータにより繰り返して描いています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

newpath
50 50 moveto

10 { 500 0 rlineto -500 10 rmoveto } repeat

stroke
showpage

**********************************************************************

PostScriptサンプル13



繰り返し回数 { 繰り返したい処理 } repeat
{}内に記述した処理を、任意の回数、繰り返して行います。

サンプルでは、500pointの線を描き、カレントポイントを直前に描いた線の描画開始位置よりy軸方向に10point移動させる、という処理を10回繰り返して行っています。

○サンプル14

サンプル14ではサンプル13に加え、定義したcircleをrepeatさせることで、円を10個、描いています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

/circle { newpath 0 360 arc stroke } def
/i 0 def
10 { 
    65 50 i mul add 200 15 circle
    /i i 1 add def
} repeat

newpath
50 50 moveto
10 { 500 0 rlineto -500 10 rmoveto } repeat
stroke

showpage

**********************************************************************

PostScriptサンプル14



変数iを初期値0で定義し、repeat内で円のx座標の値を増加させるのに使用しています。
初めの円が描かれる座標x:65の値から、i × 50ずつ値を増加させています。

65 50 i mul add
は普通の書き方をすると、
65+50×i
になります。 またrepeat内でiの値に1を足しているので(/i i 1 add def)、repeatが繰り返される度にiの値が1ずつ増加します。

○サンプル15

サンプル15ではサンプル14と同じ描画が行われますが、repeatオペレータではなくforオペレータを使用して、円を10個、描いています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

/circle { newpath 0 360 arc stroke } def

65 50 515 { 200 15 circle } for

newpath
50 50 moveto
10 { 500 0 rlineto -500 10 rmoveto } repeat
stroke

showpage

**********************************************************************

PostScriptサンプル15



初期値 増分 終了値 { 繰り返したい処理 } for
値が初期値から増分だけ増えつつ終了値まで達するまで{}内の処理が繰り返されます。

サンプルでは増える値をそのままcircleに渡すx座標の値として、円を描画しています。

○サンプル16

サンプル16ではサンプル14と同じ描画に色を使用しています。
描かれる線は分岐を使用して、交互に色を変えています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

/circle { 0 360 arc } def
/i 0 def
10 { 
    65 50 i mul add 200 15
    newpath 
    circle
    1 .5 0 setrgbcolor
    stroke
    /i i 1 add def
} repeat

/i 0 def
10 { 
    newpath
    50 50 i 10 mul add moveto
    i 2 mod 0 eq
    { 0 1 .5 setrgbcolor }
    { .5 0 1 setrgbcolor }
    ifelse
    500 0 rlineto stroke
    /i i 1 add def
} repeat

showpage

**********************************************************************

PostScriptサンプル16



論理値 { 処理1 } { 処理2 } ifelse
論理値の部分に書かれる式などが正しい場合(真)は処理1が、そうでない場合(偽)は処理2が実行されます。

サンプルではiの値を2で割った余り(i 2 mod)を0と比較しています(0 eq)。
余りが0なら(iが偶数なら)初めの{}内の処理(色を緑にする)が、そうでなければ(余りが1、iが奇数なら)次の{}内の処理(色を紫にする)が実行されます。

論理値を返す比較などを行うオペレータとして以下のようなオペレータとして用意されています。

a b gt
aの値がbの値より大きければ( a > b )、真が返されます。

a b lt
aの値がbの値より小さければ( a < b )、真が返されます。

a b ge
aの値がbの値以上であれば( a >= b )、真が返されます。

a b le
aの値がbの値以下であれば( a <= b )、真が返されます。

a b eq
aの値とbの値が等しければ( a = b )、真が返されます。

a b ne
aの値とbの値が等しくなければ( a ≠ b )、真が返されます。

○サンプル17

サンプル17では直線にそって円を描きつつ、円の色を交互に変えています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

/circle { 0 360 arc } def

/x_point 50 def
/y_point 50 def

/x1_point 50 def
/x2_point 550 def
/y1_point 50 def
/y2_point 250 def

newpath
x1_point y1_point moveto
x2_point y2_point lineto
stroke

/i 0 def
/divx 25 def
/x_plus x2_point x1_point sub divx div def

divx 1 add { 

    x_point y_point 15
    newpath 
    circle
    i 2 mod 0 eq
    { 1 .5 0 setrgbcolor }
    { 0 .5 1 setrgbcolor }
    ifelse
    stroke

    /i i 1 add def
    
    /x_point x_point x_plus add def
    
    /y_point
    y2_point y1_point sub
    x2_point x1_point sub div
    x_point x1_point sub mul
    y1_point add
    def
    
} repeat

showpage

**********************************************************************

PostScriptサンプル17



2点、( x1, y1 )、( x2, y2 ) を通る直線の方程式は、

y - y1 = ( y2 - y1 ) / ( x2 - x1 ) * ( x - x1 )

で表現できます。

サンプルでは、直線が取りうるx座標を25分割し、円を描くx座標の増分を決めています。
/divx 25 def
/x_plus x2_point x1_point sub divx div def

そして、26回(divx 1 add)円の描画を繰り返す中で、円を描くx座標の値を次第に増加させています。
/x_point x_point x_plus add def

以下の部分でy座標を計算しています。
/y_point
y2_point y1_point sub
x2_point x1_point sub div
x_point x1_point sub mul
y1_point add def

○サンプル18

サンプル18では乱数を使用して直線を描いています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

/i 0 def
/xoffset 50 def
10 srand

50 {
    /x1_point rand 500 mod def
    /x2_point rand 500 mod def
    
    newpath
    x1_point xoffset add 50 moveto
    x2_point xoffset add 250 lineto
    
    i 2 mod 0 eq
    { 0 .6 1 setrgbcolor }
    { .75 0 .75 setrgbcolor }
    ifelse
    
    stroke
    
    /i i 1 add def
} repeat

showpage

**********************************************************************

PostScriptサンプル18



repeat文で直線を描く処理を50回、繰り返しています。その度、直線の開始のx座標と終了のy座標には0〜499の値がランダムに代入されます。

rand
0から、2の31乗-1までの範囲の整数の乱数を返します。

randで返された数値を500で割ったあまりは0〜499の整数になります。
また乱数の発生はsrandオペレータで初期化できるので、
10 srand
の10の部分を変更し保存し再度ファイルを開くと、別の状態の直線が描かれます。

○サンプル19

PostScriptには座標を変換するオペレータが用意されています。サンプル19では繰り返しと座標変換オペレータを使用しています。

**********************************************************************

%!PS-Adobe-3.1 EPSF-3.0
%%BoundingBox: 0 0 600 300

/circle { newpath 0 0 15 0 360 arc stroke } def

gsave
350 25 translate
10 {
    1 .5 .8 setrgbcolor
    circle
    25 5 translate
} repeat
grestore

gsave
100 100 translate
10 {
    .6 .7 .4 setrgbcolor
    circle
    1.2 1.2 scale
}repeat
grestore

gsave
300 200 translate
10 {
    newpath
    0 0 moveto
    80 0 lineto
    .4 .5 .8 setrgbcolor
    stroke
    36 rotate
}repeat
grestore

showpage

**********************************************************************

PostScriptサンプル19



a b translate
現在の座標系の点 ( a, b ) の位置へ、新しい座標の原点を移動させます。

a b scale
原点を中心に座標系を拡大、縮小させます。
またaに-1を指定すると、x軸に対する図形の対象移動、bに-1を指定するとy軸に対する図形の対象移動、a, bともに-1を指定すると原点に対する図形の対象移動となります。

a rotate
座標系を反時計回りにa度、回転させます(aにマイナスの値を指定すると時計回りに回転します)。

座標変換を行うと、どんどん座標が変換されていくので、サンプルでは行う前の状態をgsaveオペレータで保存し、変換後grestoreオペレータで元の状態に戻しています。