Skip to content

Instantly share code, notes, and snippets.

@hrb90
Last active November 7, 2017 18:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hrb90/22ed85b852e1630bd67cabd8b2781f63 to your computer and use it in GitHub Desktop.
Save hrb90/22ed85b852e1630bd67cabd8b2781f63 to your computer and use it in GitHub Desktop.
purescript-by-example chapter 9 lsystem problem 1
module Example.LSystem where
import Prelude
import Control.Monad.Eff (Eff)
import Data.Array (foldM)
import Data.Maybe (Maybe(..))
import Graphics.Canvas (CANVAS, closePath, fillPath, getCanvasElementById, getContext2D, lineTo, moveTo, setFillStyle, setStrokeStyle, strokePath)
import Math as Math
import Partial.Unsafe (unsafePartial)
lsystem :: forall a m s. Monad m =>
Array a ->
(a -> Array a) ->
(s -> a -> m s) ->
Int ->
s -> m s
lsystem init prod interpret n state = foldM interpret state $ produce init prod n
produce :: forall a. Array a -> (a -> Array a) -> Int -> Array a
produce arr _ 0 = arr
produce arr rules n = produce (arr >>= rules) rules (n - 1)
data Alphabet = L | R | F
type Sentence = Array Alphabet
type State =
{ x :: Number
, y :: Number
, theta :: Number
}
main :: Eff (canvas :: CANVAS) Unit
main = void $ unsafePartial do
Just canvas <- getCanvasElementById "canvas"
ctx <- getContext2D canvas
let
initial :: Sentence
initial = [F, R, R, F, R, R, F, R, R]
productions :: Alphabet -> Sentence
productions L = [L]
productions R = [R]
productions F = [F, L, F, R, R, F, L, F]
interpret :: State -> Alphabet -> Eff (canvas :: CANVAS) State
interpret state L = pure $ state { theta = state.theta - Math.pi / 3.0 }
interpret state R = pure $ state { theta = state.theta + Math.pi / 3.0 }
interpret state F = do
let x = state.x + Math.cos state.theta * 1.5
y = state.y + Math.sin state.theta * 1.5
_ <- lineTo ctx x y
pure { x, y, theta: state.theta }
initialState :: State
initialState = { x: 120.0, y: 200.0, theta: 0.0 }
closeStrokeFill effRow = do
_ <- closePath ctx
_ <- strokePath ctx effRow
fillPath ctx effRow
_ <- setStrokeStyle "#000000" ctx
_ <- setFillStyle "#ff00ff" ctx
_ <- moveTo ctx initialState.x initialState.y
closeStrokeFill $ lsystem initial productions interpret 5 initialState
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment