Newer
Older
fractals / src / Main.elm
@peter peter on 10 Oct 2019 1 KB Built the Koch curve with Elm.
module Main exposing (..)

import Html exposing (..)
import Svg exposing (..)
import Svg.Attributes exposing (..)


type alias Point =
    { x : Float, y : Float }


type alias Line =
    { start : Point, end : Point }


add a b =
    Point (a.x + b.x) (a.y + b.y)


scale s p =
    Point (s * p.x) (s * p.y)


diff start end =
    add end (scale -1 start)


midpoint s line =
    add line.start (scale s (diff line.start line.end))


rotateMinus90Deg p =
    Point p.y -p.x


tip line =
    diff line.start line.end
        |> rotateMinus90Deg
        |> scale (sqrt 3 / 6)
        |> add (midpoint 0.5 line)


kochDivide line =
    [ Line line.start (midpoint (1 / 3) line)
    , Line (midpoint (1 / 3) line) (tip line)
    , Line (tip line) (midpoint (2 / 3) line)
    , Line (midpoint (2 / 3) line) line.end
    ]


kochIteration iterations lineList =
    if iterations == 0 then
        lineList

    else
        List.concatMap kochDivide lineList |> kochIteration (iterations - 1)


lineToSvg : Line -> Svg.Svg msg
lineToSvg line =
    Svg.line
        [ x1 (String.fromFloat line.start.x)
        , y1 (String.fromFloat line.start.y)
        , x2 (String.fromFloat line.end.x)
        , y2 (String.fromFloat line.end.y)
        ]
        []


baseHeight =
    250


startLine =
    Line (Point 0 baseHeight) (Point 400 baseHeight)


main =
    div [ class "tile" ]
        [ h2 [] [ Html.text "Koch" ]
        , div []
            [ svg
                [ width "400px"
                , height "400px"
                , Svg.Attributes.style "fill: none; stroke: purple; stroke-width: 1;"
                ]
                ([ startLine ] |> kochIteration 5 |> List.map lineToSvg)
            ]
        ]