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

DisplayGraph

DisplayGraph provides tools for constructing graphs and rendering them into SVG.

type alias Graph = { vertices : List Vertex, edges : List Edge }

A graph is s record with two fields - list of vertices and a list of edges.

type alias Vertex = { id : Int, label : String }

A vertex is s record with two fields, an integer id and a string label.

graphDisplay : Float -> Graph -> List (Svg msg)

graphDisplay takes a number and a graph as arguments and returns an SVG representation of the graph. The number is a scale factor. If the scale is 1, the graph is centered in a 2x2 square.

module DisplayGraph exposing (Graph, Vertex, graphDisplay)

{-| DisplayGraph provides tools for constructing graphs and
rendering them into SVG.

@docs Graph, Vertex, graphDisplay

-}

import Vector exposing (Vector)
import List.Extra
import Shape exposing (..)
import ColorRecord exposing (..)
import LineSegment exposing (..)
import Svg exposing (Svg)


{-| A graph is s record with two fields - list of vertices
and a list of edges.
-}
type alias Graph =
    { vertices : List Vertex, edges : List Edge }


{-| A vertex is s record with two fields, an integer id and a string label.
-}
type alias Vertex =
    { id : Int, label : String }


{-| A an edge is a tupe of integers, where the two elements
are the ids of vertices.
-}
type alias Edge =
    ( Int, Int )


vertexColor =
    ColorRecord 0 50 255 0.8


lineSegmentColor =
    ColorRecord 0 0 0 1.0


boundingBoxColor =
    ColorRecord 0 0 255 0.15


getPoints : Graph -> List Vector
getPoints graph =
    let
        points =
            []

        n =
            List.length graph.vertices

        theta =
            2 * 3.14159265 / (toFloat n)

        point =
            rotate (Vector 1 0) theta
    in
        List.range 0 (n - 1)
            |> List.foldl (\k acc -> (acc ++ [ point k ])) []


rotate : Vector -> Float -> Int -> Vector
rotate vector angle k =
    Vector.rotate ((toFloat k) * angle) vector


getIndexedPoints : Graph -> List ( Int, Vector )
getIndexedPoints graph =
    let
        points =
            getPoints graph

        ids =
            graph.vertices |> List.map .id
    in
        List.Extra.zip ids points


getPoint : List ( Int, Vector ) -> Int -> Maybe Vector
getPoint indexedPoints id =
    indexedPoints
        |> List.filter (\item -> (Tuple.first item) == id)
        |> List.head
        |> Maybe.map Tuple.second


edgeToSegment : List ( Int, Vector ) -> Edge -> Maybe Vector.DirectedSegment
edgeToSegment indexedPoints edge =
    let
        maybeA =
            getPoint indexedPoints (Tuple.first edge)

        maybeB =
            getPoint indexedPoints (Tuple.second edge)
    in
        case ( maybeA, maybeB ) of
            ( Just a, Just b ) ->
                Just (Vector.DirectedSegment a b)

            _ ->
                Nothing


renderPoints : List Vector -> List Shape
renderPoints centers =
    let
        size =
            0.5 / (toFloat (List.length centers))
    in
        centers |> List.map (\center -> makeCircle size center)


renderSegments : List Vector.DirectedSegment -> List LineSegment
renderSegments directedSegments =
    directedSegments |> List.map (\edge -> makeLine edge)


makeCircle : Float -> Vector -> Shape
makeCircle size center =
    let
        shapeData =
            ShapeData center (Vector size size) vertexColor vertexColor
    in
        Ellipse shapeData


makeLine : Vector.DirectedSegment -> LineSegment
makeLine segment =
    LineSegment segment.a segment.b 2.5 lineSegmentColor lineSegmentColor


{-| graphDisplay takes a number and a graph as arguments
and returns an SVG representation of the graph. The number is
a scale factor. If the scale is 1, the graph is centered in a 2x2 square.
-}
graphDisplay : Float -> Graph -> List (Svg msg)
graphDisplay scale graph =
    let
        k =
            -- make figure smaller by a scale factor than boudning box
            0.8

        kk =
            -- adjustment for size of circles (not good code)
            0.92

        points =
            getPoints graph

        indexedPoints =
            getIndexedPoints graph

        segments =
            List.map (edgeToSegment indexedPoints) graph.edges
                |> List.filterMap identity

        renderedPoints =
            renderPoints points
                |> List.map (Shape.scaleBy (k * scale))
                |> List.map (Shape.moveBy (Vector (kk * scale) scale))
                |> List.map Shape.draw

        renderedSegments =
            segments
                |> renderSegments
                |> List.map (LineSegment.scaleBy (k * scale))
                |> List.map (LineSegment.moveBy (Vector (kk * scale) scale))
                |> List.map LineSegment.draw
    in
        renderedSegments ++ renderedPoints ++ [ boundingBox scale ]


boundingBoxData =
    { center = (Vector 0 0)
    , dimensions = (Vector 2 2)
    , strokeColor = lineSegmentColor
    , fillColor = boundingBoxColor
    }


boundingBox scale =
    Rect boundingBoxData
        |> Shape.scaleBy (1.2 * scale)
        |> (Shape.moveBy (Vector (scale) (scale)))
        |> Shape.draw