gloss で Turtle Graphics

Turtle Graphics on Gloss Ver.1.0.0.0
========================

[Gloss](http://hackage.haskell.org/package/gloss) を使った [Turtle Graphics](https://en.wikipedia.org/wiki/Turtle_graphics) です。

実際のコードは [こちらの github](https://github.com/little-schemer/Turtle-on-Gloss) にあります。

Gloss については [こちら](https://qiita.com/lotz/items/eb73e62a64bc208c2dd6) の記事が参考になる と思います。


含まれるファイル
----------------

``` example
app / Main.hs               -- 実験用

sample
├ circleDance.hs    -- 複数の円を同時に描く
├ dragonCurve.hs    -- dragon 曲線を描く
├ kochCurve.hs      -- Koch 曲線を描く
├ graph.hs          -- 関数のグラフを描く
└ star.hs           -- 星を描く

sample / L-system
├ dragonCurveL.hs   -- L-system で dragon 曲線を描く
└ kochCurveL.hs     -- L-system で Koch 曲線を描く

src / Graphics
      ├ Turtle.hs    -- Turtle Graphics 本体
      └ L_system.hs  -- L-System
```

Sample の実行法
---------------

-   `stack build` を実行することで sample ディレクトリ以下にあるファイルがコン パイルされ、 `CircleDance, DragonCurve, KochCurve, Graph, Star, DragonCurveL,
     KochCurveL` といったファイルが作られます。

-   `stack exec CircleDance` や `stack exec DragonCurveL` を実行すると図形が 描画されます。

Turtle Graphics の使い方
------------------------

使用例を示します。

``` haskell
import           Graphics.Gloss
import           Graphics.Turtle

main :: IO ()
main = runTurtle window white 20 [(st, cmdLst)]
  where
    window = initWindow
    st     = initST
    cmdLst = [forward 200, left 120, forward 200, left 120, forward 200]
```

`runTurtle` の型は次のようになってます。

``` haskell
runTurtle :: WinConfig               -- ^ 画面の状態
          -> Color                   -- ^ 背景色
          -> Int                     -- ^ 1 秒あたりのステップ数
          -> [(TurtleST, [Command])] -- ^ [ ( 亀の初期値, [ コマンド ] ) ]
          -> IO ()
```

`Color` は `gloss` の `simulate` 関数に渡すものです。詳しくは [こちら](https://qiita.com/lotz/items/eb73e62a64bc208c2dd6) を参照し てください。

`WinConfig` は画面の設定を保持しています。

``` haskell
data WinConfig = WinConfig { title   :: String         -- ^ Window のタイトル
                           , winSize :: (Int, Int)     -- ^ Window のサイズ
                           , winPos  :: (Int, Int)     -- ^ Window の位置
                           , zoom    :: Float          -- ^ 画像の拡大率
                           , shiftXY :: (Float, Float) -- ^ 画像の移動量
                           } deriving Show
```

`initWindow` で既定値に設定することが可能です。

``` haskell
initWindow :: WinConfig
initWindow = WinConfig { title   = "Turtle Graphics"
                       , winSize = (800, 600)
                       , winPos  = (10, 10)
                       , zoom    = 1
                       , shiftXY = (0, 0)
                       }
```

`TurtleST` は亀の状態を保持します。

``` haskell
data TurtleST = TurtleST { angle    :: Float -- ^ 亀の向き
                         , point    :: Point -- ^ 亀の位置
                         , penColor :: Color -- ^ ペンの色
                         , pen      :: Bool  -- ^ up or down
                         , mark     :: Bool  -- ^ 亀のマーク
                         , stack    :: [(Float, Point, Color, Bool, Bool)]
                         } deriving Show
```

`TurtleST` は `initST` で既定値を設定できます。

``` haskell
initST = TurtleST { angle    = 0
                  , point    = (0, 0)
                  , penColor = black
                  , pen      = True
                  , mark     = True
                  }
```

`Command` は亀に実行させる命令です。

Turtle Graphics のコマンド
--------------------------

各コマンドの型は次のようになっています。

``` haskell
type PrimitiveCommand = TurtleST -> (Picture, TurtleST)
type Command          = [PrimitiveCommand]
```

`PrimitiveCommand` は `TurtleST` を受け取り、図形 (Picture) とコマンド実行後の `TurtleST` を返します。

`Command` は `PrimitiveCommand` のリストになっており、通常はこちらを使用します。

| コマンド                | 省略形 | 動作                                                    |
|-------------------------|--------|---------------------------------------------------------|
| forward n               | fd n   | 亀が n だけ前進する。                                   |
| quickForward n          | qf n   | forward より高速に前進する。                            |
| backward n              | bk n   | 亀が n だけ後退する。                                   |
| left th                 | lt th  | 亀が th 度だけ左旋回する。                              |
| quickLeft th            | ql th  | left より高速に左旋回する。                             |
| right th                | rt th  | 亀が th 度だけ右旋回する。                              |
| quickRight th           | qr th  | right より高速に右旋回する。                            |
| goto p                  | --     | 亀が p の位置へ移動する。亀は進行方向を向く。           |
| penDown                 | pd     | 亀のペンを下げる。亀が移動すると線が描かれる。          |
| penUp                   | pu     | 亀のペンを上げる。亀が移動しても線は描かれない。        |
| push                    | --     | 亀の状態を Push する。                                  |
| pop                     | --     | 亀の状態を Pop する。                                   |
| nop                     | --     | 何もしない。                                            |
| nopN n                  | --     | n 回 nop を繰り返す。                                   |
| setAngle th             | --     | 亀の向きを th 度に設定する。                            |
| setPoint p              | --     | 亀の位置を p に設定する。                               |
| setColor c              | --     | 亀のペンの色を c に設定する。                           |
| drawPolygonL n m        | --     | 一辺の長さが m の正 n 角形を左回りに描く。              |
| drawPolygonR n m        | --     | 一辺の長さが m の正 n 角形を右回りに描く。              |
| drawCircle r            | --     | 亀の位置を中心に、半径 r の円を描く。                   |
| drawCircleSolid r       | --     | 亀の位置を中心に、半径 r の Solid な円を描く。          |
| drawArcL th r           | --     | 中心角 th , 半径 r の円弧を左回りに描く。               |
| drawArcR th r           | --     | 中心角 th , 半径 r の円弧を右回りに描く。               |
| drawGraph fx domain     | --     | 陽関数のグラフを描く。                                  |
| drawGraph' fx fy domain | --     | 陰関数のグラフを描く。                                  |
| grid                    | --     | grid' 500 10                                            |
| grid' range size        | --     | -size ~ size の範囲に目盛サイズ size の方眼を表示する。 |
| updateAngle func        | --     | 亀の向きを関数に従って更新する。                        |
| updatePoint func        | --     | 亀の位置を関数に従って更新する。                        |
| updateColor fr fg fb fa | --     | ペンの色の成分を関数に従って更新する。                  |

-------------
※ Ver.1.0.0.0 をリリースするにあたり、以前投稿したものと一部異なる仕様になったため、本文を書き替えました。