hgis-1.0.0.2: src/GIS/Graphics/Plot.hs
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
-- | Module containing renderable objects and plots for our maps
module GIS.Graphics.Plot ( mkMapR
, mkRenderablePlots
, mkRenderableLens
, mkRenderableLabelled
, plotDataPoints
, labelByLens
, plotLabels
) where
import Control.Arrow
import Data.Colour.Names
import Data.Foldable (fold)
import GIS.Graphics.Types hiding (title)
import GIS.Math.Utils
import GIS.Types
import GIS.Utils
import Graphics.Rendering.Chart
import Graphics.Rendering.Chart.Easy hiding (lens, points)
-- | Given a map, return a `Renderable ()` for use with the
-- """Graphics.Rendering.Char""" module.
mkMapR :: Map -> Renderable ()
mkMapR Map{..} = if _labelEntities
then mkRenderableLabelled _title _labelledDistricts
else mkRenderableLabelled _title $ second (pure "") <$> _labelledDistricts
mkRenderablePlots :: String -> [Plot Double Double] -> Renderable ()
mkRenderablePlots title plots = toRenderable $
layout_title .~ title $ layout_plots .~ plots $ def
mkRenderableLens :: (Show a) => Lens' District a -> [District] -> String -> Renderable ()
mkRenderableLens lens districts title = mkRenderableLabelled title (labelByLens lens districts)
mkRenderableLabelled :: String -> [([Polygon], String)] -> Renderable ()
mkRenderableLabelled title points = mkRenderablePlots title [ plotDataPoints (fst =<< points), plotLabels points ]
-- | Helper function to plot data points as appropriate for a map, i.e. using
-- contiguous lines.
plotDataPoints :: [Polygon] -> Plot Double Double
plotDataPoints points = toPlot $
plot_lines_values .~ points $ plot_lines_style . line_color .~ opaque blue $ plot_lines_title .~ "Border" $ def
-- | Set labels via a lens field.
labelByLens :: (Show a) => Lens' District a -> [District] -> [([Polygon], String)]
labelByLens lens districts = zip (fmap _shape districts) (fmap (show . view lens) districts)
-- | Helper function to plot labels on a map. The ordinate will be plotted at
-- the centroid of the abscissa, which may be outside the polygon if it is
-- concave.
plotLabels :: [([Polygon], String)] -> Plot Double Double
plotLabels points = toPlot texts
where pairs = fmap (flatten . first (shittyCentroid . fold)) points
fontStyle = font_size .~ 15 $ font_weight .~ FontWeightBold $ def
texts = plot_annotation_values .~ pairs $ plot_annotation_style .~ fontStyle $ def