折り返しを回す
折り返しは軸を一本通すだけだった。中心のまわりに n 個コピーして各コピーを 2π/n ずつ回すと、向きを少しずつ変えた複製が円を一周埋める。n 回対称。
中心のまわりの回転だけで閉じる群が巡回群 C_n。生成元は 2π/n の回転ひとつで、それを n 回かけると一周して元に戻る。ここに軸を通す鏡映を一枚足すと二面体群 D_n になり、要素数は 2n(回転 n 個と鏡映 n 個)。C_n は向きの区別を持つ風車型、D_n は左右が揃った花型に対応する。
中心から外へ伸びる一本の腕が基本領域。まっすぐな線分を n 個コピーして放射状に並べる。回すのは角度 a を 2π/n 刻みで振るだけで、全体をゆっくり回している。
同じ線分が 2π/n ずつずれて、中心の1点から放射状に出る。n を変えると腕の本数が変わり、大きくすると車輪のスポーク、小さくすると数本の放射になる。
直線だけだと放射にしかならない。腕に形を持たせると回転の効きが見える。中心からの距離 r に沿って横へ揺れる量 wobble を持つ折れ線にする。腕は {r, w} の点の列で、w が中心軸からの横ずれ。
// 基本領域(一本の腕)。中心から外へ、少し曲げた折れ線
const arm = []
for (let i = 0; i <= 20; i++) {
const r = (i / 20) * reach
const wobble = Math.sin(i * 0.6) * 14
arm.push({ r, w: wobble })
}各点の横ずれ w は角度のずれに直す。半径 r が大きいほど同じ横幅でも角度は小さくて済むので、w / (r + 1) で割って角度にする。根元は締まり、外側はゆるく開く腕になる。
// 一本の腕を角度 a に描く。w を r で割って角度のずれにする
for (let i = 0; i < arm.length; i++) {
const p = arm[i]
const ang = a + p.w / (p.r + 1)
const x = cx + Math.cos(ang) * p.r
const y = cy + Math.sin(ang) * p.r
if (i === 0) c.moveTo(x, y)
else c.lineTo(x, y)
}この曲げた腕を n 個回す。腕は全部同じ向きにひねっているので、一方向にねじれた花になる。
腕が全部同じ向きにねじれて、回転だけが効いた C_n の絵になる。左右に揃った形にするには、各腕に鏡像をもう一本重ねる。横ずれの符号を反転した mir(+1 と -1)を掛けると、軸に対して折り返した腕が出る。
ねじれた腕と鏡像の腕が対になり、花が左右対称になる。回転に鏡映が足さって D_n になる。
n を整数で回すと腕が等間隔に揃う。割り切れない角度で回すと様子が変わる。黄金角 2π/φ²(約137.5度)で点を一つずつ置いていくと、どの整数本の腕にも乗らず、隙間が最も均等に詰まる。
整数の 2π/n は割り切れる回転で腕を揃え、黄金角は割り切れない回転で点を均す。同じ放射でも、回転の角度が整数比かどうかで密集と整列が裂ける。