Pharoでフラクタル図形を書いてみよう

技術士試験の平成27年情報工学部門に出題されたコッホ曲線を Pharo で実装してみます。
Pharo を使用するのはグラフィックス周りの実装が楽だからです。

BorderedMorph subclass: #KochMorph
	instanceVariableNames: 'location angle'
	classVariableNames: ''
	package: 'PBE-Fractal'

まずは KochMorph オブジェクトを作ります。
KochMorph は、BorderedMorph のサブクラスにします。これで BorderedMorph の性質を継承しました。
インスタンス変数は location と angle を用意します。

次にインスタンス変数のアクセッサを用意します。プロトコルは accessing が適切です。

KochMorph>>angle (accessing)
angle
	^ angle
KochMorph>>location (accessing)
location
	^ location

解説はいらないでしょう。
設定する方は private プロトコルに実装します。

KochMorph>>angle: (private)
angle: radian
	angle := radian
KochMorph>>location: (private)
location: point
	location := point

次。初期化メソッドをオーバーライドします。*1

KochMorph>>initialize (initializing)
initialize
	super initialize.
	self extent: 800 @ 300.
	self location: 100 @ 200.
	self angle: 0.
	self drawKoch: 100

initialize メソッドをオーバーライドする時は、
最初に super initialize するのを必ず忘れないようにします。
忘れると大変な事が起こります! どう大変になるかは恐ろしくて書けませんw

自身のモーフの大きさ設定、インスタンス変数の初期化をします。
ついでに、面倒なのでコッホ曲線の描画もしてしまいます。(手抜き)

さていよいよ本丸のメソッドを書いていきます。
前進するメソッドから。

KochMorph>>forward: (drawing)
forward: amountOfMovement
	| x y newLocation |
	x := angle cos * amountOfMovement.
	y := angle sin * amountOfMovement.
	newLocation := x @ y translateBy: self location .
	self addMorph: (LineMorph from: self location to: newLocation color: Color yellow width: 2).
	self location: newLocation

angle から移動先のポイントを計算して LineMorph をサブモーフに追加します。

次に方向転換するメソッド。

KochMorph>>turnLeft: (drawing)
turnLeft: degree
	self angle: self angle - (2 * Float pi * degree / 360)

left: メソッドは上位階層オブジェクトで実装されているので、これをオーバーライドはしたくないので、turnLeft: メソッドにします。
引数は角度(60度とか)ですが、angle はラジアンで持ちたいので変換しています。

次はコッホ曲線を書くメソッドです。

KochMorph>>drawKoch: (drawing)
drawKoch: n
	| nn |
	n > 7
		ifTrue: [ nn := n / 3.
			self drawKoch: nn.
			self turnLeft: 60.
			self drawKoch: nn.
			self turnLeft: -120.
			self drawKoch: nn.
			self turnLeft: 60.
			self drawKoch: nn ]
		ifFalse: [ self forward: 20 ]

これも draw: はオーバーライドしたくないので避けます。


はい。以上で実装は完了です。
Playground (Workspace) を開いて、以下を do-it します。

KochMorph new openInWorld

こんなのが表示されれば OK です。
f:id:umeaji:20190712043840p:plain
Pharo ならグラフィック周りの実装がちょー簡単です。
面倒くさい事を考える必要は何も無いです。素晴らしいね!

OOPバンザーイ!

*1:後日追記 初期化メソッドのプロトコルは initialization のほうが良いです。