見出し画像

マンデルブロ集合をお正月っぽく彩色する

あけましておめでとうございます。

上の画像は2023年1月1日にTwitter上に投稿したものです。

マンデルブロ集合の内側を白・橙・緑の3色で塗ることで鏡餅に見立て、外側も正月っぽさを意識して紅白で塗ってあります。

この記事では、この画像の生成方法を軽く説明します。

※完成品を生成できるコード自体は載せないので、どうしても同じような画像を作成したい人は説明を基に自力でコードを書いてみてください。また、解説の内容はマンデルブロ集合の定義や基礎的な描画方法を知っている人向けに書いているので、知らないという人は以下の記事等を読んでおくとよいかと思います。

内側

まずは内側の彩色方法を説明します。

マンデルブロ集合の定義に使う$${z_{n+1}=z_n^2+c,z_0=0}$$という数列は、定数$${c}$$がマンデルブロ集合の中にあれば大抵は周期数列に収束していきます。

そして、マンデルブロ集合を構成する円状の領域1個ずつには対応する周期の値が1つずつ存在し、$${z_n}$$の周期は$${c}$$がどこの領域にあるかで判別できるようです。

☝マンデルブロ集合の各領域と周期

これを利用することで、周期の値をもとにして円状領域1個ずつに色を塗ることができるようになります。

同じ周期を持つ領域が複数存在するので完全に自由自在に塗り分けられるわけではないのですが、少なくとも横一直線に並んだ領域を餅とみかんに見立てるぐらいのことならできるはずです。

さて、$${z_n}$$の周期は以下の手順により近似的に求められます。

  1. 普通にマンデルブロ集合を描画するときと同じように$${z_n}$$を計算し、所定の計算回数(5000回くらい)以内で発散するかを調べる。

  2. 発散しなかったら、最終的な$${z_n}$$の値を$${d}$$とする。

  3. $${z_1=d}$$として$${z_n}$$を再計算し、1項計算するごとに$${|z_n-d|^2}$$の大きさを調べる。

  4. $${|z_p-d|^2}$$が十分($${10^{-12}}$$くらい)小さくなったら計算を止める。($${p}$$が周期)

そして、周期$${p}$$の値に応じて以下のように塗り分けることで鏡餅っぽいカラーリングになりました。

  • $${p}$$を8で割った余りが0なら緑

  • $${p}$$を8で割った余りが4なら橙

  • それ以外なら白

ところで、正月風マンデルブロ集合の画像は実は2022年にも投稿しています。

☝2022年版正月風マンデルブロ集合

こちらのバージョンでは餅の下に敷く葉っぱを表現するのに緑色を使っているため、配色が微妙に異なります。

このバージョンの画像を投稿した直後に「せっかく緑を使うならみかんの葉っぱに使った方が『それっぽい』のでは?」と気づいたので、1年越しにリメイクしたのでした。

外側

外側の紅白の部分は、"Binary Decomposition"という手法で彩色しています。

名前を見るとなんだか難しそうに感じますが、やり方はなんと「普通に$${z_n}$$を計算して、発散したと判定されたときの$${z_n}$$の虚部の符号に応じて赤と白で塗り分ける」といういたってシンプルなものです。

なおリンク先のページではジュリア集合の内側と外側をBinary Decompositionで彩色する方法をそれぞれ解説していますが、外側の方のアルゴリズムをほぼそのまま流用することでマンデルブロ集合の外側にも応用できます。

おまけ

解説することはもうないのですが、せっかくなので関連画像を何枚か置いておきます。

☝z^2-0.76のジュリア集合

マンデルブロ集合と違い、ジュリア集合は内側の彩色の自由度が低くて鏡餅っぽくできませんでした。

☝バーニングシップフラクタル
☝バーニングシップフラクタル(-1.75付近)

バーニング宝船です。

マンデルブロ集合と同様に虚部の値で彩色したところあまり面白い模様にならなかったので、実部の値を使用しています。

☝z^2-0.122565+0.744864iのジュリア集合

今年は卯年ですが、臨界点を周期サイクルに含む2次関数の3周期ジュリア集合を"Douady rabbit"と呼ぶそうです。

ちなみにBinary Decompositionの引用元のページにはDouady rabbitの内側をBinary Decompositionで塗った画像がありますが、同じページに載っている"Modified Binary Decomposition"(ジュリア集合の内側も彩色できる改良版)のアルゴリズムは、どうやらうまく機能するような条件がある程度限られているっぽいです。

せっかくなので最近見たアニメに出てくる兎のキャラをイメージしてDouady rabbitを描画してみました。

何のキャラかわかるでしょうか?(この記事のハッシュタグにヒントがあります)

☝z^2-0.76のジュリア集合
☝z^2-1.1のジュリア集合
☝z^2-1.75のジュリア集合
☝z^2-1+0.2iのジュリア集合

Binary Decompositionを自力でジュリア集合の内側に適用しようとして得られた画像です。

$${c}$$が実数でない場合は、外側のように模様のカドとカドがうまく繋がらずに違った感じの見た目になってしまうようです。

☝z^2-0.1+0.7iのジュリア集合

内側Binary Decompositionの模様ズレを修正しようとした結果です。

☝1-z^3のジュリア集合

2次関数では紅白の縞模様の縞の数が2倍ずつ増えていくことで特徴的な模様が生成されていましたが、3次関数だと縞の数は3倍ずつ増えるようです。

☝c/(z^2-1)+1のマンデルブロ集合
☝2/(z^2-1)+1のジュリア集合
☝(-0.2+0.7i)/(z^2-1)+1のジュリア集合

$${\frac{c}{z^2-1}+1}$$の穴の中も、外側と同じようにBinary Decomposition模様になるようです。

☝(c(z-1)-1)/z^2+1のマンデルブロ集合
☝(-0.5(z-1)-1)/z^2+1のジュリア集合
☝((-0.3+1.3i)(z-1)-1)/z^2+1のジュリア集合

2周期発散関数で上手くいったんだから3周期発散関数でもイケるだろう、と思ったのですが、3周期発散関数である$${\frac{c(z-1)-1}{z^2}+1}$$の場合はマンデルブロ集合でもジュリア集合($${c}$$が実数でないとき)でも模様ズレが起きるようです。なんで?