LoginSignup
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.エディタの右の二重丸を押してから少し待つと絵が出てきます。

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
What you can do with signing up
6