42の課題でフラクタル(マンデルブロ集合とジュリア集合)を描画する課題があり, それが完了したので感想とか色々.
フラクタルとはなんぞや
Wikipediaによると
図形の部分と全体が自己相似(再帰)になっているものなどをいう。
らしいです.
以下のようなやつとかですね.
I, Avenafatua, CC 表示-継承 3.0, リンクによる
まぁ他にもフラクタルはいくつか種類があったり, 数学的な定義とか色々ありますが, まぁズームしていくと終わりが無くどんどん図形が出てくるやつのことです.
So Doge. Much fractal.
imgur.com
マンデルブロ集合
で, マンデルブロ集合 (Mandelbrot set) とはなんぞやという話ですが, マンデルブロ集合とは以下の漸化式が で発散しない集合のことです.
ここで と は複素数の式 です. また, は複素数平面上の座標に対応しています.
マンデルブロ集合のわかりやすい説明は以下の動画とサイトがわかりやすいです.
で, 実装するときには が発散するかどうかを判定しようとすると永遠に終わらないので, 適当に とかにします. また, 発散するかどうかの判定は が2を超えなければ集合に入っているということにします.
なんで2にしたかというと, マンデルブロ集合が実数, 虚数共に-2から2の範囲にあるからです.
で, これをコードとして書くと以下のような図が出てくるわけです.
これを拡大していくと再帰的にどんどん色んな形が描画されていくのです.
ジュリア集合
ジュリア集合は基本的なコンセプトはマンデルブロ集合と同じです. 違う点は, と の扱いで, ジュリア集合では を複素平面上の座標に対応させ, が定数となっています.
以下の動画がめっちゃわかりやすいので見ると良いです.
たとえば とすると以下のような形が出てきます.
だと以下のような形が出る.
こんな感じでを変えるとの値によって色んな形が出現します.
今回自分はマウスの座標によっての値を変えれるようにしました.
はい. かっこいい.
バーニングシップ
課題のボーナスで「更にもう一個別のフラクタル作りなはれ」というのがあったのでバーニングシップ(Burning Ship)というのを作りました.
基本的なコンセプトはマンデルブロ集合と同じなのですが, イテレーションごとに行う計算(を求める計算)が少し違います.
イテレーションごとに行う計算でそのまま2乗するのではなく, 絶対値を取るのがマンデルブロ集合との違いです.
これを実装して描画すると以下のような図形が出てきます.
燃えてる船(Burning Ship)っぽいですね.
これを拡大していくと
再帰的にどんどん船の形が出てきますね! かっこいい!
ただ, バーニングシップに関しては深くズームしまくると途中で行き止まりに当たるんで実装が正しくない可能性があるかも.
色付けに付いて
マンデルブロ集合, ジュリア集合, バーニングシップ は実装自体は難しくないです. ただ, 美しく描画するとなるとむずいんすよね...
今回の課題でも一応 color range shift を実装するという項目があったので, 単純にイテレーション回数に応じてHSVの色相(Hue)を変えるというので実装していて, 綺麗ではあるんですがYouTubeとかに上がっている動画の方みたいに綺麗なものを実装するのはなかなか難しそうです.
By Maxter315 - Own work, CC BY-SA 4.0, Link
Wikipediaにマンデルブロ集合の色付けについての記事があったので見てみたのですが, 色付けって奥が深いですね...
完走した感想
完走した感想ですが, 楽しかったです(小並感).
マンデルブロ集合, ジュリア集合の描画に関しては1日で実装できましが, マウスのカーソルの場所に向かってズームする処理(Google map的なアレ)がくっそむずかったです.
というのも最初はズーム倍率と中心座標を保持してその値を変えることによって実現させようと思ったのですが, まる一日やっても上手くいかず, 結局ggったり他の人のコード読んだりして最終的には描画する左右上下両端の値(min_re
, max_re
, min_im
, max_im
)を保持し, それらを使って描画するようにしました. そこにマウスのウィンドウサイズからの相対座標を使って掛けたり割ったりしてうまいことズームしたり平行移動したりするようにしました.
あと, ループ内で変数代入するタイミングをミスってデバッグに1日溶かしました.
とか色々あって大体4日くらいかかりました.
この課題以外にも2Dゲームの課題とかがあったのですが, ジュリア集合のGIFアニメーションがかっこよすぎたのでこの課題にしました.
マウスでの値を変動させるというのは課題要件に無いので別にやる必要はなかったのですが, かっこいいを求めてやりました. 結果的にはかっこよくなったので大満足です.
この課題はそこまで重くない課題なので最初は記事を書くモチベはさほどなかったのですが, 実は提出するのをやらかしてLinterに引っかかって0点を食らったので供養のために書いていたりしますw
ちゃんと課題提出前に確認するのと, 眠い時はちゃんと寝ましょう.
それではまた次の記事でお会いしましょう. ではでは〜👋👋