Playgroundでマンデルブロ集合とジュリア集合を描いてみた
Playgroundでマンデルブロ集合とジュリア集合を描いてみた
リポジトリ
動機
Playgroundを使ってプロトタイプして時に、いろいろ調べていて見つけたPlaygroundの紹介記事でマンデルブロ集合のデモをしていた。
演算子オーバーロード、PlaygroundのAnimation確認等、いろいろ試したいことがあって、ちょうど良い題材だった。
フラクタル図形を描いたり、複素数でぐにゅぐにょしたかった。
マンデルブロ集合(Mandelbrot Set)
マンデルブロ集合の定義
z_{k}, c \in \mathbb{C} \\
\begin{cases}
z_{0} = 0 \\
z_{k+1} = z_{k}^{2} + c
\end{cases}
とした時、$k$ を大きくしても $ \infty $ に発散しない( $\lim_{k \rightarrow \infty } |z_{k}| = \infty $ とならないような)$c$ の集合をマンデルブロ集合といい、複素平面を見てみるとフラクタル図形となっている。
マンデルブロ集合の計算方法
適当に$k$をインクリメントしていき、$N$ 回反復して、
発散しない$c$ をマンデルブロ集合と判断する。
$ |z| > 2 $となれば$\infty$ に発散することが保証されているので、その時点で反復を打ち切って、マンデルブロ集合の要素ではないと判断する。
また、マンデルブロ集合の要素か否かを求までのはやさ(反復回数)で色分けをしたり、漸化式をいろいろ変えてやってアニメーションするといい感じになる。
例えば、$ z_{k+1} = z_{k}^{n} + c $ として $ n $ をいろいろ変えるとこんな感じ
ジュリア集合(Julia Set)
マンデルブロ集合と似ているが、
z_{k}, c \in \mathbb{C} \\
z_{k+1} = z_{k}^{2} + c
$ \lim_{k \rightarrow \infty } |z_{k}| = \infty $ とならないような$ z_{0} $ の集合がジュリア集合。
計算方法とかもマンデルブロ集合とほぼ同じ。
これもいろいろ漸化式を変えてみると面白い。
もう少し厳密な定義等はググってください。
コーディング
元ネタ記事においてあるhttp://developer.apple.com/swift/blog/downloads/Mandelbrot.zipがベースなので詳細は省略します。上のリンクのものは、Xcode6.3の時のものなのでXcode7.xだとそのままでは動かせないと思います。
図形の描画
複素平面の座標系(下方向が虚数軸の負)とビューの座標系(下方向がy軸の正)を変換するメソッドを作っとく。図を書いてごにょごにょすればこんな感じになっている。
public func viewCoordToComplexCoord(x x: Double, y: Double, rect: CGRect, rectScale: Double = 1.0) -> Complex {
let Co = self.topLeft, Cn = self.bottomRight - Co
let W = Double(rect.size.width) * rectScale, H = Double(rect.size.height) * rectScale
let cx = Re(Co) + x * Re(Cn)/W
let cy = Im(Co) + y * Im(Cn)/H
return Complex(cx, cy)
}
UIView
を継承し、drawRect
でフレームの適当な間隔の座標をとってきて、漸化式を計算し集合に含まれるかどうかを判断しUIColor.set()
で色をつけて、UIBezierPath(rect:).fill()
で塗りつぶす。
func drawJuliaSet(rect : CGRect) {
let width = Double(rect.size.width), height = Double(rect.size.height)
for x in 0.stride(through: width, by: self.block) {
for y in 0.stride(through: height, by: self.block) {
let z0 = self.complexRect.viewCoordToComplexCoord(x: x, y: y, rect: rect, rectScale: self.rectScale)
//反復回数に応じたUIColor
self.computeJuliaSetPoint(z0).set()
UIBezierPath(rect: CGRect(x: x, y: y, width: self.block, height: self.block)).fill()
}
}
}
Playgroundでのアニメーションの確認
最近変わったみたいですが、XCPlaygroundPage.currentPage.liveView
にビューを設定するとタイムラインに表示されるようになります。
UIImageViewをanimated gifみたいにしたい場合は、UIImageView
のanimationImages
にUIImage
を入れて,startAnimating()
すれば良いです。
import XCPlayground
//...
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let iv = UIImageView(frame: rect)
XCPlaygroundPage.currentPage.liveView = iv
iv.animationImages = imgs
iv.animationDuration = 1.0
iv.animationRepeatCount = 0
iv.startAnimating()
タイムラインを表示するには、Xcodeの[View][Assistant Editor]で表示します。(右上のベン図みたいなアイコンのボタンでもいい)。Contents.swiftを表示している状態で右側のUtility Areaを見るとShow Timelineというチェックボックスがあるのでチェックする。
Assistant Editorの表示をTimelineにすればXCPlaygroundPage.currentPage.liveView
に設定されているViewのアニメーションを確認できる。
Animationが目的じゃなきゃパラメータを変えてループさせるだけで、右側のビューで見えるのでliveViewは不要かもね。
それにしても、やっぱりフレームをでかくすると遅いな...
➜ ~ swift --version
Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76)
Target: x86_64-apple-darwin15.0.0
参考
Author And Source
この問題について(Playgroundでマンデルブロ集合とジュリア集合を描いてみた), 我々は、より多くの情報をここで見つけました https://qiita.com/kanetai/items/bcf920c656a33c620f14著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .