導入
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
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