18) 円を描こう
 何だそりゃ、と気の抜けるタイトルですが、真面目に考えてみることにしましょう。
実は、NS Basicには、円を描くコマンドが用意されていません。DrawRectangleコマンドの引数で、角を丸くすることができますが、円を描くためのものではなさそうです。
円を描いたビットマップを用意するのも1つの方法です。円そのものを描く時はそれでも良いでしょうが、任意の円弧を描きたい場合には困ります。
そこで、今回は三角関数のSINとCOSを使って円を描く方法を紹介します。

半径が1の円を単位円と言いますが、この円の円周上にある点Pは、(cosθ, sinθ)で表すことができます。
これは、高校程度の数学で出てくるのでしょうか?要するに図にすると、こんなイメージです。

   

ちなみに、この単位円の円周の長さは、2πr、rは半径で、単位円ですからr=1ですね。つまり、円周は2πになります。
これがラジアンという角度の定義になりますが、慣れ親しんでいる「度」だと1周が360度、これは単に等分しただけですから、ラジアンの方が身元がしっかりしているわけです。わかりにくいですけどね。
さて、数学のお話はこれくらいにして、半径Rの円を描いてみることにしましょう。
例えば、次のコードを適当なボタンに貼りつけます。
    Dim Pai as Single
    Dim i as Single
    Dim X as Single
    Dim Y as Single

    Pai=3.14159265

    For i=0 to 2*Pai Step Pai/20
        X=50 * cos(i)
        Y=50 * sin(i)

        DrawLine 80,80,80+X,80+Y
    Next
とすると、(80,80)の位置を中心に、半径50の花火状のモノが描かれます。

   

要するに、中心を(X0,Y0)として、半径Rの円周上にある点の座標は(X0+R*cosθ,Y0+R*sinθ)で表せるのですが、これを利用して1周分(2π)をFor 〜 Nextでループさせたものが、このサンプルです。
ちなみに、MathLibにある関数sin()やcos()は単位がラジアンですから、ラジアンで指定する必要があります。

さて、これを円にしようと思うと、2つの点を結ぶ必要がありますので、ちょっと強引ですが、次のような方法を採ってみました。
    
    Dim Pai as Single
    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    Pai=3.14159265

    For i=0 to 2*Pai STEP Pai/20
        
        X1=50 * cos(i)
        Y1=50 * sin(i)
        X2=50 * cos(i+Pai/20)
        Y2=50 * sin(i+Pai/20)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next
    

ほら、今度は、円になったでしょう?描くスピードが見えるくらい鈍いですが、任意の円です。
でも、単位がラジアンだとやっぱり使い難いですよね、そこで、

    360度=2π(ラジアン)

であることを利用して、

    1度=π÷180

という定数を考えます。これで、任意の角度にこの定数をかければ、ラジアンへの変換できます。
    Dim Pai as Single
    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    Pai=3.14159265/180

    For i=0 to 360 STEP 5
        
        X1=50 * cos(i*Pai)
        Y1=50 * sin(i*Pai)
        X2=50 * cos((i+5)*Pai)
        Y2=50 * sin((i+5)*Pai)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next
これが、同じような結果になりますね。いかがですか?
もちろん、
    Dim Pai as Single
    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    Pai=3.14159265/180

    For i=0 to 270 STEP 5
        
        X1=70 * cos(i*Pai)
        Y1=50 * sin(i*Pai)
        X2=70 * cos((i+5)*Pai)
        Y2=50 * sin((i+5)*Pai)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next
こうすることで、任意の角度の楕円も描くことができます。

    


さて、今まで紹介した方法は、実は、比較的古典的な方法で、円を描く命令のなかった頃は、普通に使われていました。
なので、知っている人には目新しい方法でも何でもありません。
ただし、これをNS Basicで実行するには、多少の問題があります。それは、MathLib.prcが必要である、という点です。
このライブラリは、別にNS Basic用ではなく、数値計算用の汎用ライブラリですから、既にインストールされている事も考えられますが、全部のデバイスに入っているとは限りません。
その上、単に円を描くだけのために、50KBものライブラリをわざわざ入れるのは、抵抗があるでしょう。
そこで、NS Basic Ver.2.11で追加された「リソース」という機能を使ってもう少し賢くしてみました。

考え方は簡単です。単純に1度ごとのSINとCOSの値をデータベース化することを考えてみました。
整数だとお話になりませんから、一応、単精度の実数(Single)にしてみます。これをデータベースに配列データとして保存してみれば良いわけですね。
で、結果を先に言いますと、要素数は360個×2で720個になりますので、要素数が多いように見えても、それほど負荷にはなりませんでした。実用上のスピードは確保できるようです。
サイズも、MathLibの50KBに比べて、こちらは 3KB弱ですから、許容範囲内でしょう。
ということで、まず、そのデータベースを、ここからダウンロードして下さい。

     amisclib.zip

クリエータIDは「Test」ですが、A.N.Lなどで適当に変更して使って頂いて構いません。
具体的な使い方です。
ダウンロードしたAmiSCLib.prcをIDEのリソースに追加します。今回は、IDが1005であるとします。
次に、スタートアップに次ようなコードを入れます。
    Dim Db as Database
    Dim Res as Integer
    
    Global ss(360) as Single
    Global cs(360) as Single

    res=dbOpen(Db,"AmiSCLib",0)
    If res<>0 Or res<>3 Then
        res = DbCreateDatabaseFromResource("DBIM",1005)
        res=dbOpen(Db,"AmiSCLib",0)
    End If
    
    res=dbread(Db,"sin",ss)
    res=dbread(Db,"cos",cs)

    res=dbClose(Db)
これで、SINがSS()、COSがCS()というグローバル変数に代入されます。
AmiSCLib.prcのクリエータIDを自分のアプリと同じにしておけば、アンインストール時に、一緒に削除されますので、便利です。

実際のSIN、COSの値の参照方法ですが、これは簡単です。スタートアップで読み込んだSS()、CS()という変数に、0〜359度に対応する SIN、COSの値が入っていますから、直接その数値を指定します。
注意する点が2つあります。
1つ目は、NS Basicの配列変数が A(0)からではなく、A(1)からという点です。だから実際は、SS(360)は、SS(1)〜SS(360)になっています。従って、自分で欲しい角度が X だとすれば、実際の値は SS(X+1) と1加えた値で指定する必要があります。
もう1つは、配列としては、SS(1)〜SS(360)しか用意されていない点です。沿え字が 1〜360の範囲外ならないように注意する必要があります。
これら2点を注意して、先ほどのサンプルを書きなおしてみると、こんな感じになりますね。
    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    For i=0 to 355 STEP 5
        
        X1=50 * cs(i+1)
        Y1=50 * ss(i+1)
        X2=50 * cs(i+5)
        Y2=50 * ss(i+5)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next
コードがシンプルになる上に、速度も気になるほど低下しません。
ライブラリの方は、ご自由にお使い下さい。単なる、SIN、COSの値が入ってるだけなので・・・
ちなみに、A.N.LでクリエータIDを変更したら、1度HotSyncして下さい。母艦のBackupフォルダにAmiSCLib.prcがコピーされますので、これをNS BasicのLibフォルダにでもコピーすれば、簡単にリソースに組み込むことができます。

そんな訳で「円を描こう」を手短にお送りしました。円を描く動作を実装する時の参考になれば、幸いです。
ちなみに、EDAさん用に作成した、EDA19_2というアプリ(私の日記、2002/05/09にあります)は、これを使ったアプリです。