----------------------------------------------------------------------------- -- | -- Module : Graphics.Rendering.Chart.Plot.Lines -- Copyright : (c) Tim Docker 2006 -- License : BSD-style (see chart/COPYRIGHT) -- -- Line plots -- {-# OPTIONS_GHC -XTemplateHaskell #-} module Graphics.Rendering.Chart.Plot.Lines( PlotLines(..), defaultPlotLines, defaultPlotLineStyle, hlinePlot, vlinePlot, plot_lines_title, plot_lines_style, plot_lines_values, plot_lines_limit_values, ) where import Data.Accessor.Template import qualified Graphics.Rendering.Cairo as C import Graphics.Rendering.Chart.Types import Graphics.Rendering.Chart.Renderable import Graphics.Rendering.Chart.Plot.Types import Data.Colour (opaque) import Data.Colour.Names (black, blue) -- | 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_ :: CairoLineStyle, -- | 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 -> CRender () renderPlotLines p pmap = preserveCState $ do setLineStyle (plot_lines_style_ p) mapM_ (drawLines (mapXY pmap)) (plot_lines_values_ p) mapM_ (drawLines pmap) (plot_lines_limit_values_ p) where drawLines mapfn pts = strokePath (map mapfn pts) renderPlotLegendLines :: PlotLines x y -> Rect -> CRender () renderPlotLegendLines p r@(Rect p1 p2) = preserveCState $ do setLineStyle (plot_lines_style_ p) let y = (p_y p1 + p_y p2) / 2 strokePath [Point (p_x p1) y, Point (p_x p2) y] defaultPlotLineStyle :: CairoLineStyle defaultPlotLineStyle = (solidLine 1 $ opaque blue){ line_cap_ = C.LineCapRound, line_join_ = C.LineJoinRound } defaultPlotLines :: PlotLines x y defaultPlotLines = 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 -> CairoLineStyle -> b -> Plot a b hlinePlot t ls v = toPlot defaultPlotLines { 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 -> CairoLineStyle -> a -> Plot a b vlinePlot t ls v = toPlot defaultPlotLines { plot_lines_title_ = t, plot_lines_style_ = ls, plot_lines_limit_values_ = [[(LValue v,LMin),(LValue v,LMax)]] } ---------------------------------------------------------------------- -- Template haskell to derive an instance of Data.Accessor.Accessor -- for each field. $( deriveAccessors ''PlotLines )