LoginSignup
4
6

More than 5 years have passed since last update.

SwiftのPlaygroundでマンデルブロ集合

Last updated at Posted at 2015-09-28

Screen Shot 2015-09-29 at 4.45.52 AM.png
以前 https://developer.apple.com/swift/blog/?id=26 で紹介されていた
マンデルブロ集合がXCode7で動かなくなったのでSwiftの勉強がてらに作ってみます。

作り方

1.XCode7を立ち上げてPlaygroundをiOSの設定で作成する。
2.Sourcesフォルダにswiftファイルを適当に作成して以下を貼り付ける。

mandelbrot.swift
import UIKit

let resolution = 400
let iteration = 300

struct vec2{
  var x: Double
  var y: Double

  func length() -> Double{
   return sqrt(pow(x,2)+pow(y,2))
  }
}

func + (left:vec2,right:vec2) -> vec2{
  return vec2(x:(left.x + right.x),y:(left.y + right.y))
}

struct Result{
  var div: Bool//発散したかどうか
  var elapsed: Int?//発散した場合の計算回数
}

/// 結果格納クラス
public class ResultArray{
  var array: [Result]
  init(){
    self.array = Array(
      count:resolution * resolution,
      repeatedValue:Result(div: false,elapsed: nil)
    )
  }

  func indexIsValid(x:Int,y:Int)->Bool{
    return x>=0 && x<resolution && y>=0 && y<resolution
  }

  subscript(x:Int,y:Int) -> Result{
    get{
      assert(indexIsValid(x, y:y))
      return array[x * resolution + y]
    }
    set{
      assert(indexIsValid(x, y:y))
      array[x * resolution + y] = newValue
    }
  }
}

/// 複素数座標上の発散を計算
/// - parameter c :複素数座標
/// - returns: 発散の計算結果
func calcDiv(c:vec2) -> Result{
  var result:Result = Result(div:false,elapsed:nil)
  var z = vec2(x:0.0,y:0.0)
  for i in 0..<iteration{
    let nz = vec2(
      x: pow(z.x,2.0) - pow(z.y,2.0),
      y: 2.0 * z.x * z.y
    )
    z = nz + c
    if z.length() > 2.0{
      result = Result(div: true, elapsed: i)
      break
    }
  }
  return result
}

/// マンデルブロ集合の計算
/// - returns: 計算結果
public func calc() -> ResultArray{
  let result=ResultArray()
  for i in 0..<resolution{
    for j in 0..<resolution{
      let c = vec2(
        x: Double(i)/Double(resolution)*4.0-2.0,
        y: (Double(j)/Double(resolution)*4.0-2.0) * (-1)
      )
      result[i,j] = calcDiv(c)
    }
  }
  return result
}

/// マンデルブロ集合の描画
/// - parameters result: 計算結果
/// - returns : 描画データ
public func draw(result:ResultArray) -> UIView{
  let size = CGSize(width: resolution, height: resolution)
  let view = UIView(frame: CGRect(origin:CGPointZero, size: size))
  view.backgroundColor=UIColor(white:0.9,alpha:1.0)
  UIGraphicsBeginImageContextWithOptions(size, false,0)
  for i in 0..<resolution{
    for j in 0..<resolution{
      let rect = CGRectMake(CGFloat(i * 1), CGFloat(j * 1), 1, 1)
      let component: [CGFloat] = {
        if(result[i,j].div){
          let e: CGFloat = CGFloat(Float(result[i,j].elapsed!)*2.0/Float(iteration))
          return [1.0,1.0-e,1.0-e,1.0]
        }else{
          return [0.0,0.0,0.0,1.0]
        }
      }()
      let color = CGColorCreate(CGColorSpaceCreateDeviceRGB(), component)!
      UIColor(CGColor: color).setFill()
      UIRectFill(rect)
    }
  }
  let image = UIGraphicsGetImageFromCurrentImageContext().CGImage
  view.layer.contents = image
  return view
}

3.Playgroundのソースに以下を貼り付ける

Content.swift
//: ## Mandelbrot Set
let result = calc()
draw(result)

4.エディタの右の二重丸を押してから少し待つと絵が出てきます。

4
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6