Squeak Smalltalk でマンデルブロ集合

こちらの件のレストアしたアルト実機で BCPL で記述したマンデルブロ集合を実行してみたら1時間かかったという話を読んでいて、そういえば自分でマンデルブロ集合を描いてみたことがなかったなぁ…と気付いたのでさっそく書いてみました。

本当は、かなり以前に Smalltalk-80 で見た実装(ウインドウに表示して、一部を矩形選択するとその部分が新しいウインドウとして表示される)を作ってみたかったのですが、勢いで書けてワークスペースでさくっと実行できる簡単なもので済ませてしまいました。駄目ですね…。^^;

Display restoreAfter: [
   | limit dispRect ratio complexArea mandelbrot newRect scale |

   limit := 128.
   dispRect := Rectangle center: Display center extent: Display extent // 2.
   ratio := dispRect extent / dispRect height.
   complexArea := -1.0@0.0 - (ratio * 1.4) extent: ratio * 2.8.

   scale := [:pt |
      complexArea topLeft + (((pt x - dispRect left) * complexArea width / dispRect width)
         @ ((pt y - dispRect top) * complexArea height / dispRect height))].

   mandelbrot := [:c |
      | z count |
      z := 0.
      count := 0.
      [z squared abs < 4 and: [count < limit]] whileTrue: [
         z := z squared + c.
         count := count + 1
      ].
      (count / limit) sqrt
   ].

   Display fillWhite: dispRect.

   [:exit | [
      dispRect top to: dispRect bottom - 1 do: [:y | dispRect left to: dispRect right - 1 do: [:x |
         | pos color |
         pos := scale value: x@y.
         color := Color h: (mandelbrot value: pos x + pos y i) * 360 + 120 s: 1.0 v: 1.0.
         Display colorAt: x@y put: color.
         Sensor anyButtonPressed ifTrue: [exit value]
      ]].

      newRect := Rectangle fromUser.
      newRect area > 0 ifFalse: [exit value] ifTrue: [
         | center delta |
         center := newRect center.
         delta := dispRect extent * (newRect width / dispRect width max: newRect height / dispRect height) / 2.
         complexArea := (scale value: center - delta) corner: (scale value: center + delta).
      ]
   ] repeat] valueWithExit
]


Squeak のワークペース(デスクトップメニュー or Tools → Workspace )にペースト(alt/cmd + v)して改めて全選択(alt/cmd + a)後、do it(alt/cmd + d)で実行できます。

http://squab.no-ip.com/collab/uploads/mandelbrot01.png


一部を矩形選択するとその部分を拡大して再描画します。枠外を大きく選択すると縮小もできます。選択をせずクリックすると終了です。

http://squab.no-ip.com/collab/uploads/mandelbrot02.png


Pharo の Playground でも動かせますが、なんとけしからんことに Squeak で組み込みだった Complex が外されてモジュールに追い出されてしまっているので事前にインストールしておく必要があります(デスクトップメニュー → Tools → Catalog Browser → complex などと入力して Complex を右クリック → install stable version )。

http://squab.no-ip.com/collab/uploads/mandelbrot03.png


もうひとつ Pharo では描画後の拡大域選択操作の前にアクティブウインドウの再描画がされてしまうので、Playground ウインドウはあらかじめ端によけておかないといけません。ご注意あれかし。