module LSystem.LSystem (LSystem, lSystem, expand, render) where import LSystem.Turtle import Data.Map as Map type Axiom = String type Rules = Map.Map Char String data LSystem = LSystem Axiom Rules deriving (Eq, Show) -- | L-System constructor. lSystem :: Axiom -> [(Char, String)] -> LSystem lSystem a rs = LSystem a (fromList rs) -- | Rule lookup. getRule :: Rules -> Char -> String getRule rs c = Map.findWithDefault [c] c rs -- | Rule application. applyRule :: String -> Rules -> String applyRule a rs = concatMap (getRule rs) a -- | n interations of the specified L-System. expand :: LSystem -> Int -> String expand (LSystem a _ ) 0 = a expand (LSystem a rs) n = expand (LSystem (applyRule a rs) rs) (n-1) -- | State transformer turtle character commands. stateT :: Char -> Turtle -> Turtle stateT '+' = turnRight stateT '-' = turnLeft stateT '|' = turnBack stateT '>' = incrLine stateT '<' = decrLine stateT '[' = push stateT ']' = pop stateT 'f' = forward stateT _ = id -- | Operational turtle character commands. cmd :: (Turtle -> b -> (Turtle, b)) -> Char -> Turtle -> b -> (Turtle, b) cmd f 'F' t i = f t i cmd _ c t i = (stateT c t, i) -- | Fold over an expanded L-system using standard turtle commands. render :: b -> (b -> Pt -> Pt -> b) -> String -> Turtle -> b render i f l t = snd (foldl g (t, i) l) where g (u, j) c = cmd (stepTurtle f) c u j