※IchigoJamはjig.jpの登録商標です
ボロノイ図
ボロノイ図とは、空間内にいくつかの点を配置し、空間内をそこが配置した中のどの点に一番近いかで区分けした図である。
今回は、これを二次元平面上で行う。
IchigoJam での描画
まずは、IchigoJam 単独で、領域を文字で表現して描画してみた。
プログラム
10 ' ボロノイ ズ
20 W=32:H=24:N=8
30 IF VER()>=13208 W=POS(3):H=POS(4)
40 I=0
50 LET[I*2],RND(W),RND(H)
60 A=1:IF I>0 FOR J=0 TO I-1:A=A AND ([I*2]<>[J*2] OR [I*2+1]<>[J*2+1]):NEXT
70 I=I+A:IF I<N GOTO 50
80 CLS
90 FOR Y=H-1 TO 0 STEP -1
100 SCROLL DOWN:LOCATE 0,0
110 FOR X=0 TO W-1
120 FOR K=0 TO N-1
130 U=[K*2]-X:V=[K*2+1]-Y:S=U*U+V*V
140 IF K=0 OR S<C B=K:C=S
150 NEXT
160 ?CHR$(#61+B-#20*(C=0));
170 NEXT:NEXT
180 IF INKEY()=0 WAIT 1:GOTO 180 ELSE GOTO 40
実行結果例
配置した点を A~Hで、一番近いのがそれらの点である部分をそれぞれ a~h で表している。
解説
画面の大きさと点の数の用意
10 ' ボロノイ ズ
20 W=32:H=24:N=8
30 IF VER()>=13208 W=POS(3):H=POS(4)
画面の幅 W、画面の高さ H、点の数 N を用意する。
画面の大きさは一旦決め打ちし、対応バージョンでは POS() を用いて取得する。
点の配置
40 I=0
50 LET[I*2],RND(W),RND(H)
60 A=1:IF I>0 FOR J=0 TO I-1:A=A AND ([I*2]<>[J*2] OR [I*2+1]<>[J*2+1]):NEXT
70 I=I+A:IF I<N GOTO 50
点の座標をランダムに決め、配列に格納する。
その後、格納した座標が既存の点と重なっていないかを確認する。
重なる点が無ければ、カウンタ I を増やす。
これを、I が設定した点の数 N になるまで繰り返す。
領域の描画
80 CLS
90 FOR Y=H-1 TO 0 STEP -1
100 SCROLL DOWN:LOCATE 0,0
110 FOR X=0 TO W-1
各行ごとに、左から右に描画を行う。
一番右下に文字を PRINT すると、勝手にスクロールされてしまう。
そこで、これを避けるため、最終的に一番下になる行から順に、一番上の行に出力し、SCROLL で下に送っていく。
120 FOR K=0 TO N-1
130 U=[K*2]-X:V=[K*2+1]-Y:S=U*U+V*V
140 IF K=0 OR S<C B=K:C=S
150 NEXT
それぞれの点とのユークリッド距離の2乗を計算し、一番近い点を探す。
160 ?CHR$(#61+B-#20*(C=0));
170 NEXT:NEXT
一番近い点の情報を描画する。
一番近い点との距離が 0 であれば、それはその点そのものなので、描画する文字を変える。
180 IF INKEY()=0 WAIT 1:GOTO 180 ELSE GOTO 40
描画が完了したら、キーが押されるまで待機する。
キーが押されたら、次の描画を開始する。
PanCake での描画
IchigoJam 単体でもボロノイ図の描画はできたが、文字による表現では見にくい気がした。
そこで、PanCake を用い、色で描画できるようにしてみた。
プログラム
10 ' ボロノイ ズ (PanCake)
20 W=80:H=45:N=8
30 I=0
40 LET[I*2],RND(W),RND(H)
50 A=1:IF I>0 FOR J=0 TO I-1:A=A AND ([I*2]<>[J*2] OR [I*2+1]<>[J*2+1]):NEXT
60 I=I+A:IF I<N GOTO 40
70 ?CHR$(10);"PANCAKE CLEAR 00"
80 FOR P=0 TO H-1 STEP 8
90 FOR Q=0 TO W-1 STEP 8
100 ?"PANCAKE STAMP ";HEX$(Q,2);" ";HEX$(P,2);" 00 ";
110 FOR Y=P TO P+7
120 FOR X=Q TO Q+7
130 FOR K=0 TO N-1
140 U=[K*2]-X:V=[K*2+1]-Y:S=U*U+V*V
150 IF K=0 OR S<C B=K:C=S
160 NEXT
170 ?HEX$(B*2+(C>0),1);
180 NEXT:NEXT
190 ?CHR$(10);
200 NEXT:NEXT
210 IF INKEY()=0 WAIT 1:GOTO 210 ELSE GOTO 30
実行結果例
やはり、今回の文字での表現よりも色で表現したほうが見やすく、美しい。
解説
IchigoJam 単体版とだいたいの処理の流れは同じなので、全体の細かい解説は省略する。
PanCake の画面サイズは固定で、取得する手段も無さそうなので、画面サイズは決め打ちのみとした。
PanCake では、8×8のブロックの各ピクセルの色を指定して描画を行う命令 STAMP があるので、これを用いて効率よく描画を行えるよう、8×8のブロックごとに計算を行い、描画命令を出力するようにした。
STAMP では透明色を指定させられるので、最初にこの透明色で画面を単色クリアすることで、描画されなくても正しい表示になるようにした。
おわりに
IchigoJam で、ボロノイ図を描くことができた。
さらに PanCake と組み合わせることで、色を用いた見やすい表示ができた。
しかし、今回は1ピクセルごとにそれぞれの点との距離を総当りで調べるアルゴリズムを用いたため、1枚描画するのにそこそこ時間がかかってしまった。
改良の余地はありそうだ。





