-----------------------------------------------------------------------------

-- |

-- Module      :  Graphics.Rendering.Chart.Plot.Pie

-- Copyright   :  (c) Tim Docker 2008, 2014

-- License     :  BSD-style (see chart/COPYRIGHT)

--

-- A  basic pie chart.

--

-- Pie charts are handled different to other plots, in that they

-- have their own layout, and can't be composed with other plots. A

-- pie chart is rendered with code in the following form:

--

-- @

-- values :: [PieItem]

-- values = [...]

-- layout :: PieLayout

-- layout = pie_plot ^: pie_data ^= values

--        $ def

-- renderable = toRenderable layout

-- @

{-# LANGUAGE TemplateHaskell #-}

module Graphics.Rendering.Chart.Plot.Pie(
    PieLayout(..),
    PieChart(..),
    PieItem(..),
    
    pieToRenderable,
    pieChartToRenderable,

    pie_title,
    pie_title_style,
    pie_plot,
    pie_background,
    pie_margin,
    pie_data,
    pie_colors,
    pie_label_style,
    pie_label_line_style,
    pie_start_angle,
    pitem_label,
    pitem_offset,
    pitem_value,

) where
-- original code thanks to Neal Alexander


-- see ../Drawing.hs for why we do not use hiding (moveTo) for

-- lens < 4

import Control.Lens
import Data.Colour
import Data.Colour.Names (white)
import Data.Monoid
import Data.Default.Class
import Control.Monad

import Graphics.Rendering.Chart.Geometry hiding (moveTo)
import qualified Graphics.Rendering.Chart.Geometry as G
import Graphics.Rendering.Chart.Drawing
import Graphics.Rendering.Chart.Renderable
import Graphics.Rendering.Chart.Grid

data PieLayout = PieLayout {
   PieLayout -> String
_pie_title       :: String,
   PieLayout -> FontStyle
_pie_title_style :: FontStyle,
   PieLayout -> PieChart
_pie_plot        :: PieChart,
   PieLayout -> FillStyle
_pie_background  :: FillStyle,
   PieLayout -> Double
_pie_margin      :: Double
}

data PieChart = PieChart {
   PieChart -> [PieItem]
_pie_data             :: [PieItem],
   PieChart -> [AlphaColour Double]
_pie_colors           :: [AlphaColour Double],
   PieChart -> FontStyle
_pie_label_style      :: FontStyle,
   PieChart -> LineStyle
_pie_label_line_style :: LineStyle, 
   PieChart -> Double
_pie_start_angle      :: Double

}

data PieItem = PieItem {
   PieItem -> String
_pitem_label  :: String,
   PieItem -> Double
_pitem_offset :: Double,
   PieItem -> Double
_pitem_value  :: Double
}

instance Default PieChart where
  def :: PieChart
def = PieChart :: [PieItem]
-> [AlphaColour Double]
-> FontStyle
-> LineStyle
-> Double
-> PieChart
PieChart 
    { _pie_data :: [PieItem]
_pie_data             = []
    , _pie_colors :: [AlphaColour Double]
_pie_colors           = [AlphaColour Double]
defaultColorSeq
    , _pie_label_style :: FontStyle
_pie_label_style      = FontStyle
forall a. Default a => a
def
    , _pie_label_line_style :: LineStyle
_pie_label_line_style = Double -> AlphaColour Double -> LineStyle
solidLine Double
1 (AlphaColour Double -> LineStyle)
-> AlphaColour Double -> LineStyle
forall a b. (a -> b) -> a -> b
$ Colour Double -> AlphaColour Double
forall a. Num a => Colour a -> AlphaColour a
opaque Colour Double
forall a. Num a => Colour a
black
    , _pie_start_angle :: Double
_pie_start_angle      = Double
0
    }

instance Default PieItem where
  def :: PieItem
def = String -> Double -> Double -> PieItem
PieItem String
"" Double
0 Double
0

instance Default PieLayout where
  def :: PieLayout
def = PieLayout :: String -> FontStyle -> PieChart -> FillStyle -> Double -> PieLayout
PieLayout 
    { _pie_background :: FillStyle
_pie_background  = AlphaColour Double -> FillStyle
solidFillStyle (AlphaColour Double -> FillStyle)
-> AlphaColour Double -> FillStyle
forall a b. (a -> b) -> a -> b
$ Colour Double -> AlphaColour Double
forall a. Num a => Colour a -> AlphaColour a
opaque Colour Double
forall a. (Ord a, Floating a) => Colour a
white
    , _pie_title :: String
_pie_title       = String
""
    , _pie_title_style :: FontStyle
_pie_title_style = FontStyle
forall a. Default a => a
def { _font_size :: Double
_font_size   = Double
15
                             , _font_weight :: FontWeight
_font_weight = FontWeight
FontWeightBold }
    , _pie_plot :: PieChart
_pie_plot        = PieChart
forall a. Default a => a
def
    , _pie_margin :: Double
_pie_margin      = Double
10
    }

instance ToRenderable PieLayout where
  toRenderable :: PieLayout -> Renderable ()
toRenderable = PickFn () -> Renderable (PickFn Any) -> Renderable ()
forall b a. PickFn b -> Renderable a -> Renderable b
setPickFn PickFn ()
forall a. PickFn a
nullPickFn (Renderable (PickFn Any) -> Renderable ())
-> (PieLayout -> Renderable (PickFn Any))
-> PieLayout
-> Renderable ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PieLayout -> Renderable (PickFn Any)
forall a. PieLayout -> Renderable (PickFn a)
pieToRenderable

pieChartToRenderable :: PieChart -> Renderable (PickFn a)
pieChartToRenderable :: PieChart -> Renderable (PickFn a)
pieChartToRenderable PieChart
p = Renderable :: forall a.
BackendProgram RectSize
-> (RectSize -> BackendProgram (PickFn a)) -> Renderable a
Renderable { minsize :: BackendProgram RectSize
minsize = PieChart -> BackendProgram RectSize
minsizePie PieChart
p
                                    , render :: RectSize -> BackendProgram (PickFn (PickFn a))
render  = PieChart -> RectSize -> BackendProgram (PickFn (PickFn a))
forall a. PieChart -> RectSize -> BackendProgram (PickFn a)
renderPie PieChart
p
                                    }

instance ToRenderable PieChart where
  toRenderable :: PieChart -> Renderable ()
toRenderable = PickFn () -> Renderable (PickFn Any) -> Renderable ()
forall b a. PickFn b -> Renderable a -> Renderable b
setPickFn PickFn ()
forall a. PickFn a
nullPickFn (Renderable (PickFn Any) -> Renderable ())
-> (PieChart -> Renderable (PickFn Any))
-> PieChart
-> Renderable ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PieChart -> Renderable (PickFn Any)
forall a. PieChart -> Renderable (PickFn a)
pieChartToRenderable

pieToRenderable :: PieLayout -> Renderable (PickFn a)
pieToRenderable :: PieLayout -> Renderable (PickFn a)
pieToRenderable PieLayout
p = FillStyle -> Renderable (PickFn a) -> Renderable (PickFn a)
forall a. FillStyle -> Renderable a -> Renderable a
fillBackground (PieLayout -> FillStyle
_pie_background PieLayout
p) (
       Grid (Renderable (PickFn a)) -> Renderable (PickFn a)
forall a. Grid (Renderable a) -> Renderable a
gridToRenderable (Grid (Renderable (PickFn a)) -> Renderable (PickFn a))
-> Grid (Renderable (PickFn a)) -> Renderable (PickFn a)
forall a b. (a -> b) -> a -> b
$ [Grid (Renderable (PickFn a))] -> Grid (Renderable (PickFn a))
forall a. [Grid a] -> Grid a
aboveN
         [ Renderable (PickFn a) -> Grid (Renderable (PickFn a))
forall a. a -> Grid a
tval (Renderable (PickFn a) -> Grid (Renderable (PickFn a)))
-> Renderable (PickFn a) -> Grid (Renderable (PickFn a))
forall a b. (a -> b) -> a -> b
$ (Double, Double, Double, Double)
-> Renderable (PickFn a) -> Renderable (PickFn a)
forall a.
(Double, Double, Double, Double) -> Renderable a -> Renderable a
addMargins (Double
lmDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2,Double
0,Double
0,Double
0) (PickFn (PickFn a) -> Renderable String -> Renderable (PickFn a)
forall b a. PickFn b -> Renderable a -> Renderable b
setPickFn PickFn (PickFn a)
forall a. PickFn a
nullPickFn Renderable String
title)
         , RectSize
-> Grid (Renderable (PickFn a)) -> Grid (Renderable (PickFn a))
forall a. RectSize -> Grid a -> Grid a
weights (Double
1,Double
1) (Grid (Renderable (PickFn a)) -> Grid (Renderable (PickFn a)))
-> Grid (Renderable (PickFn a)) -> Grid (Renderable (PickFn a))
forall a b. (a -> b) -> a -> b
$ Renderable (PickFn a) -> Grid (Renderable (PickFn a))
forall a. a -> Grid a
tval (Renderable (PickFn a) -> Grid (Renderable (PickFn a)))
-> Renderable (PickFn a) -> Grid (Renderable (PickFn a))
forall a b. (a -> b) -> a -> b
$ (Double, Double, Double, Double)
-> Renderable (PickFn a) -> Renderable (PickFn a)
forall a.
(Double, Double, Double, Double) -> Renderable a -> Renderable a
addMargins (Double
lm,Double
lm,Double
lm,Double
lm)
                                             (PieChart -> Renderable (PickFn a)
forall a. PieChart -> Renderable (PickFn a)
pieChartToRenderable (PieChart -> Renderable (PickFn a))
-> PieChart -> Renderable (PickFn a)
forall a b. (a -> b) -> a -> b
$ PieLayout -> PieChart
_pie_plot PieLayout
p)
         ] )
      where
        title :: Renderable String
title = FontStyle
-> HTextAnchor -> VTextAnchor -> String -> Renderable String
label (PieLayout -> FontStyle
_pie_title_style PieLayout
p) HTextAnchor
HTA_Centre VTextAnchor
VTA_Top (PieLayout -> String
_pie_title PieLayout
p)
        lm :: Double
lm    = PieLayout -> Double
_pie_margin PieLayout
p

extraSpace :: PieChart -> BackendProgram (Double, Double)
extraSpace :: PieChart -> BackendProgram RectSize
extraSpace PieChart
p = do
    [RectSize]
textSizes <- (PieItem -> BackendProgram RectSize)
-> [PieItem] -> ProgramT ChartBackendInstr Identity [RectSize]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (String -> BackendProgram RectSize
textDimension (String -> BackendProgram RectSize)
-> (PieItem -> String) -> PieItem -> BackendProgram RectSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PieItem -> String
_pitem_label) (PieChart -> [PieItem]
_pie_data PieChart
p)
    let maxw :: Double
maxw  = (RectSize -> Double -> Double) -> Double -> [RectSize] -> Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Double -> Double -> Double
forall a. Ord a => a -> a -> a
max(Double -> Double -> Double)
-> (RectSize -> Double) -> RectSize -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
.RectSize -> Double
forall a b. (a, b) -> a
fst) Double
0 [RectSize]
textSizes
    let maxh :: Double
maxh  = (RectSize -> Double -> Double) -> Double -> [RectSize] -> Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Double -> Double -> Double
forall a. Ord a => a -> a -> a
max(Double -> Double -> Double)
-> (RectSize -> Double) -> RectSize -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
.RectSize -> Double
forall a b. (a, b) -> b
snd) Double
0 [RectSize]
textSizes
    let maxo :: Double
maxo  = (PieItem -> Double -> Double) -> Double -> [PieItem] -> Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Double -> Double -> Double
forall a. Ord a => a -> a -> a
max(Double -> Double -> Double)
-> (PieItem -> Double) -> PieItem -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PieItem -> Double
_pitem_offset) Double
0 (PieChart -> [PieItem]
_pie_data PieChart
p)
    let extra :: Double
extra = Double
label_rgap Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
label_rlength Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
maxo
    RectSize -> BackendProgram RectSize
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
extra Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
maxw, Double
extra Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
maxh )

minsizePie :: PieChart -> BackendProgram (Double, Double)
minsizePie :: PieChart -> BackendProgram RectSize
minsizePie PieChart
p = do
    (Double
extraw,Double
extrah) <- PieChart -> BackendProgram RectSize
extraSpace PieChart
p
    RectSize -> BackendProgram RectSize
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
extraw Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2, Double
extrah Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2)

renderPie :: PieChart -> (Double, Double) -> BackendProgram (PickFn a)
renderPie :: PieChart -> RectSize -> BackendProgram (PickFn a)
renderPie PieChart
p (Double
w,Double
h) = do
    (Double
extraw,Double
extrah) <- PieChart -> BackendProgram RectSize
extraSpace PieChart
p
    -- let (w,h)  = (p_x p2 - p_x p1, p_y p2 - p_y p1)

    -- let center = Point (p_x p1 + w/2)  (p_y p1 + h/2)

    --

    let center :: Point
center = Double -> Double -> Point
Point (Double
wDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) (Double
hDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)
    let radius :: Double
radius = Double -> Double -> Double
forall a. Ord a => a -> a -> a
min (Double
w Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
extraw) (Double
h Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
extrah) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2

    (Double
 -> (AlphaColour Double, PieItem)
 -> ProgramT ChartBackendInstr Identity Double)
-> Double
-> [(AlphaColour Double, PieItem)]
-> ProgramT ChartBackendInstr Identity ()
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m ()
foldM_ (Point
-> Double
-> Double
-> (AlphaColour Double, PieItem)
-> ProgramT ChartBackendInstr Identity Double
paint Point
center Double
radius) (PieChart -> Double
_pie_start_angle PieChart
p)
           ([AlphaColour Double]
-> [PieItem] -> [(AlphaColour Double, PieItem)]
forall a b. [a] -> [b] -> [(a, b)]
zip (PieChart -> [AlphaColour Double]
_pie_colors PieChart
p) [PieItem]
content)
    PickFn a -> BackendProgram (PickFn a)
forall (m :: * -> *) a. Monad m => a -> m a
return PickFn a
forall a. PickFn a
nullPickFn
 
    where
        -- p1 = Point 0 0 

        -- p2 = Point w h 

        content :: [PieItem]
content = let total :: Double
total = [Double] -> Double
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((PieItem -> Double) -> [PieItem] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map PieItem -> Double
_pitem_value (PieChart -> [PieItem]
_pie_data PieChart
p))
                  in [ PieItem
pitem{_pitem_value :: Double
_pitem_value=PieItem -> Double
_pitem_value PieItem
pitemDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
total}
                     | PieItem
pitem <- PieChart -> [PieItem]
_pie_data PieChart
p ]

        paint :: Point -> Double -> Double -> (AlphaColour Double, PieItem)
              -> BackendProgram Double
        paint :: Point
-> Double
-> Double
-> (AlphaColour Double, PieItem)
-> ProgramT ChartBackendInstr Identity Double
paint Point
center Double
radius Double
a1 (AlphaColour Double
color,PieItem
pitem) = do
            let ax :: Double
ax     = Double
360.0 Double -> Double -> Double
forall a. Num a => a -> a -> a
* PieItem -> Double
_pitem_value PieItem
pitem
            let a2 :: Double
a2     = Double
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
ax Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2)
            let a3 :: Double
a3     = Double
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
ax
            let offset :: Double
offset = PieItem -> Double
_pitem_offset PieItem
pitem

            Point
-> Double
-> Double
-> AlphaColour Double
-> ProgramT ChartBackendInstr Identity ()
pieSlice (Double -> Double -> Point
ray Double
a2 Double
offset) Double
a1 Double
a3 AlphaColour Double
color
            String
-> Double -> Double -> ProgramT ChartBackendInstr Identity ()
pieLabel (PieItem -> String
_pitem_label PieItem
pitem) Double
a2 Double
offset

            Double -> ProgramT ChartBackendInstr Identity Double
forall (m :: * -> *) a. Monad m => a -> m a
return Double
a3

            where
                pieLabel :: String -> Double -> Double -> BackendProgram ()
                pieLabel :: String
-> Double -> Double -> ProgramT ChartBackendInstr Identity ()
pieLabel String
name Double
angle Double
offset = 
                    FontStyle
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a. FontStyle -> BackendProgram a -> BackendProgram a
withFontStyle (PieChart -> FontStyle
_pie_label_style PieChart
p) (ProgramT ChartBackendInstr Identity ()
 -> ProgramT ChartBackendInstr Identity ())
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a b. (a -> b) -> a -> b
$ 
                      LineStyle
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a. LineStyle -> BackendProgram a -> BackendProgram a
withLineStyle (PieChart -> LineStyle
_pie_label_line_style PieChart
p) (ProgramT ChartBackendInstr Identity ()
 -> ProgramT ChartBackendInstr Identity ())
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a b. (a -> b) -> a -> b
$ do
                        let p1 :: Point
p1 = Double -> Double -> Point
ray Double
angle (Double
radiusDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
label_rgapDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
label_rlengthDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
offset)
                        Point
p1a <- Point -> BackendProgram Point
alignStrokePoint Point
p1
                        (Double
tw,Double
_) <- String -> BackendProgram RectSize
textDimension String
name
                        let (Double -> Double
offset',HTextAnchor
anchor) = if Double
angle Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
90 Bool -> Bool -> Bool
|| Double
angle Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
270 
                                              then ((Double
0Double -> Double -> Double
forall a. Num a => a -> a -> a
+),HTextAnchor
HTA_Left)
                                              else ((Double
0Double -> Double -> Double
forall a. Num a => a -> a -> a
-),HTextAnchor
HTA_Right)
                        Point
p0 <- Point -> BackendProgram Point
alignStrokePoint (Point -> BackendProgram Point) -> Point -> BackendProgram Point
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Point
ray Double
angle (Double
radius Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
label_rgapDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
offset)
                        Path -> ProgramT ChartBackendInstr Identity ()
strokePath (Path -> ProgramT ChartBackendInstr Identity ())
-> Path -> ProgramT ChartBackendInstr Identity ()
forall a b. (a -> b) -> a -> b
$ Point -> Path
G.moveTo Point
p0
                                  Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Point -> Path
lineTo Point
p1a
                                  Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' (Point -> Double
p_x Point
p1a Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
offset' (Double
tw Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
label_rgap)) (Point -> Double
p_y Point
p1a)

                        let p2 :: Point
p2 = Point
p1 Point -> Vector -> Point
`pvadd` Double -> Double -> Vector
Vector (Double -> Double
offset' Double
label_rgap) Double
0
                        HTextAnchor
-> VTextAnchor
-> Point
-> String
-> ProgramT ChartBackendInstr Identity ()
drawTextA HTextAnchor
anchor VTextAnchor
VTA_Bottom Point
p2 String
name

                pieSlice :: Point -> Double -> Double -> AlphaColour Double -> BackendProgram ()
                pieSlice :: Point
-> Double
-> Double
-> AlphaColour Double
-> ProgramT ChartBackendInstr Identity ()
pieSlice (Point Double
x Double
y) Double
arc1 Double
arc2 AlphaColour Double
pColor = do
                    let path :: Path
path = Double -> Double -> Double -> Double -> Double -> Path
arc' Double
x Double
y Double
radius (Double -> Double
radian Double
arc1) (Double -> Double
radian Double
arc2)
                            Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' Double
x Double
y
                            Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' Double
x Double
y
                            Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Path
close

                    FillStyle
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a. FillStyle -> BackendProgram a -> BackendProgram a
withFillStyle (AlphaColour Double -> FillStyle
FillStyleSolid AlphaColour Double
pColor) (ProgramT ChartBackendInstr Identity ()
 -> ProgramT ChartBackendInstr Identity ())
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a b. (a -> b) -> a -> b
$ 
                      Path -> ProgramT ChartBackendInstr Identity ()
fillPath Path
path
                    LineStyle
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a. LineStyle -> BackendProgram a -> BackendProgram a
withLineStyle (LineStyle
forall a. Default a => a
def { _line_color :: AlphaColour Double
_line_color = Colour Double -> Double -> AlphaColour Double
forall a. Num a => Colour a -> a -> AlphaColour a
withOpacity Colour Double
forall a. (Ord a, Floating a) => Colour a
white Double
0.1 }) (ProgramT ChartBackendInstr Identity ()
 -> ProgramT ChartBackendInstr Identity ())
-> ProgramT ChartBackendInstr Identity ()
-> ProgramT ChartBackendInstr Identity ()
forall a b. (a -> b) -> a -> b
$ 
                      Path -> ProgramT ChartBackendInstr Identity ()
strokePath Path
path

                ray :: Double -> Double -> Point
                ray :: Double -> Double -> Point
ray Double
angle Double
r = Double -> Double -> Point
Point Double
x' Double
y'
                  where
                    x' :: Double
x'   = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
cos' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x'')
                    y' :: Double
y'   = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
sin' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x'')
                    cos' :: Double
cos' = (Double -> Double
forall a. Floating a => a -> a
cos (Double -> Double) -> (Double -> Double) -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
radian) Double
angle
                    sin' :: Double
sin' = (Double -> Double
forall a. Floating a => a -> a
sin (Double -> Double) -> (Double -> Double) -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
radian) Double
angle
                    -- TODO: is x'' defined in this way to try and avoid

                    --       numerical rounding?

                    x'' :: Double
x''  = (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
x
                    x :: Double
x    = Point -> Double
p_x Point
center
                    y :: Double
y    = Point -> Double
p_y Point
center

                radian :: Double -> Double
radian = (Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
180.0))

label_rgap, label_rlength :: Double
label_rgap :: Double
label_rgap = Double
5
label_rlength :: Double
label_rlength = Double
15

$( makeLenses ''PieLayout )
$( makeLenses ''PieChart )
$( makeLenses ''PieItem )