File: Lines.hs

package info (click to toggle)
haskell-chart 1.9.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 384 kB
  • sloc: haskell: 4,680; makefile: 3
file content (102 lines) | stat: -rw-r--r-- 3,271 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
-----------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Rendering.Chart.Plot.Lines
-- Copyright   :  (c) Tim Docker 2006, 2014
-- License     :  BSD-style (see chart/COPYRIGHT)
--
-- Line plots
--
{-# LANGUAGE TemplateHaskell #-}

module Graphics.Rendering.Chart.Plot.Lines(
    PlotLines(..),
    defaultPlotLineStyle,
    hlinePlot,
    vlinePlot,

    plot_lines_title,
    plot_lines_style,
    plot_lines_values,
    plot_lines_limit_values,
) where

import Control.Lens
import Graphics.Rendering.Chart.Geometry
import Graphics.Rendering.Chart.Drawing
import Graphics.Rendering.Chart.Plot.Types
import Data.Colour (opaque)
import Data.Colour.Names (blue)
import Data.Default.Class

-- | Value defining a series of (possibly disjointed) lines,
--   and a style in which to render them.
data PlotLines x y = PlotLines {
    _plot_lines_title        :: String,
    _plot_lines_style        :: LineStyle,

    -- | The lines to be plotted
    _plot_lines_values       :: [[(x,y)]],

    -- | Additional lines to be plotted, specified using
    -- the Limit type to allow referencing the edges of
    -- the plot area.
    _plot_lines_limit_values :: [[(Limit x, Limit y)]]
}

instance ToPlot PlotLines where
    toPlot p = Plot {
        _plot_render     = renderPlotLines p,
        _plot_legend     = [(_plot_lines_title p, renderPlotLegendLines p)],
        _plot_all_points = ( map fst pts ++ xs, map snd pts ++ ys )
    }
      where
        pts = concat (_plot_lines_values p)
        xs = [ x | (LValue x,_) <- concat (_plot_lines_limit_values p)]
        ys = [ y | (_,LValue y) <- concat (_plot_lines_limit_values p)]

renderPlotLines :: PlotLines x y -> PointMapFn x y -> BackendProgram ()
renderPlotLines p pmap = 
  withLineStyle (_plot_lines_style p) $ do
    mapM_ (drawLines (mapXY pmap)) (_plot_lines_values p)
    mapM_ (drawLines pmap) (_plot_lines_limit_values p)
  where
    drawLines mapfn pts = alignStrokePoints (map mapfn pts) >>= strokePointPath 

renderPlotLegendLines :: PlotLines x y -> Rect -> BackendProgram ()
renderPlotLegendLines p (Rect p1 p2) = 
  withLineStyle (_plot_lines_style p) $ do
    let y = (p_y p1 + p_y p2) / 2
    ps <- alignStrokePoints [Point (p_x p1) y, Point (p_x p2) y]
    strokePointPath ps

defaultPlotLineStyle :: LineStyle
defaultPlotLineStyle = (solidLine 1 $ opaque blue){
     _line_cap  = LineCapRound,
     _line_join = LineJoinRound
 }

instance Default (PlotLines x y) where
  def = PlotLines 
    { _plot_lines_title        = ""
    , _plot_lines_style        = defaultPlotLineStyle
    , _plot_lines_values       = []
    , _plot_lines_limit_values = []
    }

-- | Helper function to plot a single horizontal line.
hlinePlot :: String -> LineStyle -> b -> Plot a b
hlinePlot t ls v = toPlot def {
    _plot_lines_title        = t,
    _plot_lines_style        = ls,
    _plot_lines_limit_values = [[(LMin, LValue v),(LMax, LValue v)]]
    }

-- | Helper function to plot a single vertical line.
vlinePlot :: String -> LineStyle -> a -> Plot a b
vlinePlot t ls v = toPlot def {
    _plot_lines_title        = t,
    _plot_lines_style        = ls,
    _plot_lines_limit_values = [[(LValue v,LMin),(LValue v,LMax)]]
    }

$( makeLenses ''PlotLines )