bitterharvest’s diary

A Bitter Harvestは小説の題名。作者は豪州のPeter Yeldham。苦闘の末に勝ちえた偏見からの解放は命との引換になったという悲しい物語

Haskellでお絵かき(4)

1.フラクタル

数学的な模様で有名なのはフラクタルである。同じ操作を繰り返すことで、幾何学的に作成したとは思えないほどの面白い模様を作り出してくれる。マンデルブロフラクタル幾何学を見ると、楽しい図形が沢山出ている。今回は、その中のいくつかを作成してみる。

2.シエルピンスキーの三角形

最初に登場するのは、シエルピンスキーの三角形(あるいはざる)と呼ばれる。これは次のようにして得ることができる。①最初に大きな三角形を描く。②辺の長さを半分にした三角形を三つ、大きな三角形と頂点を共有させて、描く。この操作を繰り返す。プログラムは次のようになる。

sierpinski 1 = triangle 1
sierpinski n =     s
                  ===
               (s ||| s) # centerX
  where s = sierpinski (n-1)

example :: Diagram B R2
example = pad 1.1 $ sierpinski 7 # centerXY # lw none # fc white <> square 100 # fc darkslateblue

main = mainWith example

実行結果は次のようになる。
f:id:bitterharvest:20140803165701p:plain

3.ドラゴンの踊り

コッホ曲線やレヴィ・ドラゴン曲線などがフラクタル図形として有名である。これらの曲線の作り方を示す。これらの曲線にはベースとなる図形がある。例えば、下の図は直角二等辺三角形の底辺を除いた部分である。フラクタル図形は、ベースとなる図形から、その上に同じパターンの図形を再帰的に描くことで得られる。その描き方には、同方向と逆転方向がある。図に示すように、同方向は同一の方向に同じパターンを書き続けるが、逆転方向では同一の方向と反対の方向とを繰り返す。
f:id:bitterharvest:20140803175300p:plain
ベースとなる図形にはいくつかあるが、代表的なものを下図に示す。
f:id:bitterharvest:20140804063656p:plain
これらのフラクタル図形を求めるプログラムは、以下のようになる。なお、これはモジュールとなっている。

{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module LevyDragon where

import Diagrams.Prelude

levy :: (Backend b R2, Renderable (Path R2) b)
            => Integer -> [Double] -> Diagram b R2
levy n p = map (\x -> rotateBy x unitX) (levyp n p) # fromOffsets # centerXY # fc white
           ===
           strutY 3
           ===
           map (\x -> rotateBy x unitX) (levyn n p) # fromOffsets # centerXY # fc white
             

levyp 1 p = p
levyp k p = zipWith (+) (concat $ map (replicate l) $ levyp (k - 1) p) (concat $ replicate (l ^ (k-1)) p)
            where l = length p
levyn 1 p = p
levyn k p = zipWith (+) (concat $ map (replicate l) $ levyn (k - 1) p) (concat $ take (l ^ (k-1)) $ iterate (map negate) p)
            where l = length p

コッホ曲線を求めるためには次のプログラムを使う。

import Diagrams.Prelude
import Diagrams.Backend.Rasterific.CmdLine
import LevyDragon

example :: Diagram B R2
example = pad 1.1 $ levy 7 [0, 1/6, -1/6, 0]

main = mainWith example

レヴィ・ドラゴン曲線を求めるためには次のプログラムを使う。

import Diagrams.Prelude
import Diagrams.Backend.Rasterific.CmdLine
import LevyDragon

example :: Diagram B R2
example = pad 1.1 $ levy 15 [1/8, -1/8]

main = mainWith example

ツイン曲線を求めるためには次のプログラムを使う。

import Diagrams.Prelude
import Diagrams.Backend.Rasterific.CmdLine
import LevyDragon

example :: Diagram B R2
example = pad 1.1 $ levy 7 [-1/8, 1/8, 1/8, -1/8]

main = mainWith example

4.実行結果は次のようである

コッホ曲線(上が同方向、下が逆転方向である)
f:id:bitterharvest:20140803165034p:plain
レヴィ・ドラゴン曲線(上が同方向、下が逆転方向である)
f:id:bitterharvest:20140803165057p:plain
ツイン曲線(上が同方向、下が逆転方向である)
f:id:bitterharvest:20140803165116p:plain

5.問題

個別にコッホ曲線、レヴィ・ドラゴン曲線を求めるプログラムを作成しなさい。