PolarPlot


PolarPlot

A polar plot of sin(2x)cos(2x).

module PolarPlot exposing (main)


import Svg exposing (..)
import Svg.Attributes exposing (..)
import Visualization.List exposing (range)
import Visualization.Scale as Scale exposing (ContinuousScale)
import Visualization.Shape as Shape


w : Float
w =
    900


h : Float
h =
    450


padding : Float
padding =
    30


radius : Float
radius =
    Basics.min w h / 2 - padding


radiusScale : ContinuousScale
radiusScale =
    Scale.linear ( 0, 0.5 ) ( 0, radius )


fn : Float -> Float
fn t =
    sin (2 * t) * cos (2 * t)


data : List (Maybe ( Float, Float ))
data =
    range 0 (2 * pi) 0.01
        |> List.map (\t -> Just ( -t + pi / 2, Scale.convert radiusScale (fn t) ))


spoke : Float -> Svg msg
spoke angle =
    g [ transform ("rotate(" ++ toString -angle ++ ")") ]
        [ line [ x2 (toString radius) ] []
        , text_
            [ radius + 6 |> toString |> x
            , dy ".35em"
            , textAnchor
                (if angle < 270 && angle > 90 then
                    "end"
                 else
                    "inherit"
                )
            , transform
                ((if angle < 270 && angle > 90 then
                    "rotate(180 " ++ toString (radius + 6) ++ ",0)"
                  else
                    ""
                 )
                )
            ]
            [ text (toString angle ++ "°") ]
        ]


radialAxis : Float -> Svg msg
radialAxis radius =
    g []
        [ circle [ Scale.convert radiusScale radius |> toString |> r ] []
        , text_ [ Scale.convert radiusScale radius * -1 - 4 |> toString |> y, transform "rotate(15)", textAnchor "middle" ]
            [ radius |> Scale.tickFormat radiusScale 5 |> text ]
        ]


css : String
css =
    """
    .frame {
      fill: none;
      stroke: #000;
    }

    .axis text {
      font: 10px sans-serif;
    }

    .axis line,
    .axis circle {
      fill: none;
      stroke: #777;
      stroke-dasharray: 1,4;
    }

    .axis :last-of-type circle {
      stroke: #333;
      stroke-dasharray: none;
    }

    .line {
      fill: none;
      stroke: red;
      stroke-width: 1.5px;
    }

    .label {
      font-family:  sans-serif;
    }
  """


main : Svg msg
main =
    svg [ width (toString w ++ "px"), height (toString h ++ "px") ]
        [ Svg.style [] [ text css ]
        , g [ class "label", transform ("translate" ++ toString ( padding * 2, h / 2 )) ]
            [ text_ [ fontSize "20" ] [ text "sin(2x)cos(2x)" ]
            , text_ [ fontSize "12", y "20" ] [ text "A polar plot." ]
            ]
        , g [ transform ("translate" ++ toString ( w / 2 + radius, h / 2 )) ]
            [ Scale.ticks radiusScale 5
                |> List.drop 1
                |> List.map radialAxis
                |> g [ class "r axis" ]
            , range 0 360 30
                |> List.map spoke
                |> g [ class "a axis" ]
            , Svg.path [ d <| Shape.lineRadial Shape.linearCurve data, class "line" ] []
            ]
        ]