見出し画像

刺し子模様をPythonで描く:基本1・麻の葉

 刺し子をするときに,模様を手で描くのはなかなか大変。本を見て,これを刺したいと思ったとき,パソコンできれいに描けるとよい。
 そんな要請で作ったのがCinderellaJapanの「刺し子模様を作る」のページ。

左上の三本線をクリックすると,さらにインデックスが表示される。
これは,CinderellaとCindyScriptで作ったもの。これをPythonで書きなおす。
ちょっとしたプログラミングの教材になる。部活動で使ってもよいだろう。

見出し画像が「麻の葉」という模様で,刺し子では基本的なものだ。刺し子では下絵を描いておいて,糸を刺していくのだが,一筆で描けるところを探して刺していく。ここで描くのはその下絵だが,刺し子以外でも日本伝統の図柄として利用できる。これをコンピュータで描くには,もとになる図形(基本パターン)を探し出して,それを描く関数を作り,繰り返しを使って全体を描いていく。縦横に並べていくので,刺し子と同様,同じ線を重ねて描かないような基本パターンを探し出す。これはちょっとしたパズルだ。

プログラムの構造は次のようにする。

(1) 描画する画面の設定:サイズなどを決める
(2) 描画関数を定義する:いろいろなパターンで共通に使える描画関数を定義
  drawpattern(m,n) と下請けの draw(org,plist)
(3) 基本パターンを描くものを関数として定義する。 basicpattern(org)
(4) 基本パターンを移動する量と描画色を決めて,drawpattern() を呼び出す。

では,刺し子模様で最も基本的なこの「麻の葉」を描いてみよう。

(1) 描画する画面の設定

 外部ライブラリの numpy と matplotlib をインポートする。
次は,描画する画面を 800×800 のサイズとし,横軸を0から20,縦軸も0から20 までとしたもの。描画したときの座標を確かめるには,目盛を表示して,plt.grid() も有効にする。軸の範囲を広げると,ひとつのパターンが小さく描かれる。

import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 8))
plt.axis([0, 20, 0, 20])
# plt.grid()
plt.xticks([]) # 目盛を非表示にする 
plt.yticks([])


(2) 描画関数を定義する

いろいろな図柄で共通に使える描画関数を定義する。
draw(org,plist) は,基本パターンを描く関数 drawpattern(m,n) の下請けで,点のリスト plist を線分で結ぶ。org は描画時の原点。描画色 Drawcolor は平行移動量とともにあとで定義する。
drawpattern(m,n) は,基本パターンを横にm個,縦にn個描く。
中で使っている変数 Shiftx , Shifty は平行移動量で,あとで(関数の外で)定義する。basicpattern(org) が基本パターンを定義する関数だ。

# 点を線分で結ぶ
def draw(org, plist):
   x = []
   y = []
   for pt in plist:
       x.append(org[0]+pt[0])
       y.append(org[1]+pt[1])
   plt.plot(x, y, lw=1, color=Drawcolor)
   
# 横方向にm,縦方向にn個のパターンを描く
def drawpattern(m, n):
   for x in range(m):
       for y in range(n):
           org = x*Shiftx + y*Shifty
           basicpattern(org)

ここまでは,他の図柄でも共通に使う。画面のサイズと範囲は場合によって変えればよい。

(3) 基本パターンを関数として定義する

 刺し子模様は,あるパターンの繰り返しである。それを「基本パターン」と呼ぼう。そのパターンを描く手続きを関数として定義する。全体を描くには,(2) で定義した drawpattern(m,n) で基本パターンを平行移動しながら繰り返し描く。

 したがって,この関数が模様ごとに設計しなければならないものだ。
麻の葉の例で,その作り方を説明しよう。

 麻の葉は正六角形を基本とする。次の模様から正六角形が見えるだろうか。

画像5

これを見て,基本パターンを考える。基本パターンはいろいろが取り方がある。たとえば次のように取り,点に名前を付け,その座標と線の引き方を決める。背景は普通の方眼ではなく,正三角形の斜眼になっているので,縦横の長さはあとでしっかり考えよう。(この図はCinderellaで描いた)

画像2

I とJ は抜かしている。
一筆書きで描けるところをまず拾う。たとえば
     A, B, C, D, E, F, G, H, C, K, L, M, A, G 
を結ぶ。

画像3

あとは,残りの EL,FM,CN を結べばよい。点のリストを与えて,線分で結ぶのが(2)で定義した関数 draw() だ。
正三角形の斜眼になるので,一目盛を1とすると,横2に対し,縦は√3 になる。そこで,r を√3として使う。点Bは(2,0),点Mは(1,√3),つまり(1,r)になる。

# 基本パターンをorgを原点として描く
def basicpattern(org):
   r = np.sqrt(3)
   A=[0, 0]
   B=[2, 0]
   C=[3, r]
   D=[4, 0]
   E=[6, 0]
   F=[5, r]
   G=[6, 2*r]
   H=[4, 2*r]
   K=[2, 2*r]
   L=[0, 2*r]
   M=[1, r]
   N=[3, 3*r]
   draw(org, [A, B, C, D, E, F, G, H, C, K, L, M, A, G])
   draw(org, [E, L])
   draw(org, [F, M])
   draw(org, [C, N])


(4) 基本パターンを移動する量と描画色を決める

基本パターンの横幅はAからEまで6,縦幅はAからLまで2√3 なので,横につなげるには,原点(点Aの位置)を [6,0] に移動する。縦につなげるには,原点を [0,2√3] に移動する。
これを Shiftx, Shifty とする。
描画色はたとえば黒。これが Drawcolor。
基本パターンを横に4つ,縦に6つ描くことにして,drawpattern() を呼び出す。
画像ファイルに書き出すなら,plt.savefig() でファイル名を指定すればよい。

# 横方向のシフト量,縦方向のシフト量,描画色を定義して描く
Shiftx = np.array([6, 0])
Shifty = np.array([0, 2*np.sqrt(3)])
Drawcolor = 'k'
drawpattern(4, 6)
# plt.savefig("asaonoha.png")
plt.show()

空行を入れても 53行だ。
できたのが前の図。

飛び麻の葉

 次に,飛び麻の葉を描く。色を緑にしてみた。

画像5

基本パターンは次のように作った。

画像4

こんどは真横ではなく,斜めに移動するので,

Shiftx = np.array([6, 2*np.sqrt(3)])
Shifty = np.array([0, 4*np.sqrt(3)])

とする。すると,右下が空いてくるので,描画面の原点をずらして

plt.axis([0, 20, 10, 30])

とする。このあたりが工夫のしどころ。

基本パターンの定義以降は次のようにした。

# 基本パターンをorgを原点として描く
def drawpat(org):
   r = np.sqrt(3)
   A=[0, r]
   B=[2, r]
   C=[3, 0]
   D=[4, r]
   E=[6, r]
   F=[5, 2*r]
   G=[3, 2*r]
   H=[1, 2*r]
   K=[0, 3*r]
   L=[2, 3*r]
   M=[4, 3*r]
   N=[6, 3*r]
   O=[3, 4*r]
   draw(org, [A, B, C, D, E, F, N, M, O, L, K, H, A, N])
   draw(org, [E, K])
   draw(org, [C, O])
   draw(org, [F, H])
   draw(org, [B, M])
   draw(org, [D, L])
# 横方向のシフト量,縦方向のシフト量,描画色を定義して描く
Shiftx = np.array([6, 2*np.sqrt(3)])
Shifty = np.array([0, 4*np.sqrt(3)])
Drawcolor = 'g'
drawpattern(4, 5)


以上が,折れ線で描くパターンの基本だ。

次回は円弧を使って描く方法を考える。