{-# LANGUAGE DeriveDataTypeable        #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts          #-}
{-# LANGUAGE FlexibleInstances         #-}
{-# LANGUAGE MultiParamTypeClasses     #-}
{-# LANGUAGE RankNTypes                #-}
{-# LANGUAGE RecordWildCards           #-}
{-# LANGUAGE TypeFamilies              #-}
{-# LANGUAGE FunctionalDependencies    #-}
{-# LANGUAGE ViewPatterns    #-}
{-# LANGUAGE ScopedTypeVariables    #-}

{-# LANGUAGE UndecidableInstances      #-}

{-# LANGUAGE StandaloneDeriving        #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Plots.Types.Line
-- Copyright   :  (C) 2016 Christopher Chalmers
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Christopher Chalmers
-- Stability   :  experimental
-- Portability :  non-portable
--
-- A pie plot is a circular statistical graphic, which is divided into
-- slices to illustrate numerical proportion.
--
-- <<diagrams/src_Plots_Types_Pie_piePlotExample.svg#diagram=piePlotExample&height=350>>
--
-- (see 'piePlot' example for code to make this plot)
--
----------------------------------------------------------------------------

module Plots.Types.Pie
  ( -- * Pie plot
    PieState
  , piePlot
  , piePlot'
  , onWedges
  , wedgeKeys

    -- * Wedges
  , Wedge
  , mkWedge
  , HasWedge (..)
  , wedgePlot

  ) where

import           Control.Monad.State.Lazy

import           Data.Typeable
import qualified Data.Foldable as F
import qualified Data.List as List

import           Diagrams.Coordinates.Isomorphic
import           Diagrams.Coordinates.Polar
import           Diagrams.Prelude hiding (r2)

import           Plots.Style
import           Plots.Types
import           Plots.Axis

------------------------------------------------------------------------
-- Pie wedge
------------------------------------------------------------------------

-- | Contains information to draw a single wedge of a pie. It is not
--   intended to be drawn directly. Instead use 'piePlot'.
data Wedge n = Wedge
  { forall n. Wedge n -> n
sEndR   :: n
  , forall n. Wedge n -> n
sStartR :: n
  , forall n. Wedge n -> n
sOffset :: n
  , forall n. Wedge n -> Direction V2 n
sDir    :: Direction V2 n
  , forall n. Wedge n -> Angle n
sWidth  :: Angle n
  } deriving Typeable

type instance V (Wedge n)  = V2
type instance N (Wedge n)  = n

instance RealFloat n => Enveloped (Wedge n) where
  getEnvelope :: Wedge n -> Envelope (V (Wedge n)) (N (Wedge n))
getEnvelope Wedge {n
Direction V2 n
Angle n
sWidth :: Angle n
sDir :: Direction V2 n
sOffset :: n
sStartR :: n
sEndR :: n
sWidth :: forall n. Wedge n -> Angle n
sDir :: forall n. Wedge n -> Direction V2 n
sOffset :: forall n. Wedge n -> n
sStartR :: forall n. Wedge n -> n
sEndR :: forall n. Wedge n -> n
..} = Path V2 n -> Envelope (V (Path V2 n)) (N (Path V2 n))
forall a. Enveloped a => a -> Envelope (V a) (N a)
getEnvelope Path V2 n
shape Envelope V2 n -> (Envelope V2 n -> Envelope V2 n) -> Envelope V2 n
forall a b. a -> (a -> b) -> b
# Vn (Envelope V2 n) -> Envelope V2 n -> Envelope V2 n
forall t. Transformable t => Vn t -> t -> t
translate Vn (Envelope V2 n)
V2 n
off where
    shape :: Path V2 n
shape
      | n
sStartR n -> n -> Bool
forall a. Eq a => a -> a -> Bool
== n
0 = n -> Direction V2 n -> Angle n -> Path V2 n
forall n t.
(InSpace V2 n t, OrderedField n, TrailLike t) =>
n -> Direction V2 n -> Angle n -> t
wedge n
sEndR Direction V2 n
sDir Angle n
sWidth :: Path V2 n
      | Bool
otherwise    = n -> n -> Direction V2 n -> Angle n -> Path V2 n
forall t n.
(TrailLike t, V t ~ V2, N t ~ n, RealFloat n) =>
n -> n -> Direction V2 n -> Angle n -> t
annularWedge n
sEndR n
sStartR Direction V2 n
sDir Angle n
sWidth
    off :: V2 n
off
      | n
sOffset n -> n -> Bool
forall a. Eq a => a -> a -> Bool
== n
0 = V2 n
forall (f :: * -> *) a. (Additive f, Num a) => f a
zero
      | Bool
otherwise    = n
sOffset n -> V2 n -> V2 n
forall (f :: * -> *) a. (Functor f, Num a) => a -> f a -> f a
*^ Direction V2 n -> V2 n
forall (v :: * -> *) n.
(Metric v, Floating n) =>
Direction v n -> v n
fromDir (Angle n -> Direction V2 n -> Direction V2 n
forall n t.
(InSpace V2 n t, Transformable t, Floating n) =>
Angle n -> t -> t
rotate (Angle n
sWidth Angle n -> n -> Angle n
forall (f :: * -> *) a.
(Functor f, Fractional a) =>
f a -> a -> f a
^/ n
2) Direction V2 n
sDir)

instance (TypeableFloat n, Renderable (Path V2 n) b)
    => Plotable (Wedge n) b where
  renderPlotable :: forall (v :: * -> *) n.
InSpace v n (Wedge n) =>
AxisSpec v n -> PlotStyle b v n -> Wedge n -> QDiagram b v n Any
renderPlotable AxisSpec v n
s PlotStyle b v n
sty Wedge {n
Direction V2 n
Angle n
sWidth :: Angle n
sDir :: Direction V2 n
sOffset :: n
sStartR :: n
sEndR :: n
sWidth :: forall n. Wedge n -> Angle n
sDir :: forall n. Wedge n -> Direction V2 n
sOffset :: forall n. Wedge n -> n
sStartR :: forall n. Wedge n -> n
sEndR :: forall n. Wedge n -> n
..} =
    QDiagram b v n Any
shape
      # applyAreaStyle sty
      # translate off
      # transform (s^.specTrans)
    where
      shape :: QDiagram b v n Any
shape
        | n
sStartR n -> n -> Bool
forall a. Eq a => a -> a -> Bool
== n
0 = n -> Direction V2 n -> Angle n -> QDiagram b v n Any
forall n t.
(InSpace V2 n t, OrderedField n, TrailLike t) =>
n -> Direction V2 n -> Angle n -> t
wedge n
sEndR Direction V2 n
sDir Angle n
sWidth
        | Bool
otherwise    = n -> n -> Direction V2 n -> Angle n -> QDiagram b v n Any
forall t n.
(TrailLike t, V t ~ V2, N t ~ n, RealFloat n) =>
n -> n -> Direction V2 n -> Angle n -> t
annularWedge n
sEndR n
sStartR Direction V2 n
sDir Angle n
sWidth
      off :: V2 n
off
        | n
sOffset n -> n -> Bool
forall a. Eq a => a -> a -> Bool
== n
0 = V2 n
forall (f :: * -> *) a. (Additive f, Num a) => f a
zero
        | Bool
otherwise    = n
sOffset n -> V2 n -> V2 n
forall (f :: * -> *) a. (Functor f, Num a) => a -> f a -> f a
*^ Direction V2 n -> V2 n
forall (v :: * -> *) n.
(Metric v, Floating n) =>
Direction v n -> v n
fromDir (Angle n -> Direction V2 n -> Direction V2 n
forall n t.
(InSpace V2 n t, Transformable t, Floating n) =>
Angle n -> t -> t
rotate (Angle n
sWidth Angle n -> n -> Angle n
forall (f :: * -> *) a.
(Functor f, Fractional a) =>
f a -> a -> f a
^/ n
2) Direction V2 n
sDir)

  defLegendPic :: forall (v :: * -> *) n.
InSpace v n (Wedge n) =>
PlotStyle b v n -> Wedge n -> QDiagram b v n Any
defLegendPic PlotStyle b v n
sty Wedge {}
      = n -> QDiagram b v n Any
forall n t. (InSpace V2 n t, TrailLike t) => n -> t
square n
5 QDiagram b v n Any
-> (QDiagram b v n Any -> QDiagram b v n Any) -> QDiagram b v n Any
forall a b. a -> (a -> b) -> b
# PlotStyle b v n -> QDiagram b v n Any -> QDiagram b v n Any
forall a t b.
(SameSpace a t, HasPlotStyle (Const (PlotStyle b (V a) (N a))) a b,
 HasStyle t) =>
a -> t -> t
applyAreaStyle PlotStyle b v n
sty

-- | Create a pie wedge with unit radius, starting at direction @d@ with
--   width @theta@.
mkWedge
  :: Num n
  => Direction V2 n -- ^ starting direction
  -> Angle n        -- ^ width of wedge
  -> Wedge n        -- ^ resulting wedge
mkWedge :: forall n. Num n => Direction V2 n -> Angle n -> Wedge n
mkWedge Direction V2 n
d Angle n
theta = Wedge
  { sEndR :: n
sEndR   = n
1
  , sStartR :: n
sStartR = n
0
  , sOffset :: n
sOffset = n
0
  , sDir :: Direction V2 n
sDir    = Direction V2 n
d
  , sWidth :: Angle n
sWidth  = Angle n
theta
  }

class HasWedge f a where
  -- | Description on how to draw a wedge.
  pieWedge :: LensLike' f a (Wedge (N a))

  -- | The outside radius of the wedge. Default is @1@.
  wedgeOuterRadius :: Functor f => LensLike' f a (N a)
  wedgeOuterRadius = LensLike' f a (Wedge (N a))
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge LensLike' f a (Wedge (N a))
-> ((N a -> f (N a)) -> Wedge (N a) -> f (Wedge (N a)))
-> LensLike' f a (N a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge (N a) -> N a)
-> (Wedge (N a) -> N a -> Wedge (N a))
-> Lens (Wedge (N a)) (Wedge (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Wedge (N a) -> N a
forall n. Wedge n -> n
sEndR (\Wedge (N a)
p N a
r -> Wedge (N a)
p {sEndR :: N a
sEndR = N a
r})

  -- | The inside radius of the wedge. Default is $0$.
  wedgeInnerRadius :: Functor f => LensLike' f a (N a)
  wedgeInnerRadius = LensLike' f a (Wedge (N a))
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge LensLike' f a (Wedge (N a))
-> ((N a -> f (N a)) -> Wedge (N a) -> f (Wedge (N a)))
-> LensLike' f a (N a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge (N a) -> N a)
-> (Wedge (N a) -> N a -> Wedge (N a))
-> Lens (Wedge (N a)) (Wedge (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Wedge (N a) -> N a
forall n. Wedge n -> n
sStartR (\Wedge (N a)
p N a
r -> Wedge (N a)
p {sStartR :: N a
sStartR = N a
r})

  -- | The offset of the wedge from the center.
  wedgeOffset :: Functor f => LensLike' f a (N a)
  wedgeOffset = LensLike' f a (Wedge (N a))
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge LensLike' f a (Wedge (N a))
-> ((N a -> f (N a)) -> Wedge (N a) -> f (Wedge (N a)))
-> LensLike' f a (N a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge (N a) -> N a)
-> (Wedge (N a) -> N a -> Wedge (N a))
-> Lens (Wedge (N a)) (Wedge (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Wedge (N a) -> N a
forall n. Wedge n -> n
sOffset (\Wedge (N a)
p N a
x -> Wedge (N a)
p {sOffset :: N a
sOffset = N a
x})

  -- | The width of the wedge, starting from the 'wedgeDirection'.
  wedgeWidth :: Functor f => LensLike' f a (Angle (N a))
  wedgeWidth = LensLike' f a (Wedge (N a))
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge LensLike' f a (Wedge (N a))
-> ((Angle (N a) -> f (Angle (N a)))
    -> Wedge (N a) -> f (Wedge (N a)))
-> LensLike' f a (Angle (N a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge (N a) -> Angle (N a))
-> (Wedge (N a) -> Angle (N a) -> Wedge (N a))
-> Lens (Wedge (N a)) (Wedge (N a)) (Angle (N a)) (Angle (N a))
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Wedge (N a) -> Angle (N a)
forall n. Wedge n -> Angle n
sWidth (\Wedge (N a)
p Angle (N a)
x -> Wedge (N a)
p {sWidth :: Angle (N a)
sWidth = Angle (N a)
x})

  -- | The inititial direction of the wedge.
  wedgeDirection :: Functor f => LensLike' f a (Direction V2 (N a))
  wedgeDirection = LensLike' f a (Wedge (N a))
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge LensLike' f a (Wedge (N a))
-> ((Direction V2 (N a) -> f (Direction V2 (N a)))
    -> Wedge (N a) -> f (Wedge (N a)))
-> LensLike' f a (Direction V2 (N a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge (N a) -> Direction V2 (N a))
-> (Wedge (N a) -> Direction V2 (N a) -> Wedge (N a))
-> Lens
     (Wedge (N a))
     (Wedge (N a))
     (Direction V2 (N a))
     (Direction V2 (N a))
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Wedge (N a) -> Direction V2 (N a)
forall n. Wedge n -> Direction V2 n
sDir (\Wedge (N a)
p Direction V2 (N a)
x -> Wedge (N a)
p {sDir :: Direction V2 (N a)
sDir = Direction V2 (N a)
x})

instance HasWedge f (Wedge n) where
  pieWedge :: LensLike' f (Wedge n) (Wedge (N (Wedge n)))
pieWedge = LensLike' f (Wedge n) (Wedge (N (Wedge n)))
forall a. a -> a
id

instance (Functor f, HasWedge f a) => HasWedge f (Plot a b) where
  pieWedge :: LensLike' f (Plot a b) (Wedge (N (Plot a b)))
pieWedge = (a -> f a) -> Plot a b -> f (Plot a b)
forall p p' b. SameSpace p p' => Lens (Plot p b) (Plot p' b) p p'
rawPlot ((a -> f a) -> Plot a b -> f (Plot a b))
-> ((Wedge (N a) -> f (Wedge (N a))) -> a -> f a)
-> (Wedge (N a) -> f (Wedge (N a)))
-> Plot a b
-> f (Plot a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge (N a) -> f (Wedge (N a))) -> a -> f a
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge

instance Applicative f => HasWedge f (PieState b n a) where
  pieWedge :: LensLike' f (PieState b n a) (Wedge (N (PieState b n a)))
pieWedge = ([(a, Plot (Wedge n) b)] -> f [(a, Plot (Wedge n) b)])
-> PieState b n a -> f (PieState b n a)
forall b n a. Lens' (PieState b n a) [(a, Plot (Wedge n) b)]
stateMods (([(a, Plot (Wedge n) b)] -> f [(a, Plot (Wedge n) b)])
 -> PieState b n a -> f (PieState b n a))
-> ((Wedge n -> f (Wedge n))
    -> [(a, Plot (Wedge n) b)] -> f [(a, Plot (Wedge n) b)])
-> (Wedge n -> f (Wedge n))
-> PieState b n a
-> f (PieState b n a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, Plot (Wedge n) b) -> f (a, Plot (Wedge n) b))
-> [(a, Plot (Wedge n) b)] -> f [(a, Plot (Wedge n) b)]
forall (f :: * -> *) a b.
Traversable f =>
IndexedTraversal Int (f a) (f b) a b
traversed (((a, Plot (Wedge n) b) -> f (a, Plot (Wedge n) b))
 -> [(a, Plot (Wedge n) b)] -> f [(a, Plot (Wedge n) b)])
-> ((Wedge n -> f (Wedge n))
    -> (a, Plot (Wedge n) b) -> f (a, Plot (Wedge n) b))
-> (Wedge n -> f (Wedge n))
-> [(a, Plot (Wedge n) b)]
-> f [(a, Plot (Wedge n) b)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Plot (Wedge n) b -> f (Plot (Wedge n) b))
-> (a, Plot (Wedge n) b) -> f (a, Plot (Wedge n) b)
forall s t a b. Field2 s t a b => Lens s t a b
_2 ((Plot (Wedge n) b -> f (Plot (Wedge n) b))
 -> (a, Plot (Wedge n) b) -> f (a, Plot (Wedge n) b))
-> ((Wedge n -> f (Wedge n))
    -> Plot (Wedge n) b -> f (Plot (Wedge n) b))
-> (Wedge n -> f (Wedge n))
-> (a, Plot (Wedge n) b)
-> f (a, Plot (Wedge n) b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge n -> f (Wedge n))
-> Plot (Wedge n) b -> f (Plot (Wedge n) b)
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge

instance (Applicative f, Typeable b, v ~ V2, Typeable n)
    => HasWedge f (DynamicPlot b v n) where
  pieWedge :: LensLike' f (DynamicPlot b v n) (Wedge (N (DynamicPlot b v n)))
pieWedge = (forall p b.
(Typeable p, Typeable b) =>
Traversal' (DynamicPlot b (V p) (N p)) (Plot p b)
forall {f :: * -> *}.
Applicative f =>
(Plot (Wedge n) b -> f (Plot (Wedge n) b))
-> DynamicPlot b v n -> f (DynamicPlot b v n)
dynamicPlot :: Traversal' (DynamicPlot b v n) (Plot (Wedge n) b))
           ((Plot (Wedge n) b -> f (Plot (Wedge n) b))
 -> DynamicPlot b v n -> f (DynamicPlot b v n))
-> ((Wedge n -> f (Wedge n))
    -> Plot (Wedge n) b -> f (Plot (Wedge n) b))
-> (Wedge n -> f (Wedge n))
-> DynamicPlot b v n
-> f (DynamicPlot b v n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge n -> f (Wedge n))
-> Plot (Wedge n) b -> f (Plot (Wedge n) b)
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge

instance (v ~ V2, Applicative f, Typeable n)
    => HasWedge f (StyledPlot b v n) where
  pieWedge :: LensLike' f (StyledPlot b v n) (Wedge (N (StyledPlot b v n)))
pieWedge = (forall p b. Typeable p => Traversal' (StyledPlot b (V p) (N p)) p
forall {f :: * -> *}.
Applicative f =>
(Wedge n -> f (Wedge n))
-> StyledPlot b v n -> f (StyledPlot b v n)
styledPlot :: Traversal' (StyledPlot b v n) (Wedge n))

instance (BaseSpace c ~ V2, Settable f, Typeable n)
    => HasWedge f (Axis b c n) where
  pieWedge :: LensLike' f (Axis b c n) (Wedge (N (Axis b c n)))
pieWedge = (StyledPlot b V2 n -> f (StyledPlot b V2 n))
-> Axis b c n -> f (Axis b c n)
forall (c :: * -> *) (v :: * -> *) b n.
(BaseSpace c ~ v) =>
Setter' (Axis b c n) (StyledPlot b v n)
finalPlots ((StyledPlot b V2 n -> f (StyledPlot b V2 n))
 -> Axis b c n -> f (Axis b c n))
-> ((Wedge n -> f (Wedge n))
    -> StyledPlot b V2 n -> f (StyledPlot b V2 n))
-> (Wedge n -> f (Wedge n))
-> Axis b c n
-> f (Axis b c n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Wedge n -> f (Wedge n))
-> StyledPlot b V2 n -> f (StyledPlot b V2 n)
forall (f :: * -> *) a. HasWedge f a => LensLike' f a (Wedge (N a))
pieWedge

------------------------------------------------------------------------
-- Full pie
------------------------------------------------------------------------

-- | The state used to draw a part chart made of multiple pie wedges.
data PieState b n a = PieState
  { forall b n a. PieState b n a -> [(a, Plot (Wedge n) b)]
psMods  :: [(a, Plot (Wedge n) b)] -- non-empty list
  }

type instance V (PieState b n a) = V2
type instance N (PieState b n a) = n

-- internal lens
stateMods :: Lens' (PieState b n a) [(a, Plot (Wedge n) b)]
stateMods :: forall b n a. Lens' (PieState b n a) [(a, Plot (Wedge n) b)]
stateMods = (PieState b n a -> [(a, Plot (Wedge n) b)])
-> (PieState b n a -> [(a, Plot (Wedge n) b)] -> PieState b n a)
-> Lens
     (PieState b n a)
     (PieState b n a)
     [(a, Plot (Wedge n) b)]
     [(a, Plot (Wedge n) b)]
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens PieState b n a -> [(a, Plot (Wedge n) b)]
forall b n a. PieState b n a -> [(a, Plot (Wedge n) b)]
psMods (\PieState b n a
ps [(a, Plot (Wedge n) b)]
ms -> PieState b n a
ps {psMods :: [(a, Plot (Wedge n) b)]
psMods = [(a, Plot (Wedge n) b)]
ms})

-- -- | The direction for the first entry in the pie. Default is 'xDir'.
-- startingDirection :: Lens' (PieState b n a) (Direction V2 n)
-- startingDirection = lens psStart (\ps d -> ps {psStart = d})

-- -- | The ending direction of the final wedge. This can be used to make a
-- finalDirection ::

-- | Modify the state for each wedge given the data entry.
--
--   Some common lenses to use on the 'Wedge':
--
--       * 'plotColour' - change the colour of the bars
--
--       * 'areaStyle' - modify the style of the bars
--
--       * 'key' - add a legend entry for that group of bars
--
--       * 'wedgeOffset' - the offset of the wedge from the center
--
onWedges :: (a -> State (Plot (Wedge n) b) ()) -> State (PieState b n a) ()
onWedges :: forall a n b.
(a -> State (Plot (Wedge n) b) ()) -> State (PieState b n a) ()
onWedges a -> State (Plot (Wedge n) b) ()
f = ([(a, Plot (Wedge n) b)] -> Identity [(a, Plot (Wedge n) b)])
-> PieState b n a -> Identity (PieState b n a)
forall b n a. Lens' (PieState b n a) [(a, Plot (Wedge n) b)]
stateMods (([(a, Plot (Wedge n) b)] -> Identity [(a, Plot (Wedge n) b)])
 -> PieState b n a -> Identity (PieState b n a))
-> ([(a, Plot (Wedge n) b)] -> [(a, Plot (Wedge n) b)])
-> StateT (PieState b n a) Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= ((a, Plot (Wedge n) b) -> (a, Plot (Wedge n) b))
-> [(a, Plot (Wedge n) b)] -> [(a, Plot (Wedge n) b)]
forall a b. (a -> b) -> [a] -> [b]
map (\(a
a, Plot (Wedge n) b
p) -> (a
a, State (Plot (Wedge n) b) () -> Plot (Wedge n) b -> Plot (Wedge n) b
forall s a. State s a -> s -> s
execState (a -> State (Plot (Wedge n) b) ()
f a
a) Plot (Wedge n) b
p))

-- | Add a legend entry for each item given a function that extracts the
--   item's name.
wedgeKeys :: Num n => (a -> String) -> State (PieState b n a) ()
wedgeKeys :: forall n a b. Num n => (a -> String) -> State (PieState b n a) ()
wedgeKeys a -> String
f = (a -> State (Plot (Wedge n) b) ()) -> State (PieState b n a) ()
forall a n b.
(a -> State (Plot (Wedge n) b) ()) -> State (PieState b n a) ()
onWedges ((a -> State (Plot (Wedge n) b) ()) -> State (PieState b n a) ())
-> (a -> State (Plot (Wedge n) b) ()) -> State (PieState b n a) ()
forall a b. (a -> b) -> a -> b
$ \a
a -> String -> State (Plot (Wedge n) b) ()
forall a b (m :: * -> *).
(HasPlotOptions Identity a b, MonadState a m, Num (N a)) =>
String -> m ()
key (a -> String
f a
a)

-- | Make a pie plot from a list of data by making a series of wedge
--   plots.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Pie_piePlotExample.svg#diagram=piePlotExample&height=350>>
--
-- > import Plots
-- >
-- > pieData = [("red", 3), ("blue", 4), ("green", 2), ("purple", 5)]
-- >
-- > piePlotAxis :: Axis B Polar Double
-- > piePlotAxis = polarAxis &~ do
-- >   piePlot pieData snd $ wedgeKeys fst
-- >   hide (axes . traversed)
--
-- > piePlotExample = renderAxis piePlotAxis
piePlot
  :: (MonadState (Axis b Polar n) m,
      Plotable (Wedge n) b,
      F.Foldable f)
  => f a    -- ^ data for each wedge
  -> (a -> n) -- ^ extract weight of each wedge
  -> State (PieState b n a) ()
  -> m ()
piePlot :: forall b n (m :: * -> *) (f :: * -> *) a.
(MonadState (Axis b Polar n) m, Plotable (Wedge n) b,
 Foldable f) =>
f a -> (a -> n) -> State (PieState b n a) () -> m ()
piePlot (f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList -> [a]
as) a -> n
f State (PieState b n a) ()
st = [Plot (Wedge n) b] -> (Plot (Wedge n) b -> m ()) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
F.forM_ [Plot (Wedge n) b]
ps Plot (Wedge n) b -> m ()
forall (c :: * -> *) n p b (m :: * -> *).
(InSpace (BaseSpace c) n p, MonadState (Axis b c n) m,
 Plotable p b) =>
Plot p b -> m ()
addPlot
  where
    -- calculate pie widths
    ns :: [n]
ns = (a -> n) -> [a] -> [n]
forall a b. (a -> b) -> [a] -> [b]
map a -> n
f [a]
as
    x :: n
x  = [n] -> n
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
F.sum [n]
ns
    wedges :: [Wedge n]
wedges = (Direction V2 n, [Wedge n]) -> [Wedge n]
forall a b. (a, b) -> b
snd ((Direction V2 n, [Wedge n]) -> [Wedge n])
-> (Direction V2 n, [Wedge n]) -> [Wedge n]
forall a b. (a -> b) -> a -> b
$ (Direction V2 n -> a -> (Direction V2 n, Wedge n))
-> Direction V2 n -> [a] -> (Direction V2 n, [Wedge n])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
List.mapAccumR Direction V2 n -> a -> (Direction V2 n, Wedge n)
wedgeAccum Direction V2 n
forall (v :: * -> *) n. (R1 v, Additive v, Num n) => Direction v n
xDir [a]
as
    wedgeAccum :: Direction V2 n -> a -> (Direction V2 n, Wedge n)
wedgeAccum Direction V2 n
d a
a = (Direction V2 n
d', Wedge n
wdg)
      where theta :: Angle n
theta = (a -> n
f a
a n -> n -> n
forall a. Fractional a => a -> a -> a
/ n
x) n -> AReview (Angle n) n -> Angle n
forall b a. b -> AReview a b -> a
@@ AReview (Angle n) n
forall n. Floating n => Iso' (Angle n) n
turn
            d' :: Direction V2 n
d'    = Direction V2 n
d Direction V2 n
-> (Direction V2 n -> Direction V2 n) -> Direction V2 n
forall a b. a -> (a -> b) -> b
# Angle n -> Direction V2 n -> Direction V2 n
forall n t.
(InSpace V2 n t, Transformable t, Floating n) =>
Angle n -> t -> t
rotate Angle n
theta
            wdg :: Wedge n
wdg   = Direction V2 n -> Angle n -> Wedge n
forall n. Num n => Direction V2 n -> Angle n -> Wedge n
mkWedge Direction V2 n
d Angle n
theta

    -- run pie state
    ps :: [Plot (Wedge n) b]
ps  = ((a, Plot (Wedge n) b) -> Plot (Wedge n) b)
-> [(a, Plot (Wedge n) b)] -> [Plot (Wedge n) b]
forall a b. (a -> b) -> [a] -> [b]
map (a, Plot (Wedge n) b) -> Plot (Wedge n) b
forall a b. (a, b) -> b
snd ([(a, Plot (Wedge n) b)] -> [Plot (Wedge n) b])
-> (PieState b n a -> [(a, Plot (Wedge n) b)])
-> PieState b n a
-> [Plot (Wedge n) b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PieState b n a -> [(a, Plot (Wedge n) b)]
forall b n a. PieState b n a -> [(a, Plot (Wedge n) b)]
psMods (PieState b n a -> [Plot (Wedge n) b])
-> PieState b n a -> [Plot (Wedge n) b]
forall a b. (a -> b) -> a -> b
$ State (PieState b n a) () -> PieState b n a -> PieState b n a
forall s a. State s a -> s -> s
execState State (PieState b n a) ()
st PieState b n a
ps0
    ps0 :: PieState b n a
ps0 = PieState { psMods :: [(a, Plot (Wedge n) b)]
psMods = [a] -> [Plot (Wedge n) b] -> [(a, Plot (Wedge n) b)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a]
as ((Wedge n -> Plot (Wedge n) b) -> [Wedge n] -> [Plot (Wedge n) b]
forall a b. (a -> b) -> [a] -> [b]
map Wedge n -> Plot (Wedge n) b
forall p b. (Additive (V p), Num (N p)) => p -> Plot p b
mkPlot [Wedge n]
wedges) }

-- | Make a pie plot from list of values without any changes.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Pie_pieExample'.svg#diagram=pieExample'&height=350>>
--
-- > import Plots
-- >
-- > piePlotAxis' :: Axis B Polar Double
-- > piePlotAxis' = polarAxis &~ do
-- >   piePlot' [1,3,5,2]
-- >   wedgeInnerRadius .= 0.5
-- >   hide (axes . traversed)
--
-- > pieExample' = renderAxis piePlotAxis'
piePlot'
  :: (MonadState (Axis b Polar n) m,
      Plotable (Wedge n) b,
      F.Foldable f)
  => f n    -- ^ weight of each wedge
  -> m ()
piePlot' :: forall b n (m :: * -> *) (f :: * -> *).
(MonadState (Axis b Polar n) m, Plotable (Wedge n) b,
 Foldable f) =>
f n -> m ()
piePlot' f n
ns = f n -> (n -> n) -> State (PieState b n n) () -> m ()
forall b n (m :: * -> *) (f :: * -> *) a.
(MonadState (Axis b Polar n) m, Plotable (Wedge n) b,
 Foldable f) =>
f a -> (a -> n) -> State (PieState b n a) () -> m ()
piePlot f n
ns n -> n
forall a. a -> a
id (() -> State (PieState b n n) ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())

------------------------------------------------------------------------
-- Wedge
------------------------------------------------------------------------

-- $ pieplot
-- Pie plots display data as wedges and annular wedges.
-- Pie plots have the following lenses:
--
-- @
-- * 'strokeArc' :: 'Lens'' ('BoxPlot' v n) 'Bool' - False
-- @

-- | Add a single 'PiePlot' to the 'AxisState' from a data set.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Pie_wedgeExample.svg#diagram=wedgeExample&height=350>>
--
-- > import Plots
-- >
-- > wedgePlotAxis :: Axis B Polar Double
-- > wedgePlotAxis = polarAxis &~ do
-- >   wedgePlot xDir (38@@deg) $ key "wedge"
--
-- > wedgeExample = renderAxis wedgePlotAxis
wedgePlot
  :: (v ~ BaseSpace c, v ~ V2,
      PointLike v n (Polar n),
      MonadState (Axis b c n) m,
      Plotable (Wedge n) b
      )
  => Direction V2 n -> Angle n -> State (Plot (Wedge n) b) () -> m ()
wedgePlot :: forall (v :: * -> *) (c :: * -> *) n b (m :: * -> *).
(v ~ BaseSpace c, v ~ V2, PointLike v n (Polar n),
 MonadState (Axis b c n) m, Plotable (Wedge n) b) =>
Direction V2 n -> Angle n -> State (Plot (Wedge n) b) () -> m ()
wedgePlot Direction V2 n
r Angle n
theta = Wedge n -> State (Plot (Wedge n) b) () -> m ()
forall (c :: * -> *) n p b (m :: * -> *).
(InSpace (BaseSpace c) n p, MonadState (Axis b c n) m,
 Plotable p b) =>
p -> State (Plot p b) () -> m ()
addPlotable (Direction V2 n -> Angle n -> Wedge n
forall n. Num n => Direction V2 n -> Angle n -> Wedge n
mkWedge Direction V2 n
r Angle n
theta)