見出し画像

刺し子模様をPythonで描く:丸毘沙門

丸毘沙門。一見複雑そうだが,基本パターンは次のもの。

画像1

弧が6つだが,原点中心の円が基本になっていることはわかるだろう。次のようになっている。(Cinderellaで描画)

画像2

4つの緑の円は同じ半径。周りの3つの円の中心は,赤い円の円周上にある。中心を結ぶと,正三角形だ。つまり,どの円の中心も計算で求められる。したがって面倒なのは,弧の描き始めと描き終わりの角を求めることだ。
 次の図で考える。OAはx軸と30°の角をなす。
二等辺三角形OABで,角AOBの大きさを求めることができればよい。BからOAに垂線BHを下す。OB=R2,OA=R1 とすると,OHはOAの半分なので,三角比を用いて cosθ=OH/OB  と表せる。そこで,OH/OB の値から逆にθを求めればよい。これは,三角関数の逆関数 arccos() で求められる。

画像3

すなわち,th=np.arccos(R1/R2/2) で角θ(th)が求められるのだ。
あとは,30° ,120°を使って計算していけばよい。

円周率は numpy を用いると np.pi だが,何度も使うので pi = np.pi としてしまおう。関数定義の外側で,描画設定を合わせて書いておけばよい。pi は,モジュール math でも円周率を表すが,ここでは用いないし,使うときは math.pi なので,特に不具合はあるまい。

青海波を描くときに,弧を使った。それをそのまま使えばよい。基本パターンは次のように作る。

# 基本パターンをorgを原点として描く
def basicpattern(org):
   drawarc(org, R2, th+pi/6, 5*pi/6-th)
   drawarc(org, R2, th+5*pi/6, 3*pi/2-th)
   drawarc(org, R2, th+3*pi/2, 13*pi/6-th)
   drawarc(org+[R1*np.cos(pi/6), R1*np.sin(pi/6)], R2, 7*pi/6-th, 7*pi/6+th)
   drawarc(org+[R1*np.cos(5*pi/6), R1*np.sin(5*pi/6)], R2, -pi/6-th, -pi/6+th)
   drawarc(org+[0, -R1], R2, pi/2-th, pi/2+th);

描画設定は,

Shiftx = np.array([R1*np.cos(pi/6), R1*np.sin(pi/6)])
Shifty = np.array([R1*np.cos(5*pi/6), R1*np.sin(5*pi/6)])

あとは,画面設定を適当に設定する。

R1 = 5,R2 = 3.5 のとき,次のようになる。

画像4

R1 = 5,R2 = 4 のとき,次のようになる。

画像5

R1 = 4.5,R2 = 3 のとき,次のようになる。

画像6

プログラム全体を掲載しておこう。

import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 8))
plt.axis([-20, 25, 10, 40])
plt.xticks([]) # 目盛を非表示にする 
plt.yticks([])
# 横方向にm,縦方向にn個のパターンを描く
def drawpattern(m, n):
   for x in range(m):
       for y in range(n):
           org = x*Shiftx + y*Shifty
           basicpattern(org)
# 弧を描く 引数は 中心,半径,描き始めと描き終わりの角
def drawarc(center, r, st, en):
   t = np.linspace(st, en, 100)
   x = r*np.cos(t) + center[0]
   y = r*np.sin(t) + center[1]
   plt.plot(x, y, lw=1, color=Drawcolor)
   
# 基本パターンをorgを原点として描く
def basicpattern(org):
   drawarc(org, R2, th+pi/6, 5*pi/6-th)
   drawarc(org, R2, th+5*pi/6, 3*pi/2-th)
   drawarc(org, R2, th+3*pi/2, 13*pi/6-th)
   drawarc(org+[R1*np.cos(pi/6), R1*np.sin(pi/6)], R2, 7*pi/6-th, 7*pi/6+th)
   drawarc(org+[R1*np.cos(5*pi/6), R1*np.sin(5*pi/6)], R2, -pi/6-th, -pi/6+th)
   drawarc(org+[0, -R1], R2, pi/2-th, pi/2+th);
R1 = 5
R2 = 3.5
th = np.arccos(R1/R2/2)
pi = np.pi
# 横方向のシフト量,縦方向のシフト量,描画色を定義して描く
Shiftx = np.array([R1*np.cos(pi/6), R1*np.sin(pi/6)])
Shifty = np.array([R1*np.cos(5*pi/6), R1*np.sin(5*pi/6)])
Drawcolor = 'k'
drawpattern(12, 12)
#plt.savefig("marubisyamon.png")
plt.show()