This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.
README LSystem

LSystem.Turtle

Turtle graphics consists of 4 states:

type State
    = D -- | Draw forward
    | S -- | Skip foward without drawing
    | L -- | Turn left by some degrees
    | R -- | Turn right by some degrees

(In formal literature, it is known as F, f, -, and + respectively.)

Given a starting point and an angle, you can iterate through a list of States and create a generative drawing.

For example, the following ruleset applied 3 times will generate this:

rule : LSystem.Rule State
rule state =
    case state of
        D ->
            [ D, D, R, D, L, D, R, D, R, D, D ]

        S ->
            [ S ]

        L ->
            [ L ]

        R ->
            [ R ]

If you want a complete example of how this can be used in the Elm Architecture, see https://github.com/creative/elm-generative/blob/master/example/Turtle.elm

Module functions

type State = D -- | Draw forward | S -- | Skip foward without drawing | L -- | Turn left by some degrees | R -- | Turn right by some degrees | A -- | Ignored by the drawing rules | B -- | Ignored by the drawing rules | C -- | Ignored by the drawing rules

Turtle consists of 4 primary states.

  • D -- Draw forward
  • S -- Skip foward without drawing
  • L -- Turn left by some degrees
  • R -- Turn right by some degrees

We also supply additional states A, B, and C, which are ignored during drawing. They are useful for constructing rulesets only.

turtle : List State -> Float -> List Segment

Transforms a list of States into Svg.Path d-compatible property strings. This requires a starting point and a starting angle.

You can use the Svg.PathD library's d_ to draw segments as a SVG attribute:

import Svg.PathD as PathD exposing (d_)

...


Svg.path
    [ d_ <| turtle [ D, R, D, R, D, R, D ] 90
    ]
    []
module LSystem.Turtle exposing (..)

{-| Turtle graphics consists of 4 states:

    type State
        = D -- | Draw forward
        | S -- | Skip foward without drawing
        | L -- | Turn left by some degrees
        | R -- | Turn right by some degrees

(In formal literature, it is known as `F`, `f`, `-`, and `+` respectively.)

Given a starting point and an angle, you can iterate through a list of `State`s
and create a generative drawing.

For example, the following ruleset applied 3 times will generate [this](https://twitter.com/Xavier_Ho/status/995651719064252416):

    rule : LSystem.Rule State
    rule state =
        case state of
            D ->
                [ D, D, R, D, L, D, R, D, R, D, D ]

            S ->
                [ S ]

            L ->
                [ L ]

            R ->
                [ R ]

If you want a complete example of how this can be used in the Elm Architecture,
see <https://github.com/creative/elm-generative/blob/master/example/Turtle.elm>


# Module functions

@docs State, turtle

-}

import List.Extra exposing (mapAccuml)
import Svg.PathD as PathD exposing (Segment)


{-| Turtle consists of 4 primary states.

  - D -- Draw forward
  - S -- Skip foward without drawing
  - L -- Turn left by some degrees
  - R -- Turn right by some degrees

We also supply additional states `A`, `B`, and `C`, which are ignored during
drawing. They are useful for constructing rulesets only.

-}
type State
    = D -- | Draw forward
    | S -- | Skip foward without drawing
    | L -- | Turn left by some degrees
    | R -- | Turn right by some degrees
    | A -- | Ignored by the drawing rules
    | B -- | Ignored by the drawing rules
    | C -- | Ignored by the drawing rules


{-| Transforms a list of `State`s into `Svg.Path` `d`-compatible property
strings. This requires a starting point and a starting angle.

You can use the `Svg.PathD` library's [`d_`](http://package.elm-lang.org/packages/spaxe/svg-pathd/1.0.1/Svg-PathD#d_)
to draw segments as a SVG attribute:

    import Svg.PathD as PathD exposing (d_)

    ...


    Svg.path
        [ d_ <| turtle [ D, R, D, R, D, R, D ] 90
        ]
        []

-}
turtle : List State -> Float -> List Segment
turtle states dAngle =
    let
        move ( x, y ) a =
            ( x + cos (degrees a), y + sin (degrees a) )

        next ( p, a ) state =
            case state of
                D ->
                    ( ( move p a, a ), [ PathD.L (move p a) ] )

                S ->
                    ( ( move p a, a ), [ PathD.M (move p a) ] )

                L ->
                    ( ( p, a - dAngle ), [] )

                R ->
                    ( ( p, a + dAngle ), [] )

                A ->
                    ( ( p, a ), [] )

                B ->
                    ( ( p, a ), [] )

                C ->
                    ( ( p, a ), [] )
    in
        List.concat (Tuple.second <| mapAccuml next ( (0, 0), 0 ) states)