BASIC 《 プログラミング言語 《 大系彷徨の神殿
『スピログラフ』

第1回 円

Part 1. Circle
2006.10.28-2006.11.11,2006.12.25

スピログラフ(spirographというものがあるそうです。

歯車を使って図を描くもののようですが、僕は知りませんでした。もしかしたらどこかで目にしていたりするのかもしれませんが、少なくとも記憶には残っていません。

何となく面白そうなので、プログラムで描いてみます。

  1. 用意するもの
  2. デモンストレーション
    1. 円の式
    2. (擬似)円を描く
      1. とりあえず点を打つ
      2. 繰り返し
      3. 変数
      4. 線を引く
      5. 中心の座標と半径を指定する
    3. (擬似)円描画ルーチン
      1. サブルーチン化
      2. 中心の座標と半径を入力させる
      3. 入力を省略できるようにする
      4. 円弧を描いてみる

1. 用意するもの

開発環境
プログラムは「(仮称)十進BASIC」を使って作成します(「(仮称)十進BASICのセットアップ」を参照)。

2. デモンストレーション

この文書のゴールを示すために、まずはデモンストレーションを行います。

プログラムのダウンロード

次のファイルをダウンロードします。

(仮称)十進BASICで開く

demo-spiro.bas を(仮称)十進BASICで開くと、プログラムコードが表示されます。

(仮称)十進BASICで実行する

ツールバー上の実行ボタン 、あるいはF9キーで実行します。

途中で止める時は、ツールバー上の中断ボタン 、あるいはCtrl+Bキーで止めます。

上のような感じでパラメータの入力を二回求められますが、空欄のままOKボタンを押すかEnterキーを押して構いません。

すると、グラフィックスウィンドウ上にスピログラフが描かれていきます。

大きな円の円周に沿って小さな円が転がり、その転がる円の中の一点が描く軌跡 — それがスピログラフです。

描き終わると次のような図形が現れます。

描かれる図形は、与えるパラメータによって変わってきます。

例えば、最初に求められる入力で「8,5,4」と入力してみます。二つ目の入力は空欄のままで構いません。

すると、次のような図形が描かれます。

とまあ、こんな感じで遊ぶおもちゃです。

3. 円

物事には段階があります。

まずは、円(circleを描くところから始めます。

3.1. 円の式

図1*1. 円

図1のように、中心 C の座標が (xc,yc) 、半径の長さが r の円を考えます。

円の中心 C から見た円周上の点 P の位置は、図のように中心角が θ であるとすると、

CP=(r cos θ,r sin θ)

と、三角関数を使って表せます。

まあ、三角関数の定義そのもの、といった感じです。

また、円の中心 C の座標が

C=(xc,yc)

なので、原点から見た円周上の点 P の座標は、原点→C→Pと求められて、

(1)
P = C + CP = ( xc + r cos θ, yc + r sin θ )

となります。

(1)で円を描く場合は、 θ を 0 ~ 2π まで変化させつつ(角度をラジアンで表す場合。度なら0°~360°)、線を引いていきます。

もう一つの円の表し方

円にはもう一つの表し方があります。

中心がC(xc,yc) 、半径の長さが r の円円周上の点Pの座標を(x,y) とすると、

(x-xc)^2+(y-yc)^2=r^2

という式が成り立ちます。

この式を変形すると、

(2)
y = yc ± sqrt( r^2 - ( x - xc )^2 )

となります。

(2)で描く場合、 x の範囲は xc-r ~ xc+r となるので(この範囲を超えると、yは実数では求まらない、つまりそれは円の範囲外ということ)、 x を xc-r から xc+r まで変化させつつ、±の + の場合と - の場合それぞれに線を引いていけば、円を描くことができます。

3.2. (擬似)円を描く

前項の式を基に、円を描くプログラムを作っていきます。

3.2.1. とりあえず点を打つ

まずは、原点を中心とした半径1の円(=単位円(unit circle))の円周上に、(1)においてθ=0°,30°,60,°90°とした時の4つの点を打つことを考えます。

リスト1. circle0.bas
!
! (擬似)円を描く
!      Copyright(c) カイン Cain 2006
!
SET WINDOW -1.5, 1.5, -1.5, 1.5
DRAW grid
!
PLOT POINTS : COS( 0 ), SIN( 0 )
PLOT POINTS : COS( PI / 6 ), SIN( PI / 6 )
PLOT POINTS : COS( PI / 6 * 2 ), SIN( PI / 6 * 2 )
PLOT POINTS : COS( PI / 6 * 3 ), SIN( PI / 6 * 3 )
END

リスト1を(仮称)十進BASIC上で入力するかコピーするかして実行すると、次のような結果が得られます。

期待した通り、4つの点が打たれています。

このプログラムを、頭から見ていきます。

BASICのプログラムは、行(line単位で、最初の行から順番に実行されます。
JIS Full BASICの場合、基本的に1行1命令です。
コメント
! から行末まではコメント(commentとなり、プログラムの実行には影響を与えません。
プログラムを人が読む手助けとして記述するだけです。
コメントを行の途中から始めることもできます。
大文字・小文字
BASICでは、大文字・小文字は区別されません(全角・半角は区別されます)。
ただし、初期設定では、機能語((仮称)十進BASIC自体で使う単語)は自動的に大文字にされます。
グラフィックスウィンドウの設定
SET WINDOW -1.5, 1.5, -1.5, 1.5
で、グラフィックスウィンドウを設定します。
左端のx座標、右端のx座標、下端のy座標、上端のy座標の順に指定します。
リスト1では、x=-1.5~1.5、y=-1.5~1.5の範囲の座標系が表示されます。
グリッド
DRAW grid
で、グリッド(grid;目盛り線)を表示します。
つまりは、グラフィックウィンドウを方眼紙にするわけですね。
(仮称)十進BASIC独自の拡張ですが、便利なので、今回は全てのプログラムで表示しています。
点を打つ
PLOT POINTS : x座標, y座標
で、指定された座標 (x座標, y座標) に点を打ちます
英単語の「plot」は、グラフ等の図を描くことを示す動詞です。
リスト1では、この命令を4つ並べることで、4つの点を打っています。
点と言っても、JIS Full BASICでは記号(標準では*)が打たれます。
例えば PLOT POINTS での座標の指定のように、プログラム中で数値を指定する場所では、数値を直接指定する代わりに、式(expressionで指定することができます。
式というのはつまり、計算をするための「数式」で、プログラムを実行するとその場で計算され、その計算結果が、 PLOT POINTS なら点を打つ座標として使われます。
は、数学の数式に近い形で、数値、演算子(後述)、関数等を組み合わせて作ります。
円周率
PI は、円周率πです。
もちろん、本物の円周率は無限に続いてコンピュータ上では表現しきれないので、近似値です。
三角関数
SINCOSは、数学の三角関数sin、cosと同じです。
ただし、
COS( 角度 )
のように、角度の指定を必ず括弧でくくります。
括弧でくくるのは、他の関数を使う時でも同様です。
角度はラジアンで指定します。
ラジアン
ラジアン(radianは、角度0°~360°を、0~2πで表す単位です。
ラジアンを使うと、例えば円弧の長さを rθ というすっきりした式で表すことができます。
三角関数に0~2πを超える値を与えた場合は、それを2πで割った余りが使われます。
加減乗除
加減乗除演算子(operatorは、それぞれ
  • + : 足し算
  • - : 引き算
  • * : 掛け算
  • / : 割り算
となります。
日本語で「演算子」なんて言うと堅苦しいですが、英語だと「operator」=操作するもの、日本語よりずっと単純な単語です。
数学と同じように、掛け算・割り算は足し算・引き算より先に計算されます。
角度を求める
ラジアンではπ=180°なので、π/6=30°となります。
これを使って、
PLOT POINTS : COS( 0 ), SIN( 0 )
PLOT POINTS : COS( PI / 6 ), SIN( PI / 6 )
PLOT POINTS : COS( PI / 6 * 2 ), SIN( PI / 6 * 2 )
PLOT POINTS : COS( PI / 6 * 3 ), SIN( PI / 6 * 3 )
として、つまりは
  • 30°をπ/6
  • 60°をπ/6×2
  • 90°をπ/6×3
として求めています。
終了
プログラムの末尾には END を付けます。

こうして、円周上の4つの点が打てました。

(仮称)十進BASIC上でのプログラムの保存

(仮称)十進BASIC上での「保存」は、一般的なWindowsアプリケーションとはちょっと違ったやり方になっています。

  • ディスクアイコン
    普通、このアイコンの意味するところは「上書き保存」ですが、(仮称)十進BASICでは「名前をつけて保存」になります。
  • Ctrl+S
    一般的なWindowsアプリケーションでは、Ctrl+Sに「上書き保存」が割り当てられていますが、(仮称)十進BASICでは割り当てられていません。

というわけで、「上書き保存」したい時は、メニューから [ファイル]-[上書き保存] とする必要があります。

3.2.2. 繰り返し

円を描くにはもっと点を打たないといけないわけですが、打つ点の数だけ PLOT POINTS を並べていては、点の数が増えたら大変になります。

そこで、繰り返し(=ループ(loop)を使って簡潔に記述します。

リスト2. circle1.bas

FOR i=0 TO 11
   PLOT POINTS : COS( PI / 6 * i ), SIN( PI / 6 * i )
NEXT i
END

リスト2では、主にリスト1からの変更箇所を表示しています。

4つの PLOT POINTS 文を、 FORNEXT i で置き換えます。

このプログラムを実行すると、次のように12個の点が打たれます。

変数
変数(variable、variableを直訳すれば「変化し得るもの」。
変数は、名前が付けられた「データの記憶場所」であり、プログラムの実行中、必要に応じて書き換えられ、利用されます。
リスト2では、 i と名付けられた変数が使われています。
通常、変数に入れられるのは数値データで、(仮称)十進BASICでは、整数部・小数部合わせて十進数15桁(オプションで変更可能)の数値を変数に入れることができます。
FOR
FORは、繰り返しのための構文で、
FOR 変数名=初めの値 TO 終わりの値
   繰り返す処理
NEXT 変数名
という形で使います。
処理の流れとしては、まず変数「初めの値」が入れられて「繰り返す処理」が行われ、次に変数1が加えられてまた「繰り返す処理」、が行われ…それが、変数「終わりの値」になるところまで繰り返されます。
リスト2の場合は、次のようになります。
  1. i=0で PLOT POINTS される。
    つまり、 ( COS(π/6×0), SIN(π/6×0) ) = ( COS(0°), SIN(0°) ) に点が打たれる。
  2. i=1で PLOT POINTS される。
    つまり、 ( COS(π/6×1), SIN(π/6×1) ) = ( COS(30°), SIN(30°) ) に点が打たれる。
  3. i=2で PLOT POINTS される。
    つまり、 ( COS(π/6×2), SIN(π/6×2) ) = ( COS(60°), SIN(60°) ) に点が打たれる。
  4. i=11で PLOT POINTS される。
    つまり、 ( COS(π/6×11), SIN(π/6×11) ) = ( COS(330°), SIN(330°) ) に点が打たれる。
と、処理が12回繰り返され、12個の点が打たれます。
インデント
リスト2では、 PLOT POINTS 文の前に空白を入れることで、プログラムの構造を分かりやすくしています。
このような空白をインデント(indent;字下げ)と言います。
読みやすくするだけで、プログラムの実行自体には影響しません。

こうして、ループでプログラムを簡潔にすることができました。

ループにしてしまえば、打つ点の数を倍にすることも簡単にできます。

3.2.3. 変数

繰り返し回数を柔軟に変更できるように、変数で指定することを考えます。

リスト3. circle2.bas

LET div = 36
!
FOR t=0 TO 2 * PI STEP 2 * PI / div
   PLOT POINTS : COS( t ), SIN( t )
NEXT t
END

リスト3では、主にリスト2からの変更箇所を表示しています。

リスト2FORNEXT を置き換えます。

実行すると、次のように36個の点が打たれます。

LET
LET 変数名 = 
で、「変数」に「式」を計算して得られた「値」を代入(assign;割り当てる)します。
リスト3では、変数 div に36という数値を入れて、円周を36分割して描くことを意図しています。
この36を書き換えるだけで、50分割にでも100分割にでもできます。
STEP
FOR 文では、何も指定されなければ変数は1ずつ増えますが、
FOR 変数名=初めの値 TO 終わりの値 STEP 一度に増える値
   繰り返す処理
NEXT 変数名
STEP 句を付け加えれば、1度繰り返すごとに変数の値を「一度に増える値」ずつ増やすことができます。
リスト3では、繰り返しのたびに変数 t を 2π/36 ずつ増やしているので、次のようになります。
なお、変数 t は、図1角度θに対応します。
  1. t=0=0°で、 ( COS(0°), SIN(0°) ) に点が打たれる。
  2. t=2π/36=10°で、 ( COS(10°), SIN(10°) ) に点が打たれる。
  3. t=2π/36×2=20°で、 ( COS(20°), SIN(20°) ) に点が打たれる。
  4. t=2π/36×35=350°で、 ( COS(350°), SIN(350°) ) に点が打たれる。
  5. t=2π/36×36=360°で、 ( COS(360°), SIN(360°) ) に点が打たれる(0°の点と重なる)。
と、37個の点(最初と最後が重なるので実際には36個)の点が打たれます。
ただし、誤差によってこの通りにならない可能性もありますが、それはまたいずれ述べます。
STEP 句でマイナスの値を指定すれば、変数の値を繰り返すごとに「減らす」こともできます。

コンピュータの主な機能は、データを「処理する」ことと「記憶する」ことなわけで、変数を使ってデータを記憶することでぐっとプログラムらしくなります。

3.2.4. 線を引く

ここまでは点を打ってきましたが、点を打つ代わりに直線を引いて、正多角形を描きます。

リスト4. circle3.bas

LET prev_x = 1
LET prev_y = 0
FOR t=0 TO 2 * PI STEP 2 * PI / div
   PLOT LINES : prev_x, prev_y; COS( t ), SIN( t )
   LET prev_x = COS( t )
   LET prev_y = SIN( t )
NEXT t
END

リスト4では、主にリスト3からの変更箇所を表示しています。

リスト3FORNEXT を置き換えます。

実行すると、次のように正36角形が描かれます。

見ての通り、パッと見、円に見えます。

これが(擬似)円の「擬似」の意味です。

つまり、正多角形の角数を多くすることで、擬似的に円を描いています。

見方によっては、「これでは円を描いたことにならない」とも言えます。例えば、計算に関する論文でも書こうとするなら、これでは不十分かもしれません。

しかし今回は、そんな厳密さはいりません。それっぽく見えれば十分です。

であればこの場合、簡単に実装できるこの方法が、最適な方法であると言えます。

大事なのは、「目的に応じた方法」です。

線を引く
PLOT LINES : 始点のx座標, 始点のy座標; 終点のx座標, 終点のy座標
とすることで、始点から終点直線を引けます。
セミコロン(;)でつなぐことで、もっと線をつなげることもできます。
一つ前の座標
リスト4では、変数 prev_xprev_y で、一つ前の点の座標を記憶して、線を引く時に>始点の座標として使っています(prevはpreviousの略)。

やっとらしくなりました。

3.2.5. 中心の座標と半径を指定する

(擬似)円の中心の座標と半径を指定することを考えます。

また、 prev_xprev_y を使わない方法も示します。

リスト5. circle4.bas

SET WINDOW -1, 5, -4, 2
DRAW grid
!
LET div = 36
LET xc = 2
LET yc = -1
LET r = 2
!
FOR t=0 TO 2 * PI STEP 2 * PI / div
   PLOT LINES : xc + r * COS( t ), yc + r * SIN( t );
NEXT t
END

リスト5では、リスト4からの変更箇所を中心に表示しています。

実行すると、次のように中心の座標が(2,-1)、半径2の円が描かれます。

中心の座標と半径
中心のx座標を xc 、y座標を yc 、半径を r として指定し、(1)に基づいて座標を求めています。
指定した中心(2,-1)、半径2に合わせて、 SET WINDOW も、xを-1~5、yを-4~2の範囲に書き換えています。
線を続けて引く
PLOT LINES : x座標, y座標;
末尾をセミコロン( ; )で終わらせると、次に PLOT LINES 文が実行された時に、前の PLOT LINES 文で描かれた線に続けることができます。
例えば、
PLOT LINES : 0, 0;
PLOT LINES : 1, 1
とすれば、原点から(1,1)へ斜めの線が引かれます。
だったら、最初から prev_xprev_y は要らなかったのでは?という感じですが、例えばループの中で他の図形を描いたりする場合、prev_xprev_y を使う方法が必要になります。
いずれ、そういうのが出てきます。

これで、任意の円を描けるようになりました。

3.3. (擬似)円描画ルーチン

3.3.1. サブルーチン化

(擬似)円の描画プログラムをサブルーチン(subroutine(routineは決まりきった手順等の意味)にすることを考えます。

サブルーチンとは、プログラムの一部を取り出して独立させたものです。

手続き(procedureも同じような意味です。

サブルーチンの形にすることには、次のようなメリットがあります。

  • サブルーチンの呼び出しは1行でできるので、同じプログラムを繰り返し何度も記述するより短く記述できる。
  • 独立しているため、他のプログラムで使い回しやすい。
  • プログラムの構造が分かりやすくなる。
リスト6. circle5.bas
!
! (擬似)円を描く
!      Copyright(c) カイン Cain 2006
!
DECLARE EXTERNAL PICTURE circle
SET WINDOW -1, 5, -4, 2
DRAW grid
!
DRAW circle( 2, -1, 2 )
END
!
! (擬似)円描画ルーチン
!
EXTERNAL PICTURE circle( xc, yc, r )
   LET div = 90
   !
   FOR t=0 TO 2 * PI STEP 2 * PI / div
      PLOT LINES : xc + r * COS( t ), yc + r * SIN( t );
   NEXT t
END PICTURE

リスト6の実行結果自体は、リスト5とほぼ同じです。

div=90 になっているので、若干滑らかかもしれませんけどね。

外部絵定義
JIS Full BASICで言う外部絵定義とは、まず初めに
DECLARE EXTERNAL PICTURE 絵の名前
宣言し、 END 文より後に
EXTERNAL PICTURE 絵の名前( 引数1,  引数2,  )
   プログラム
END PICTURE
サブルーチン本体を定義したものです。
あえて「宣言」をする主な目的は、言語自体に組み込まれている単語と区別しやすいようにするためです。
長いプログラムを先頭から読んでいって、「ん?この circle は言語自体に組み込まれてるのかな?」と、余分な疑問を持つことがなくなります。
実際のところ、(仮称)十進BASIC自体に実は、 circle という絵が定義されていたりします。
絵定義の呼び出し
絵定義の呼び出しは、
DRAW 絵の名前( 引数1,  引数2,  )
と、 DRAW 文を使って行います。
引数によって呼び出し元からサブルーチンにデータを渡しますが、引数を持たない絵定義であれば、括弧は要りません。
引数
引数ひきすうargumentは、サブルーチンの呼び出し元からサブルーチンにデータを受け渡すための変数です。
DRAW circle( 2, -1, 2 )
と呼び出すことで、
EXTERNAL PICTURE circle( xc, yc, r )
と定義されたサブルーチン側では、 xc に2、 yc に-1、 r に2が代入された上でプログラムが実行されます。
パラメータ(parameterも、だいたい同じ意味です。
呼び出し側で、例えば DRAW circle(a,b,c) などと引数として変数を渡すと、サブルーチン側ではその変数がそのまま使われます。つまり、サブルーチン側で引数を書き換えれば、呼び出し元の変数までも書き換えることになります。
なので通常は、サブルーチン内で引数を書き換えない方がいいでしょう。
もちろん、サブルーチン内で書き換えられることを意図することもあり、この場合、そのパラメータは「出力パラメータ」と呼ばれます。
ローカル変数
リスト6の、 circle ルーチン内の変数 div は、メインプログラム( END から前の部分)から使うことはできません
メインプログラム中で同じ div という名前の変数を使ったとしても、それは circle ルーチン内の変数 div とは別物になります。
このように、そのルーチン内だけで有効な変数を ローカル変数(local variable と言います。
外部手続きEXTERNAL をつけたものとメインプログラム;メインプログラムも一つのサブルーチンと解釈)で使われる変数は、基本的にローカル変数になります。
これによって、ルーチン内の処理はその他のプログラムの影響を受けないので、他のプログラムにそのままコピーして使い回すことができます。
DECLARE EXTERNAL PICTURE routine1

LET a = 0 ! routine1内のaとは別の変数

DRAW routine1

END
EXTERNAL PICTURE routine1
   
   LET a = 20 ! メインプログラムのaとは別の変数
   
END PICTURE

JIS Full BASICでは、絵定義を呼び出す時に、引数の代わりに変換関数を使うこともできるのですが、今回は変換関数については扱いません。

3.3.2. 中心の座標と半径を入力させる

パラメータを変えようと思ったときに、一々プログラムを書き換えるというのは、スマートではありません。

その代わりに、ユーザーに入力させることを考えます。

リスト7. circle6.bas

DECLARE EXTERNAL PICTURE circle
!
INPUT xc, yc, r
LET r = ABS( r ) ! 絶対値
!
SET WINDOW xc - r - 1, xc + r + 1, yc - r - 1, yc + r + 1
DRAW grid
!
DRAW circle( xc, yc, r )
END

リスト7では、主にリスト6からの変更箇所を表示しています。

実行すると、 xcycr入力を求められます。

そこで、 xcycrカンマ( , )で区切って入力すれば、グラフィックウィンドウの座標系も適切に設定されて、円が描かれます。

例えば、 3,1,5 と入力した結果は、次のようになります。

パラメータの入力を省略することはできません。正しく入力しないと(空欄だったりパラメータの数が合ってなかったり)、エラーが表示されて何度でも入力し直しになります。

INPUT
INPUT 変数1,変数2,
とすることで、ユーザーに各変数の値を入力させることができます。
入力は、各値の間をカンマで区切り、変数の数入力された値の数同じでなければなりません。
正しく入力しなければ、エラーが出てやり直しになります。
絶対値
ABS(r) は、 r絶対値(absolute valueを返す関数です。数学では |r| と書きます。
リスト7で半径 r にマイナスの値を入力すると、 SET WINDOW が適切にできないため、半径 r の絶対値を取っています。

これで、ユーザーとの対話ができるようになりました。

3.3.3. 入力を省略できるようにする

毎回入力しなければならないのではなく、入力を省略すればデフォルト値(default value;特に指定しない場合に使われる値)が使われるようにすることを考えます。

リスト8. circle7.bas

LET xc = 0
LET yc = 0
LET r = 1
WHEN EXCEPTION IN
   INPUT xc, yc, r
USE
END WHEN

リスト8では、主にリスト7からの変更箇所を表示しています。

リスト7INPUT 文を、リスト8で置き換えます。

リスト8では、パラメータを完全に入力しなくてもエラーは出ず、入力しなかった分にはデフォルト値 xc=0yc=0r=1 で円が描かれます。

例外
例外(exceptionというのは、つまりはエラー(errorのことです。
もうちょっと言えば、「聞き捨てならないエラー」といったところでしょうか。
プログラムは基本的に、前から順々に実行されるわけですが、「このまますんなり次の命令に行かせるわけにはいかない!」という時に、例外が発生します。
例外処理の構文
例外が発生したら、すんなり次の命令には行けません。
「例外が発生したらどうするか」を、プログラムする必要があります。
その構文は、次のようになります。
WHEN EXCEPTION IN
   プログラム
USE
   例外が発生したときの処理
END WHEN
WHEN EXCEPTION IN 以下のプログラム中で例外が発生したら、 USE 以降の「例外が発生したときの処理」が為されます。
例外が発生しなければ、 USEEND WHEN は無視されて、その次へと進んでいきます。
INPUT 文の例外
LET xc = 0
LET yc = 0
LET r = 1
WHEN EXCEPTION IN
   INPUT xc, yc, r
USE
END WHEN
INPUT 文で、入力が完全にはされなかった場合、リスト7のように特に何もしなければ、完全な入力がされるまで先へ進みません。
しかし、リスト8のように WHEN EXCEPTION IN例外を受け止めれば、たとえ入力が不完全でも、そのまま先へ進みます(今回は、 USEEND WHEN 中で特に何もしていません)。
リスト8の場合、例えば入力が空なら、その前で設定している xc=0yc=0r=1のまま処理が進みます。
また、例えば入力が 5,6 なら、 xc=5yc=6 という代入はされますが、 r1 のままで処理が進みます。

以上のように、入力が不完全ならデフォルト値を使う、という処理が実現できました。

3.3.4. 円弧を描いてみる

ついでなので、円弧も描いてみます。

リスト9. circle8.bas
!
! (擬似)円を描く
!      Copyright(c) カイン Cain 2006
!
DECLARE EXTERNAL PICTURE arc
!
LET xc = 0
LET yc = 0
LET r = 1
LET t1 = 0
LET t2 = 360
WHEN EXCEPTION IN
   INPUT xc, yc, r
USE
END WHEN
LET r = ABS( r ) ! 絶対値
WHEN EXCEPTION IN
   INPUT t1, t2
USE
END WHEN
LET t1 = t1 * PI / 180 ! 度→ラジアン
LET t2 = t2 * PI / 180
!
SET WINDOW xc - r - 1, xc + r + 1, yc - r - 1, yc + r + 1
DRAW grid
!
DRAW arc( xc, yc, r, t1, t2 )
END
!
! (擬似)円描画ルーチン
!
EXTERNAL PICTURE arc( xc, yc, r , t1, t2 )
   LET div = 360
   !
   FOR t=t1 TO t2 STEP 2 * PI / div
      PLOT LINES : xc + r * COS( t ), yc + r * SIN( t );
   NEXT t
END PICTURE

リスト9を実行すると、xc,yc,r の入力に続いて、 t1,t2 の入力も求めら得ます。

ここでは、 t1 に円弧の開始角t2 に円弧の終了角を 単位で入力します。

角度の指定の仕方は、図1のθに準じます。

例えば、 xc,yc,r はデフォルト値のまま、 t1,t245,180 と入力すると、次のような円弧が描かれます。

LET t1=t1*PI/180 で、単位を度からラジアンに変換
t1 へ代入する値を計算するのに、 t1 自体の持っている値を使うことができます。
この命令文は、
  1. t1*PI/180 を計算する。
  2. 計算結果を t1 に代入する。
という2段階で実行されるので、こういうことができます。

今回はここまで。

次回は、リスト9の(擬似)円弧描画ルーチンではなく、リスト6(擬似)円描画ルーチンを使い回します。

たとえば…

リスト8を、(2)に基づいて描くように書き換えたら、どうなるでしょうか?

ただし、ある数値 x のルートを求める関数は、 SQR(x) です。

『スピログラフ』 第1回 円 (続く…)
【まとめ】
  1. ファイル庫/Spiro/figure/fig-circle.odg(OpenOffice.org Draw)にて出力。
参考文献
[1]. (仮称)十進BASIC オンラインヘルプ
inserted by FC2 system