はじめに
シェットランドというイギリス最北端に位置する群島地域で17世紀初頭に普及した編み込み模様をフェアアイルと呼びます。フェアアイル模様はOXO模様のような、小さなモチーフを規則正しく繰り返すことが特徴です。
私は自分でデザインしたものを編んで形にするのが好きなので普段からデザインを考えているのですが、デザインをするだけでかなりの時間がかかります。そこでフェアアイル模様の特徴である規則性や対称性をルール化し、自動生成できるようにすれば、デザイン時間を大幅に短縮できるのではないかと考えました。
模様の対称性を数学的に表現する手法として、壁紙群(Wallpaper Groups)とう概念があり、平面の繰り返し模様を 17 種類の対称性に分類するもので、フェアアイル模様の構造と相性が良いと考えました。
そこで今回は、壁紙群のひとつである「p4m」を使い、フェアアイル風の対称模様を Pythonで自動生成する仕組みを実装してみました。
壁紙群
壁紙群とは、平面に広がる繰り返し模様を「どんな対称性を持っているか」で分類した 17 種類のグループのことです。回転、鏡映、平行移動といった操作によって、模様がどのように自分自身と一致するかを表すため、タイル模様やイスラム幾何学、建築の装飾などあらゆるデザインの基礎となっています。
フェアアイル模様は基本的に四角いグリッドで構成されます。今回採用するp4mは90° 回転対称と鏡映対称という対称性をもつ壁紙群です。この対称性はフェアアイル模様で頻繁に用いられる模様の性質と非常に相性が良いです。
p4m対称性をプログラムで表現
0/1の二値でタイルを表現し、生成の仕組みとしては以下のように設計しました。
1.グリッド中心を決める
2.適当にセルを選び、p4mの対象操作(回転、鏡映)を行う
3.対象操作により影響の受けたセル同士をグループ化して、0,1を割り当てる
以上の仕組みにより対称的なモチーフがデザインできると考えた。
Pythonにて実装
基本タイル N×N の点 (i, j) が、p4m 対称群の作用で移る全ての点集合を返す関数。
import numpy as np
import random
def p4m_group(i, j, N):
cx = cy = N // 2
x = i - cx
y = j - cy
points = set()
def add_point(x, y):
ii = x + cx
jj = y + cy
if 0 <= ii < N and 0 <= jj < N:
points.add((ii, jj))
# 90° 回転を4回
rotations = [
( x, y),
(-y, x),
(-x, -y),
( y, -x),
]
for rx, ry in rotations:
# 8種の変換
add_point( rx, ry)
add_point(-rx, ry)
add_point( rx, -ry)
add_point(-rx, -ry)
# 対角線反射
add_point( ry, rx)
add_point(-ry, rx)
add_point( ry, -rx)
add_point(-ry, -rx)
return points
次に0/1の二値でp4m対称を持つN×Nタイルを生成する関数を定義。
def generate_p4m_tile(N=15):
assert N % 2 == 1
pattern = np.zeros((N, N), dtype=int)
assigned = set()
for i in range(N):
for j in range(N):
if (i, j) in assigned:
continue
group = p4m_group(i, j, N)
# 0or1をランダムに与える
color = random.randint(0, 1)
for (ii, jj) in group:
pattern[ii, jj] = color
assigned.add((ii, jj))
return pattern
生成したモチーフを縦横方向に繰り返す関数を定義。
def tile_periodic(tile, repeat_x=4, repeat_y=4):
return np.tile(tile, (repeat_y, repeat_x))
では、プロットしてみます!
import matplotlib.pyplot as plt
tile = generate_p4m_tile(N=15)
pattern = tile_periodic(tile, repeat_x=2, repeat_y=4)
# Plot
plt.figure(figsize=(6,6))
plt.imshow(pattern, cmap="binary", interpolation="nearest")
plt.axis("off")
plt.title("")
plt.show()
生成できたデザイン
無限にデザインを生成することに成功しました。しかも結構いいデザイン。アルゴリズムはいたって簡単ですが、とんでもないものができてしまった予感。
まとめ
今回はフェアアイル風模様の自動生成に取り組みました。今まで方眼紙に手でデザインしていたのが、なんと一瞬で無限に生成できるようになりました。編み物好きの人はぜひ使ってみてください。




