


円を隙間なく並べるパターンを作成します。
天地左右対象になるようにパターンを配置します。
行に並んだ円に接するために三角関数でy座標を計算します。
その計算結果は実数になるため、天地を対称にするための計算も実数にする必要があります。
余りを得るためのmodオペレータは整数しか使用できないので、実数の余りを得るmodプロシージャを作りました。
割り算は引き算の繰り返しなので、引き算をループさせます。
余りが割る方の数字より小さくなったらループを抜けるようにします。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | %!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 240 240 %%Title: 円と円の外接 % =========== 実数版 mod =============== /mod_real { % 実数版 modプロシージャ /waru exch def % 割る方の数値 /num exch def % 割られる方の数値 % gext:余り { /gext num waru sub def % 割られる方から割る方を引いてgext(余り)に入れる gext waru le { exit } if % 余りが割る方より小さくなったら終了 /num gext def % 割られる方に余りの数字を入れる } loop /ky gext def % 余りをkyに入れる } def /r 24 def % 円の半径(整数のみ) /d r 2 mul def % 円の直径 /sd d 30 cos mul def % 下段の円とのy方向の距離 /w0 120 def % 横幅の半分 /h0 120 def % 縦幅の半分 /w w0 r add def % 横幅にパターンが見切れないように円の半径を足す /h h0 sd add def % 縦の高さに下段の円との距離を足す /kx w0 d mod def % 横幅を円の直径で割って、余りをkxに入れる h0 sd mod_real % 縦の高さは下段の円と距離で割る <pre>/sw -1 def 1 setlinewidth newpath 0 0 240 240 rectstroke % 黒枠 120 120 translate % 座標の原点を中央に移動 % =========== メイン =============== newpath % パスの初期化 h neg sd h { % -hからhまでsdづつ増分し{ }内を繰り返す /dy exch def % 制御変数をdy(縦移動量)に入れる w neg d w kx sub { % -wからw-kxまでdづつ増分し{ }内を繰り返す /dx exch def % 制御変数をdx(横移動量)に入れる /x dx kx add def /y dy ky add def % x=dx+kx y=dy+ky sw 1 ne { /x x r add def } if % swが1でないならx=x+r x y r 0 360 arc stroke % (x,y)に半径rの円を描く } for /sw sw neg def % swの符号を反転する } for |
3色の円を交互に並べます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 %!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 240 240
%%Title: 円と円の外接
% =========== 実数版 mod ===============
/mod_real { % 実数版 mod
/waru exch def % 割る方
/num exch def % 割られる方
% gext 余り
{ /gext num waru sub def % 割られる方から割る方を引いて余りに入れる
gext waru le { exit } if % 余りが割る方より小さくなったら終了
/num gext def % 割られる方に余りの数字を入れる
} loop
} def
/csw 0 def % 色を切り替えるスイッチ
/col1 { .8 .4 .8 setrgbcolor } def % カラー1(紫)
/col2 { 1 .65 0 setrgbcolor } def % カラー2(オレンジ)
/col3 { 1 0 .7 setrgbcolor } def % カラー3(ピンク)
/r 18 def % 円の半径(整数)
/d r 2 mul def % 円の直径
/sd d 30 cos mul def % 下段の円と距離
/w0 120 def % 横幅
/h0 120 def % 縦幅
/w w0 d add def % 横幅にパターンが見切れないように円の直径を足す
/h h0 sd add def % 縦の高さに下段の円と距離を足す
/kx w0 d mod def % 横幅を円の直径で割って、余りをkxに入れる
h0 sd mod_real % 縦の高さは下段の円と距離で割る
/ky gext def % 余りをkyに入れる
/sw 1 def
0 0 240 240 rectfill % 黒背景
120 120 translate % 座標の原点を中央に移動
% =========== メイン ===============
newpath % パスの初期化
h neg sd h { % -hからhまでsize2づつ増分し{ }内を繰り返す
/dy exch def % 制御変数をdy(縦移動量)に入れる
w d add neg d w kx sub { % -wからwまでsizeづつ増分し{ }内を繰り返す
/dx exch def % 制御変数をdx(横移動量)に入れる
/x dx kx add def /y dy ky add def % x=dx+kx y=dy+ky
sw 1 eq { /x x r 3 mul add def } if % 横にずらす(swが1ならx=x+r*3)
x y r 0 360 arc % (x,y)に半径rの円を描く
csw 0 eq { col1 } { % 1なら紫
csw 1 eq { col2 } { % 2ならオレンジ
col3 } ifelse } ifelse % それ以外ならピンク
fill % 塗りつぶす
% 色の切り替え(cswが2以下ならcsw+1する、さもなくば0にする)
csw 2 lt { /csw csw 1 add def} { /csw 0 def } ifelse
} for
/csw 0 def
/sw sw neg def % swの符号を反転する
} for
コメント