図形を描く

# 導入
Pharo で図形を描いてみます。Pharo は Smalltalk 処理系の一つですが、Smalltalk は Lisp 言語と LOGO 言語の影響を強く受けているオブジェクト指向言語です。LOGO のようにタートルを実装し、いろいろな図形を描いてみます。
# FractalMorph クラス
まずは FractalMorph クラスからです。このクラスはタートルの機能を実装します。
```
BorderedMorph subclass: #FractalMorph
	instanceVariableNames: 'location angle'
	classVariableNames: ''
	package: 'PBE-Fractal'
```
FractalMorph は BorderedMorph のサブクラスとします。インスタンス変数は location と angle を持ちます。location はタートルの置き場所であり、angle はタートルが向いている方向を表します。タートルの向きの指定は度数法ですが、angle は弧度法（ラジアン）で持つようにします。
### accessing プロトコルメソッド
インスタンス変数を参照するメソッド群を実装します。
```
angle
	^ angle
```
```
location
	^ location
```
### 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
```
```
turnLeft: degree
	self turnRight: degree negated
```
```
turnRight: degree
	self angle: self angle + (2 * Float pi * degree / 360)
```
### initializing プロトコルメソッド
自身のオブジェクトを初期化するメソッドを実装します。
```
initialize
	super initialize.
	self angle: 0.
	self location: self center
```
### protected プロトコルメソッド
自身とサブクラスからのみ使用して欲しいメソッドを実装します。
```
angle: radian
	angle := radian
```
```
location: point
	location := point
```
### overrides プロトコルメソッド
このプロトコル内にはオーバーライドしているメソッドが自動的にカテゴライズされます。これから図形を描画するサブクラスを実装しますが、そのサブクラスでオーバーライドされているメソッドも含みます。以下がオーバーライドされているメソッド群です。
```
angle
angle:
forward:
initialize
location
location:
turnLegt:
turnRight:
```
# 実際に図形を描画するオブジェクトを実装する。
FractalMorph オブジェクトだけでは図形は何も描画できません。具体的に図形を描画するオブジェクト（これを「特化」といいます）を実装していきます。
# KochMorph
KochMorph は、コッホ曲線を描画するオブジェクトです。スーパークラスは先程実装した FractalMorph です。
```
FractalMorph subclass: #KochMorph
	instanceVariableNames: ''
	classVariableNames: ''
	package: 'PBE-Fractal'
```
### 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 ]
```
### initializing プロトコルメソッド
自身を初期化するメソッドです。
```
initialize
	super initialize.
	self extent: 800 @ 300.
	self location: 100 @ 200.
	self drawKoch: 100
```
### 実行
Playground で以下を do-it します。
```
KochMorph new openInWorld
```
こんな Morph を表示します。
![koch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3430684/55a599bc-f811-47f6-a45a-8bbecf610927.png)
# TriangleMorph
TriangleMorph は小さい三角形をたくさん描画して大きな三角形を描画ます。インスタンス変数に lengthOfSide を持ちます。描画する三角形の一辺の長さ持ちます。スーパークラスは FractalMorph です。
```
FractalMorph subclass: #TriangleMorph
	instanceVariableNames: 'lengthOfSide'
	classVariableNames: ''
	package: 'PBE-Fractal'
```

### accessing プロトコルメソッド
インスタンス変数を参照するメソッド群を実装します。
```
halfLengthOfSide
	^(self lengthOfSide / 2) rounded
```
```
heightOfTriangle
	^ (self halfLengthOfSide * 3 sqrt) rounded
```
```
lengthOfSide
	^lengthOfSide
```
```
lengthOfSide: newLength
	lengthOfSide := newLength
```
### constants プロトコルメソッド
三角形を何段にするかの定数値を持ちます。値は 5 となっているので五段の三角形を描画します。
```
stepOfTriangles
	^5
```
### drawing プロトコルメソッド
三角形を描画するメソッドを実装します。
```
drawTriangle: topPoint
	self angle: 0.
	self location: topPoint.
	self turnRight: 60.
	self forward: self lengthOfSide.
	self turnRight: 120.
	self forward: self lengthOfSide.
	self turnRight: 120.
	self forward: self lengthOfSide
```
```
drawTriangleRec1: row top: aPoint 
	row = 0
		ifTrue: [ ^self ].
	self drawTriangleRec2: row top: aPoint.
	self drawTriangleRec1: row - 1 top: (aPoint x + self halfLengthOfSide) @ (aPoint y + self heightOfTriangle)
```
```
drawTriangleRec2: row top: aPoint 
	row = 0
		ifTrue: [ ^self ].
	self drawTriangle: aPoint.
	self drawTriangleRec2: row - 1 top: (aPoint x - self halfLengthOfSide) @ (aPoint y + self heightOfTriangle)
```
### initializing プロトコルメソッド
初期化メソッドです。
```
initialize
	super initialize.
	self extent: 800 @ 800.
	self location: self center x @ 100.
	self lengthOfSide: 100.
	self drawTriangleRec1: self stepOfTriangles top: self location
```
### 実行
Playground で以下を do-it します。
```
TriangleMorph new openInWorld
```
こんな Morph を表示します。
![tri.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3430684/dabc0781-3b7d-45f8-8c3a-13424754f58b.png)