{-# LANGUAGE FlexibleContexts          #-}
{-# LANGUAGE TypeFamilies              #-}

-------------------------------------------------------------------------------
-- |
-- Module      :  Diagrams.TwoD.Path.LSystem
-- Copyright   :  (c) 2015 Jeffrey Rosenbluth
-- License     :  BSD-style (see LICENSE)
-- Maintainer  :  [email protected]
--
-- Create LSystem diagrams and paths.
--
-- See "The Algorithmic Beauty of Plants".
-- <http://algorithmicbotany.org/papers/abop/abop-ch1.pdf>
-------------------------------------------------------------------------------

module Diagrams.TwoD.Path.LSystem
  ( -- * Lindenmayer Systems

    -- ** L-Systems
    Symbol(..)
  , Rules
  , generations

    -- ** L-System graphics
  , lSystemR , lSystem , lSystemPath , lSystemDiagram

    -- ** Making rules from strings
  , symbol, symbols
  , rule

    -- * Predefined L-Systems
  , sierpinski, cantor
  , dragon, hexGosper, kochIsland, kochLake
  , koch1, koch2, koch3, koch4, koch5, koch6
  , tree1, tree2, tree3, tree4, tree5, tree6

    -- * Re-exports from "Diagrams.TwoD.Path.Turtle"
  , TurtleState
  , getTurtlePath, getTurtleDiagram
  ) where

import           Control.Monad.Reader
import           Diagrams.Prelude                    hiding (local)
import           Diagrams.TwoD.Path.Turtle.Internal
import           Data.Map                           (Map)
import qualified Data.Map                           as M
import           Data.Maybe                         (fromMaybe)

-- | Symbols:
--
--     * @F (\'F\') draw a segment.@
--     * @G (\'f\' or \'G\') move the turtle one unit without drawing anything.@
--     * @Plus (\'+\') turn the turtle clockwise.@
--     * @Minus (\'-\') turn the turtle anti-clockwise.@
--     * @Reverse (\'!\') turn the turtle 180 degrees.@
--     * @Flip ('~') switch right and left.@
--     * @Push (\'[\') push the current state onto the stack.@
--     * @Pop (\']\') pop the current state.@
--     * @Width x (\'\<\', \'\>\') increase (decrease) stroke width by factor of 1.1 (0.9).@
--     * @Delta x (\'\(\', \'\)\') increase (decrease) turn angle by factor of 1.1 (0.9).@
--     * @X n (\'X\',\'Y\',\'Z\',\'A\',\'B\') constants.@
data Symbol n
  = F
  | G
  | Plus
  | Minus
  | Reverse
  | Flip
  | Push
  | Pop
  | X Int
  | Width n
  | Delta n
  deriving (Symbol n -> Symbol n -> Bool
(Symbol n -> Symbol n -> Bool)
-> (Symbol n -> Symbol n -> Bool) -> Eq (Symbol n)
forall n. Eq n => Symbol n -> Symbol n -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall n. Eq n => Symbol n -> Symbol n -> Bool
== :: Symbol n -> Symbol n -> Bool
$c/= :: forall n. Eq n => Symbol n -> Symbol n -> Bool
/= :: Symbol n -> Symbol n -> Bool
Eq, Eq (Symbol n)
Eq (Symbol n) =>
(Symbol n -> Symbol n -> Ordering)
-> (Symbol n -> Symbol n -> Bool)
-> (Symbol n -> Symbol n -> Bool)
-> (Symbol n -> Symbol n -> Bool)
-> (Symbol n -> Symbol n -> Bool)
-> (Symbol n -> Symbol n -> Symbol n)
-> (Symbol n -> Symbol n -> Symbol n)
-> Ord (Symbol n)
Symbol n -> Symbol n -> Bool
Symbol n -> Symbol n -> Ordering
Symbol n -> Symbol n -> Symbol n
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall n. Ord n => Eq (Symbol n)
forall n. Ord n => Symbol n -> Symbol n -> Bool
forall n. Ord n => Symbol n -> Symbol n -> Ordering
forall n. Ord n => Symbol n -> Symbol n -> Symbol n
$ccompare :: forall n. Ord n => Symbol n -> Symbol n -> Ordering
compare :: Symbol n -> Symbol n -> Ordering
$c< :: forall n. Ord n => Symbol n -> Symbol n -> Bool
< :: Symbol n -> Symbol n -> Bool
$c<= :: forall n. Ord n => Symbol n -> Symbol n -> Bool
<= :: Symbol n -> Symbol n -> Bool
$c> :: forall n. Ord n => Symbol n -> Symbol n -> Bool
> :: Symbol n -> Symbol n -> Bool
$c>= :: forall n. Ord n => Symbol n -> Symbol n -> Bool
>= :: Symbol n -> Symbol n -> Bool
$cmax :: forall n. Ord n => Symbol n -> Symbol n -> Symbol n
max :: Symbol n -> Symbol n -> Symbol n
$cmin :: forall n. Ord n => Symbol n -> Symbol n -> Symbol n
min :: Symbol n -> Symbol n -> Symbol n
Ord, Int -> Symbol n -> ShowS
[Symbol n] -> ShowS
Symbol n -> String
(Int -> Symbol n -> ShowS)
-> (Symbol n -> String) -> ([Symbol n] -> ShowS) -> Show (Symbol n)
forall n. Show n => Int -> Symbol n -> ShowS
forall n. Show n => [Symbol n] -> ShowS
forall n. Show n => Symbol n -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall n. Show n => Int -> Symbol n -> ShowS
showsPrec :: Int -> Symbol n -> ShowS
$cshow :: forall n. Show n => Symbol n -> String
show :: Symbol n -> String
$cshowList :: forall n. Show n => [Symbol n] -> ShowS
showList :: [Symbol n] -> ShowS
Show)

-- | Production rules.
type Rules n = Map (Symbol n) [Symbol n]

data Environment n = Environment
  { forall n. Environment n -> Angle n
angleInc    :: Angle n
  , forall n. Environment n -> [TurtleState n]
turtleStack :: [TurtleState n]
  }

push :: TurtleState n -> Environment n -> Environment n
push :: forall n. TurtleState n -> Environment n -> Environment n
push TurtleState n
t (Environment Angle n
a [TurtleState n]
ts) = Angle n -> [TurtleState n] -> Environment n
forall n. Angle n -> [TurtleState n] -> Environment n
Environment Angle n
a (TurtleState n
tTurtleState n -> [TurtleState n] -> [TurtleState n]
forall a. a -> [a] -> [a]
:[TurtleState n]
ts)

pop :: Environment n -> Environment n
pop :: forall n. Environment n -> Environment n
pop (Environment Angle n
a (TurtleState n
_:[TurtleState n]
ts)) = Angle n -> [TurtleState n] -> Environment n
forall n. Angle n -> [TurtleState n] -> Environment n
Environment Angle n
a [TurtleState n]
ts
pop Environment n
_ = String -> Environment n
forall a. HasCallStack => String -> a
error String
"Tried to pop from an empty stack in LSystem"

incAngle :: Num n => n -> Environment n -> Environment n
incAngle :: forall n. Num n => n -> Environment n -> Environment n
incAngle n
n (Environment Angle n
a [TurtleState n]
ts) = Angle n -> [TurtleState n] -> Environment n
forall n. Angle n -> [TurtleState n] -> Environment n
Environment ((n -> n) -> Angle n -> Angle n
forall a b. (a -> b) -> Angle a -> Angle b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (n -> n -> n
forall a. Num a => a -> a -> a
* n
n) Angle n
a) [TurtleState n]
ts

-- | Successive generations of the production rules applied to the
--   starting symbols.
generations :: Ord n => Rules n -> [Symbol n] -> [[Symbol n]]
generations :: forall n. Ord n => Rules n -> [Symbol n] -> [[Symbol n]]
generations Rules n
dict [Symbol n]
syms = ([Symbol n] -> [Symbol n]) -> [Symbol n] -> [[Symbol n]]
forall a. (a -> a) -> a -> [a]
iterate ((Symbol n -> [Symbol n]) -> [Symbol n] -> [Symbol n]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Rules n -> Symbol n -> [Symbol n]
forall {k}. Ord k => Map k [k] -> k -> [k]
produce Rules n
dict)) [Symbol n]
syms
  where
  produce :: Map k [k] -> k -> [k]
produce Map k [k]
d k
s = [k] -> Maybe [k] -> [k]
forall a. a -> Maybe a -> a
fromMaybe [k
s] (k -> Map k [k] -> Maybe [k]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup k
s Map k [k]
d)

-- | Interpret a list of symbols as turtle graphics commands
--   to create a 'TurtleState'. The turtle data is tracked in a Reader monad.
lSystemR :: (Floating n, Ord n) => [Symbol n] -> Reader (Environment n) (TurtleState n)
lSystemR :: forall n.
(Floating n, Ord n) =>
[Symbol n] -> Reader (Environment n) (TurtleState n)
lSystemR [Symbol n]
syms = TurtleState n
-> [Symbol n] -> ReaderT (Environment n) Identity (TurtleState n)
forall {m :: * -> *} {n}.
(Floating n, Ord n, MonadReader (Environment n) m) =>
TurtleState n -> [Symbol n] -> m (TurtleState n)
go TurtleState n
forall n. (Floating n, Ord n) => TurtleState n
startTurtle [Symbol n]
syms
  where
  go :: TurtleState n -> [Symbol n] -> m (TurtleState n)
go TurtleState n
turtle []     = TurtleState n -> m (TurtleState n)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return TurtleState n
turtle
  go TurtleState n
turtle (Symbol n
x:[Symbol n]
xs) = case Symbol n
x of
    Symbol n
F       -> TurtleState n -> [Symbol n] -> m (TurtleState n)
go (n -> TurtleState n -> TurtleState n
forall n.
(Floating n, Ord n) =>
n -> TurtleState n -> TurtleState n
forward n
1 (TurtleState n -> TurtleState n)
-> (TurtleState n -> TurtleState n)
-> TurtleState n
-> TurtleState n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TurtleState n -> TurtleState n
forall n. (Ord n, Floating n) => TurtleState n -> TurtleState n
penDown (TurtleState n -> TurtleState n) -> TurtleState n -> TurtleState n
forall a b. (a -> b) -> a -> b
$ TurtleState n
turtle) [Symbol n]
xs
    Symbol n
G       -> TurtleState n -> [Symbol n] -> m (TurtleState n)
go (n -> TurtleState n -> TurtleState n
forall n.
(Floating n, Ord n) =>
n -> TurtleState n -> TurtleState n
forward n
1 (TurtleState n -> TurtleState n)
-> (TurtleState n -> TurtleState n)
-> TurtleState n
-> TurtleState n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TurtleState n -> TurtleState n
forall n. (Ord n, Floating n) => TurtleState n -> TurtleState n
penUp   (TurtleState n -> TurtleState n) -> TurtleState n -> TurtleState n
forall a b. (a -> b) -> a -> b
$ TurtleState n
turtle) [Symbol n]
xs
    Symbol n
Plus    -> do
      Environment n
env <- m (Environment n)
forall r (m :: * -> *). MonadReader r m => m r
ask
      TurtleState n -> [Symbol n] -> m (TurtleState n)
go (n -> TurtleState n -> TurtleState n
forall n. Floating n => n -> TurtleState n -> TurtleState n
left  (Environment n -> Angle n
forall n. Environment n -> Angle n
angleInc Environment n
env Angle n -> Getting n (Angle n) n -> n
forall s a. s -> Getting a s a -> a
^. Getting n (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
deg) TurtleState n
turtle) [Symbol n]
xs
    Symbol n
Minus   -> do
      Environment n
env <- m (Environment n)
forall r (m :: * -> *). MonadReader r m => m r
ask
      TurtleState n -> [Symbol n] -> m (TurtleState n)
go (n -> TurtleState n -> TurtleState n
forall n. Floating n => n -> TurtleState n -> TurtleState n
right (Environment n -> Angle n
forall n. Environment n -> Angle n
angleInc Environment n
env Angle n -> Getting n (Angle n) n -> n
forall s a. s -> Getting a s a -> a
^. Getting n (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
deg) TurtleState n
turtle) [Symbol n]
xs
    Symbol n
Reverse -> TurtleState n -> [Symbol n] -> m (TurtleState n)
go (n -> TurtleState n -> TurtleState n
forall n. Floating n => n -> TurtleState n -> TurtleState n
left n
180 TurtleState n
turtle) [Symbol n]
xs
    Symbol n
Flip    -> (Environment n -> Environment n)
-> m (TurtleState n) -> m (TurtleState n)
forall a. (Environment n -> Environment n) -> m a -> m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (n -> Environment n -> Environment n
forall n. Num n => n -> Environment n -> Environment n
incAngle (-n
1)) (TurtleState n -> [Symbol n] -> m (TurtleState n)
go TurtleState n
turtle [Symbol n]
xs)
    Symbol n
Push    -> (Environment n -> Environment n)
-> m (TurtleState n) -> m (TurtleState n)
forall a. (Environment n -> Environment n) -> m a -> m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (TurtleState n -> Environment n -> Environment n
forall n. TurtleState n -> Environment n -> Environment n
push (TurtleState n -> TurtleState n
forall n. (Ord n, Floating n) => TurtleState n -> TurtleState n
penUp TurtleState n
turtle)) (TurtleState n -> [Symbol n] -> m (TurtleState n)
go TurtleState n
turtle [Symbol n]
xs)
    Symbol n
Pop     -> do
      Environment n
env <- m (Environment n)
forall r (m :: * -> *). MonadReader r m => m r
ask
      case Environment n -> [TurtleState n]
forall n. Environment n -> [TurtleState n]
turtleStack Environment n
env of
        []    -> String -> m (TurtleState n)
forall a. HasCallStack => String -> a
error String
"Nothing to pop"
        (TurtleState n
t:[TurtleState n]
_) -> (Environment n -> Environment n)
-> m (TurtleState n) -> m (TurtleState n)
forall a. (Environment n -> Environment n) -> m a -> m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local Environment n -> Environment n
forall n. Environment n -> Environment n
pop (m (TurtleState n) -> m (TurtleState n))
-> m (TurtleState n) -> m (TurtleState n)
forall a b. (a -> b) -> a -> b
$ TurtleState n -> [Symbol n] -> m (TurtleState n)
go (TurtleState n
t { currTrail = currTrail turtle
                                   , paths = paths turtle}) [Symbol n]
xs
    Width n
w -> TurtleState n -> [Symbol n] -> m (TurtleState n)
go (Measure n -> TurtleState n -> TurtleState n
forall n.
(Ord n, Floating n) =>
Measure n -> TurtleState n -> TurtleState n
setPenWidth ((n -> n -> n
forall a. Num a => a -> a -> a
* (n
1n -> n -> n
forall a. Num a => a -> a -> a
+n
w)) (n -> n) -> Measure n -> Measure n
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (PenStyle n -> Measure n
forall n. PenStyle n -> Measure n
penWidth (PenStyle n -> Measure n)
-> (TurtleState n -> PenStyle n) -> TurtleState n -> Measure n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TurtleState n -> PenStyle n
forall n. TurtleState n -> PenStyle n
currPenStyle (TurtleState n -> Measure n) -> TurtleState n -> Measure n
forall a b. (a -> b) -> a -> b
$ TurtleState n
turtle))
                               TurtleState n
turtle) [Symbol n]
xs
    Delta n
d -> (Environment n -> Environment n)
-> m (TurtleState n) -> m (TurtleState n)
forall a. (Environment n -> Environment n) -> m a -> m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (n -> Environment n -> Environment n
forall n. Num n => n -> Environment n -> Environment n
incAngle (n
1n -> n -> n
forall a. Num a => a -> a -> a
+n
d)) (TurtleState n -> [Symbol n] -> m (TurtleState n)
go TurtleState n
turtle [Symbol n]
xs)
    Symbol n
_       -> TurtleState n -> [Symbol n] -> m (TurtleState n)
go TurtleState n
turtle [Symbol n]
xs

-- | Create a 'TurtelState' using n iterations of the rules with given axiom symbols
--   and the angle increment, delta. The first segment is in the unitX direction.
lSystem :: (Floating n, Ord n)
         => Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem :: forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n Angle n
delta [Symbol n]
axiom Rules n
rules =
  Reader (Environment n) (TurtleState n)
-> Environment n -> TurtleState n
forall r a. Reader r a -> r -> a
runReader ([Symbol n] -> Reader (Environment n) (TurtleState n)
forall n.
(Floating n, Ord n) =>
[Symbol n] -> Reader (Environment n) (TurtleState n)
lSystemR (Rules n -> [Symbol n] -> [[Symbol n]]
forall n. Ord n => Rules n -> [Symbol n] -> [[Symbol n]]
generations Rules n
rules [Symbol n]
axiom [[Symbol n]] -> Int -> [Symbol n]
forall a. HasCallStack => [a] -> Int -> a
!! Int
n)) (Angle n -> [TurtleState n] -> Environment n
forall n. Angle n -> [TurtleState n] -> Environment n
Environment Angle n
delta [])

-- | Create a path using n iterations of the rules with given axiom symbols
--   and the angle increment, delta. The first segment is in the unitX direction.
--   The styles in the 'TurtleState' are ignored.
lSystemPath :: (Floating n, Ord n)
             => Int -> Angle n -> [Symbol n] -> Rules n -> Path V2 n
lSystemPath :: forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> Path V2 n
lSystemPath Int
n Angle n
delta [Symbol n]
axiom Rules n
rules = TurtleState n -> Path V2 n
forall n. (Floating n, Ord n) => TurtleState n -> Path V2 n
getTurtlePath (TurtleState n -> Path V2 n) -> TurtleState n -> Path V2 n
forall a b. (a -> b) -> a -> b
$ Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n Angle n
delta [Symbol n]
axiom Rules n
rules

-- | Create a diagram using n iterations of the rules with given axiom symbols
--   and the angle increment, delta. The first segment is in the unitX direction.
--   The styles in the 'TurtleState' are applied to the trails in the diagram.
lSystemDiagram :: (TypeableFloat n, Renderable (Path V2 n) b)
                => Int -> Angle n -> [Symbol n] -> Rules n -> QDiagram b V2 n Any
lSystemDiagram :: forall n b.
(TypeableFloat n, Renderable (Path V2 n) b) =>
Int -> Angle n -> [Symbol n] -> Rules n -> QDiagram b V2 n Any
lSystemDiagram Int
n Angle n
delta [Symbol n]
axiom Rules n
rules = TurtleState n -> QDiagram b V2 n Any
forall n b.
(Renderable (Path V2 n) b, TypeableFloat n) =>
TurtleState n -> QDiagram b V2 n Any
getTurtleDiagram (TurtleState n -> QDiagram b V2 n Any)
-> TurtleState n -> QDiagram b V2 n Any
forall a b. (a -> b) -> a -> b
$ Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n Angle n
delta [Symbol n]
axiom Rules n
rules

symbol :: Fractional n => Char -> Symbol n
symbol :: forall n. Fractional n => Char -> Symbol n
symbol Char
'F' = Symbol n
forall n. Symbol n
F
symbol Char
'G' = Symbol n
forall n. Symbol n
G
symbol Char
'f' = Symbol n
forall n. Symbol n
G
symbol Char
'+' = Symbol n
forall n. Symbol n
Plus
symbol Char
'-' = Symbol n
forall n. Symbol n
Minus
symbol Char
'!' = Symbol n
forall n. Symbol n
Reverse
symbol Char
'~' = Symbol n
forall n. Symbol n
Flip
symbol Char
'[' = Symbol n
forall n. Symbol n
Push
symbol Char
']' = Symbol n
forall n. Symbol n
Pop
symbol Char
'X' = Int -> Symbol n
forall n. Int -> Symbol n
X Int
0
symbol Char
'Y' = Int -> Symbol n
forall n. Int -> Symbol n
X Int
1
symbol Char
'Z' = Int -> Symbol n
forall n. Int -> Symbol n
X Int
2
symbol Char
'A' = Int -> Symbol n
forall n. Int -> Symbol n
X Int
3
symbol Char
'B' = Int -> Symbol n
forall n. Int -> Symbol n
X Int
4
symbol Char
'C' = Int -> Symbol n
forall n. Int -> Symbol n
X Int
5
symbol Char
'<' = n -> Symbol n
forall n. n -> Symbol n
Width n
0.1
symbol Char
'>' = n -> Symbol n
forall n. n -> Symbol n
Width (-n
0.1)
symbol Char
'(' = n -> Symbol n
forall n. n -> Symbol n
Delta n
0.1
symbol Char
')' = n -> Symbol n
forall n. n -> Symbol n
Delta (-n
0.1)
symbol Char
c   = String -> Symbol n
forall a. HasCallStack => String -> a
error (String
"Invalid character " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
c])

symbols :: Fractional n => String -> [Symbol n]
symbols :: forall n. Fractional n => String -> [Symbol n]
symbols = (Char -> Symbol n) -> String -> [Symbol n]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Symbol n
forall n. Fractional n => Char -> Symbol n
symbol

rule :: Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule :: forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
c String
cs = (Char -> Symbol n
forall n. Fractional n => Char -> Symbol n
symbol Char
c, String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
cs)

-------------------------------------------------------------------------------
-- Examples

-- > import Diagrams.TwoD.Path.LSystem
-- > sierpinskiEx = pad 1.1 . centerXY . lwO 4 . stroke . getTurtlePath $ sierpinski 6 :: Diagram B

-- | Sierpinski triangle.
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_sierpinskiEx.svg#diagram=sierpinskiEx&height=400>>
sierpinski :: RealFloat n => Int -> TurtleState n
sierpinski :: forall n. RealFloat n => Int -> TurtleState n
sierpinski Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
60 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
deg) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"FX") Rules n
rules
  where
  rules :: Rules n
rules = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"Z"
                     , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'X' String
"+FY-FX-FY+"
                     , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'Y' String
"-FX+FY+FX-" ]

-- > import Diagrams.TwoD.Path.LSystem
-- > cantorEx = pad 1.1 . centerXY $ cantor 4 :: Diagram B

-- | Cantor dust
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_cantorEx.svg#diagram=cantorEx&width=400>>
cantor :: (Renderable (Path V2 n) b, TypeableFloat n) => Int -> QDiagram b V2 n Any
cantor :: forall n b.
(Renderable (Path V2 n) b, TypeableFloat n) =>
Int -> QDiagram b V2 n Any
cantor Int
n = n -> [QDiagram b V2 n Any] -> QDiagram b V2 n Any
forall n a.
(InSpace V2 n a, Floating n, Juxtaposable a, HasOrigin a,
 Monoid' a) =>
n -> [a] -> a
vsep n
0.05 ([QDiagram b V2 n Any] -> QDiagram b V2 n Any)
-> [QDiagram b V2 n Any] -> QDiagram b V2 n Any
forall a b. (a -> b) -> a -> b
$ (Int -> QDiagram b V2 n Any) -> [Int] -> [QDiagram b V2 n Any]
forall a b. (a -> b) -> [a] -> [b]
map Int -> QDiagram b V2 n Any
dust [Int
0..Int
n]
  where
  dust :: Int -> QDiagram b V2 n Any
dust Int
i =  n -> QDiagram b V2 n Any -> QDiagram b V2 n Any
forall (v :: * -> *) n t.
(InSpace v n t, R2 v, Enveloped t, Transformable t) =>
n -> t -> t
scaleToX n
1 (QDiagram b V2 n Any -> QDiagram b V2 n Any)
-> (QDiagram b V2 n Any -> QDiagram b V2 n Any)
-> QDiagram b V2 n Any
-> QDiagram b V2 n Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Measure n -> QDiagram b V2 n Any -> QDiagram b V2 n Any
forall a n.
(N a ~ n, HasStyle a, Typeable n) =>
Measure n -> a -> a
lw Measure n
forall n. OrderedField n => Measure n
ultraThick (QDiagram b V2 n Any -> QDiagram b V2 n Any)
-> QDiagram b V2 n Any -> QDiagram b V2 n Any
forall a b. (a -> b) -> a -> b
$ Int -> Angle n -> [Symbol n] -> Rules n -> QDiagram b V2 n Any
forall n b.
(TypeableFloat n, Renderable (Path V2 n) b) =>
Int -> Angle n -> [Symbol n] -> Rules n -> QDiagram b V2 n Any
lSystemDiagram Int
i (n
0 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F") Rules n
rules
  rules :: Rules n
rules = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FfF"
                     , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'f' String
"fff" ]

-- > import Diagrams.TwoD.Path.LSystem
-- > dragonEx =
-- >   pad 1.1 . centerXY . rotateBy (1/4) . getTurtleDiagram $ dragon 10 :: Diagram B

-- | Dragon curve
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_dragonEx.svg#diagram=dragonEx&height=400>>
dragon :: RealFloat n => Int -> TurtleState n
dragon :: forall n. RealFloat n => Int -> TurtleState n
dragon Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
90 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
deg) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"FX") Rules n
rules
  where
  rules :: Rules n
rules = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"Z"
                       , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'X' String
"FX+FY+"
                       , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'Y' String
"-FX-FY" ]

-- > import Diagrams.TwoD.Path.LSystem
-- > hexGosperEx = rotateBy (1/4) . getTurtleDiagram $ hexGosper 4 :: Diagram B

-- | Hexagonal Gosper curve
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_hexGosperEx.svg#diagram=hexGosperEx&height=400>>
hexGosper :: RealFloat n => Int -> TurtleState n
hexGosper :: forall n. RealFloat n => Int -> TurtleState n
hexGosper Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
60 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
deg) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"FX") Rules n
hex
  where
  hex :: Rules n
hex = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"Z"
                   , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'X' String
"FX+FY++FY-FX--FXFX-FY+"
                   , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'Y' String
"-FX+FYFY++FY+FX--FX-FY" ]

-- > import Diagrams.TwoD.Path.LSystem
-- > kochIslandEx = lwO 3 . stroke . getTurtlePath $ kochIsland 3 :: Diagram B

-- | Koch Island
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_kochIslandEx.svg#diagram=kochIslandEx&height=400>>
kochIsland :: RealFloat n => Int -> TurtleState n
kochIsland :: forall n. RealFloat n => Int -> TurtleState n
kochIsland Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
90 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
deg) [Symbol n]
axiom Rules n
koch
  where
  koch :: Rules n
koch  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"F-F+F+FF-F-F+F"]
  axiom :: [Symbol n]
axiom = String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F-F-F-F"

-- > import Diagrams.TwoD.Path.LSystem
-- > kochLakeEx =
-- >   pad 1.1 . centerXY . rotateBy (1/4) . getTurtleDiagram $ kochLake 2 :: Diagram B

-- | Koch lake
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_kochLakeEx.svg#diagram=kochLakeEx&height=400>>
kochLake :: RealFloat n => Int -> TurtleState n
kochLake :: forall n. RealFloat n => Int -> TurtleState n
kochLake Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
4 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F+F+F+F") Rules n
lake
  where
  lake :: Rules n
lake = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"F+f-FF+F+FF+Ff+FF-f+FF-F-FF-Ff-FFF"
                    , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'f' String
"ffffff"]

-- > import Diagrams.TwoD.Path.LSystem
-- > koch1Ex = lwO 3 . stroke . getTurtlePath $ koch1 4 :: Diagram B

-- | Koch curve 1
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_koch1Ex.svg#diagram=koch1Ex&height=400>>
koch1 :: RealFloat n => Int -> TurtleState n
koch1 :: forall n. RealFloat n => Int -> TurtleState n
koch1 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
4 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) [Symbol n]
axiom Rules n
koch
  where
  koch :: Rules n
koch  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF-F-F-F-F-F+F"]
  axiom :: [Symbol n]
axiom = String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F-F-F-F"

-- > import Diagrams.TwoD.Path.LSystem
-- > koch2Ex =  getTurtleDiagram $ koch2 4 :: Diagram B

-- | Koch curve 2
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_koch2Ex.svg#diagram=koch2Ex&height=400>>
koch2 :: RealFloat n => Int -> TurtleState n
koch2 :: forall n. RealFloat n => Int -> TurtleState n
koch2 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
4 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) [Symbol n]
axiom Rules n
koch
  where
  koch :: Rules n
koch  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF-F-F-F-FF"]
  axiom :: [Symbol n]
axiom = String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F-F-F-F"

-- > import Diagrams.TwoD.Path.LSystem
-- > koch3Ex = pad 1.1 . centerXY . getTurtleDiagram $ koch3 3 :: Diagram B

-- | Koch curve 3
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_koch3Ex.svg#diagram=koch3Ex&height=400>>
koch3 :: RealFloat n => Int -> TurtleState n
koch3 :: forall n. RealFloat n => Int -> TurtleState n
koch3 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
4 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) [Symbol n]
axiom Rules n
koch
  where
  koch :: Rules n
koch  =[(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF-F+F-F-FF"]
  axiom :: [Symbol n]
axiom = String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F-F-F-F"

-- > import Diagrams.TwoD.Path.LSystem
-- > koch4Ex = pad 1.1 . centerXY . getTurtleDiagram $ koch4 4 :: Diagram B

-- | Koch curve 4
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_koch4Ex.svg#diagram=koch4Ex&height=400>>
koch4 :: RealFloat n => Int -> TurtleState n
koch4 :: forall n. RealFloat n => Int -> TurtleState n
koch4 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
4 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) [Symbol n]
axiom Rules n
koch
  where
  koch :: Rules n
koch  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF-F--F-F"]
  axiom :: [Symbol n]
axiom = String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F-F-F-F"

-- > import Diagrams.TwoD.Path.LSystem
-- > koch5Ex =  getTurtleDiagram $ koch5 5:: Diagram B

-- | Koch curve 5
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_koch5Ex.svg#diagram=koch5Ex&height=400>>
koch5 :: RealFloat n => Int -> TurtleState n
koch5 :: forall n. RealFloat n => Int -> TurtleState n
koch5 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
4 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) [Symbol n]
axiom Rules n
koch
  where
  koch :: Rules n
koch  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"F-FF--F-F"]
  axiom :: [Symbol n]
axiom = String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F-F-F-F"

-- > import Diagrams.TwoD.Path.LSystem
-- > koch6Ex =  getTurtleDiagram $ koch6 4:: Diagram B

-- | Koch curve 6
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_koch6Ex.svg#diagram=koch6Ex&height=400>>
koch6 :: RealFloat n => Int -> TurtleState n
koch6 :: forall n. RealFloat n => Int -> TurtleState n
koch6 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
4 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) [Symbol n]
axiom Rules n
koch
  where
  koch :: Rules n
koch  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"F-F+F-F-F"]
  axiom :: [Symbol n]
axiom = String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F-F-F-F"

-- > import Diagrams.TwoD.Path.LSystem
-- > tree1Ex =  rotateBy (1/4) . getTurtleDiagram $ tree1 5 :: Diagram B

-- | Tree 1
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_tree1Ex.svg#diagram=tree1Ex&width=150>>
tree1 :: RealFloat n => Int -> TurtleState n
tree1 :: forall n. RealFloat n => Int -> TurtleState n
tree1 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
14 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F") Rules n
tree
  where
  tree :: Rules n
tree  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"F[+F]F[-F]F"]

-- > import Diagrams.TwoD.Path.LSystem
-- > tree2Ex =  rotateBy (1/4) . getTurtleDiagram $ tree2 6 :: Diagram B

-- | Tree 2
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_tree2Ex.svg#diagram=tree2Ex&height=400>>
tree2 :: RealFloat n => Int -> TurtleState n
tree2 :: forall n. RealFloat n => Int -> TurtleState n
tree2 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
18 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F") Rules n
tree
  where
  tree :: Rules n
tree  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"F[+>>>F]F[->>>F][>>>F]"]

-- > import Diagrams.TwoD.Path.LSystem
-- > tree3Ex =  rotateBy (1/4) . getTurtleDiagram $ tree3 4 :: Diagram B

-- | Tree 3
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_tree3Ex.svg#diagram=tree3Ex&height=400>>
tree3 :: RealFloat n => Int -> TurtleState n
tree3 :: forall n. RealFloat n => Int -> TurtleState n
tree3 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
16 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"F") Rules n
tree
  where
  tree :: Rules n
tree  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF-[->F+>F+>F]+[+>F->F->F]"]

-- > import Diagrams.TwoD.Path.LSystem
-- > tree4Ex =  rotateBy (1/4) . getTurtleDiagram $ tree4 7 :: Diagram B

-- | Tree 4
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_tree4Ex.svg#diagram=tree4Ex&height=400>>
tree4 :: RealFloat n => Int -> TurtleState n
tree4 :: forall n. RealFloat n => Int -> TurtleState n
tree4 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
18 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"X") Rules n
tree
  where
  tree :: Rules n
tree  = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'X' String
"F>>[+X]F>>[-X]+X"
                     , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF"]

-- > import Diagrams.TwoD.Path.LSystem
-- > tree5Ex =  rotateBy (1/4) . getTurtleDiagram $ tree5 7 :: Diagram B

-- | Tree 5
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_tree5Ex.svg#diagram=tree5Ex&height=400>>
tree5 :: RealFloat n => Int -> TurtleState n
tree5 :: forall n. RealFloat n => Int -> TurtleState n
tree5 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
14 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"X") Rules n
tree
  where
  tree :: Rules n
tree = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'X' String
"F[+>>X][->>X]F>X"
                    , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF"]

-- > import Diagrams.TwoD.Path.LSystem
-- > tree6Ex =  rotateBy (1/4) . getTurtleDiagram $ tree6 5 :: Diagram B

-- | Tree 6
--
--   <<diagrams/src_Diagrams_TwoD_Path_LSystem_tree6Ex.svg#diagram=tree6Ex&height=400>>
tree6 :: RealFloat n => Int -> TurtleState n
tree6 :: forall n. RealFloat n => Int -> TurtleState n
tree6 Int
n = Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
forall n.
(Floating n, Ord n) =>
Int -> Angle n -> [Symbol n] -> Rules n -> TurtleState n
lSystem Int
n (n
1n -> n -> n
forall a. Fractional a => a -> a -> a
/n
16 n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
Iso' (Angle n) n
turn) (String -> [Symbol n]
forall n. Fractional n => String -> [Symbol n]
symbols String
"X") Rules n
tree
  where
  tree :: Rules n
tree = [(Symbol n, [Symbol n])] -> Rules n
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'X' String
"F-[[>>X]+X]+F[+F>>X]-X"
                    , Char -> String -> (Symbol n, [Symbol n])
forall n. Fractional n => Char -> String -> (Symbol n, [Symbol n])
rule Char
'F' String
"FF"]