-----------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Rendering.Chart.Axis.Unit
-- Copyright   :  (c) Tim Docker 2010, 2014
-- License     :  BSD-style (see chart/COPYRIGHT)
--
-- Calculate and render indexed axes

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TupleSections #-}

module Graphics.Rendering.Chart.Axis.Indexed(
    PlotIndex(..),
    autoIndexAxis',
    autoIndexAxis,
    addIndexes,
) where

import Data.Default.Class

import Graphics.Rendering.Chart.Axis.Types

-- | Type for capturing values plotted by index number
--   (ie position in a list) rather than a numerical value.
newtype PlotIndex = PlotIndex { PlotIndex -> Int
plotindex_i :: Int }
  deriving (PlotIndex -> PlotIndex -> Bool
(PlotIndex -> PlotIndex -> Bool)
-> (PlotIndex -> PlotIndex -> Bool) -> Eq PlotIndex
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PlotIndex -> PlotIndex -> Bool
== :: PlotIndex -> PlotIndex -> Bool
$c/= :: PlotIndex -> PlotIndex -> Bool
/= :: PlotIndex -> PlotIndex -> Bool
Eq,Eq PlotIndex
Eq PlotIndex =>
(PlotIndex -> PlotIndex -> Ordering)
-> (PlotIndex -> PlotIndex -> Bool)
-> (PlotIndex -> PlotIndex -> Bool)
-> (PlotIndex -> PlotIndex -> Bool)
-> (PlotIndex -> PlotIndex -> Bool)
-> (PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex -> PlotIndex)
-> Ord PlotIndex
PlotIndex -> PlotIndex -> Bool
PlotIndex -> PlotIndex -> Ordering
PlotIndex -> PlotIndex -> PlotIndex
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PlotIndex -> PlotIndex -> Ordering
compare :: PlotIndex -> PlotIndex -> Ordering
$c< :: PlotIndex -> PlotIndex -> Bool
< :: PlotIndex -> PlotIndex -> Bool
$c<= :: PlotIndex -> PlotIndex -> Bool
<= :: PlotIndex -> PlotIndex -> Bool
$c> :: PlotIndex -> PlotIndex -> Bool
> :: PlotIndex -> PlotIndex -> Bool
$c>= :: PlotIndex -> PlotIndex -> Bool
>= :: PlotIndex -> PlotIndex -> Bool
$cmax :: PlotIndex -> PlotIndex -> PlotIndex
max :: PlotIndex -> PlotIndex -> PlotIndex
$cmin :: PlotIndex -> PlotIndex -> PlotIndex
min :: PlotIndex -> PlotIndex -> PlotIndex
Ord,Int -> PlotIndex
PlotIndex -> Int
PlotIndex -> [PlotIndex]
PlotIndex -> PlotIndex
PlotIndex -> PlotIndex -> [PlotIndex]
PlotIndex -> PlotIndex -> PlotIndex -> [PlotIndex]
(PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex)
-> (Int -> PlotIndex)
-> (PlotIndex -> Int)
-> (PlotIndex -> [PlotIndex])
-> (PlotIndex -> PlotIndex -> [PlotIndex])
-> (PlotIndex -> PlotIndex -> [PlotIndex])
-> (PlotIndex -> PlotIndex -> PlotIndex -> [PlotIndex])
-> Enum PlotIndex
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: PlotIndex -> PlotIndex
succ :: PlotIndex -> PlotIndex
$cpred :: PlotIndex -> PlotIndex
pred :: PlotIndex -> PlotIndex
$ctoEnum :: Int -> PlotIndex
toEnum :: Int -> PlotIndex
$cfromEnum :: PlotIndex -> Int
fromEnum :: PlotIndex -> Int
$cenumFrom :: PlotIndex -> [PlotIndex]
enumFrom :: PlotIndex -> [PlotIndex]
$cenumFromThen :: PlotIndex -> PlotIndex -> [PlotIndex]
enumFromThen :: PlotIndex -> PlotIndex -> [PlotIndex]
$cenumFromTo :: PlotIndex -> PlotIndex -> [PlotIndex]
enumFromTo :: PlotIndex -> PlotIndex -> [PlotIndex]
$cenumFromThenTo :: PlotIndex -> PlotIndex -> PlotIndex -> [PlotIndex]
enumFromThenTo :: PlotIndex -> PlotIndex -> PlotIndex -> [PlotIndex]
Enum,Integer -> PlotIndex
PlotIndex -> PlotIndex
PlotIndex -> PlotIndex -> PlotIndex
(PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex)
-> (Integer -> PlotIndex)
-> Num PlotIndex
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: PlotIndex -> PlotIndex -> PlotIndex
+ :: PlotIndex -> PlotIndex -> PlotIndex
$c- :: PlotIndex -> PlotIndex -> PlotIndex
- :: PlotIndex -> PlotIndex -> PlotIndex
$c* :: PlotIndex -> PlotIndex -> PlotIndex
* :: PlotIndex -> PlotIndex -> PlotIndex
$cnegate :: PlotIndex -> PlotIndex
negate :: PlotIndex -> PlotIndex
$cabs :: PlotIndex -> PlotIndex
abs :: PlotIndex -> PlotIndex
$csignum :: PlotIndex -> PlotIndex
signum :: PlotIndex -> PlotIndex
$cfromInteger :: Integer -> PlotIndex
fromInteger :: Integer -> PlotIndex
Num,Num PlotIndex
Ord PlotIndex
(Num PlotIndex, Ord PlotIndex) =>
(PlotIndex -> Rational) -> Real PlotIndex
PlotIndex -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
$ctoRational :: PlotIndex -> Rational
toRational :: PlotIndex -> Rational
Real,Enum PlotIndex
Real PlotIndex
(Real PlotIndex, Enum PlotIndex) =>
(PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex -> PlotIndex)
-> (PlotIndex -> PlotIndex -> (PlotIndex, PlotIndex))
-> (PlotIndex -> PlotIndex -> (PlotIndex, PlotIndex))
-> (PlotIndex -> Integer)
-> Integral PlotIndex
PlotIndex -> Integer
PlotIndex -> PlotIndex -> (PlotIndex, PlotIndex)
PlotIndex -> PlotIndex -> PlotIndex
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: PlotIndex -> PlotIndex -> PlotIndex
quot :: PlotIndex -> PlotIndex -> PlotIndex
$crem :: PlotIndex -> PlotIndex -> PlotIndex
rem :: PlotIndex -> PlotIndex -> PlotIndex
$cdiv :: PlotIndex -> PlotIndex -> PlotIndex
div :: PlotIndex -> PlotIndex -> PlotIndex
$cmod :: PlotIndex -> PlotIndex -> PlotIndex
mod :: PlotIndex -> PlotIndex -> PlotIndex
$cquotRem :: PlotIndex -> PlotIndex -> (PlotIndex, PlotIndex)
quotRem :: PlotIndex -> PlotIndex -> (PlotIndex, PlotIndex)
$cdivMod :: PlotIndex -> PlotIndex -> (PlotIndex, PlotIndex)
divMod :: PlotIndex -> PlotIndex -> (PlotIndex, PlotIndex)
$ctoInteger :: PlotIndex -> Integer
toInteger :: PlotIndex -> Integer
Integral,Int -> PlotIndex -> ShowS
[PlotIndex] -> ShowS
PlotIndex -> String
(Int -> PlotIndex -> ShowS)
-> (PlotIndex -> String)
-> ([PlotIndex] -> ShowS)
-> Show PlotIndex
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PlotIndex -> ShowS
showsPrec :: Int -> PlotIndex -> ShowS
$cshow :: PlotIndex -> String
show :: PlotIndex -> String
$cshowList :: [PlotIndex] -> ShowS
showList :: [PlotIndex] -> ShowS
Show)

instance PlotValue PlotIndex where
    toValue :: PlotIndex -> Double
toValue (PlotIndex Int
i) = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i
    fromValue :: Double -> PlotIndex
fromValue             = Int -> PlotIndex
PlotIndex (Int -> PlotIndex) -> (Double -> Int) -> Double -> PlotIndex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round
    autoAxis :: AxisFn PlotIndex
autoAxis              = [String] -> AxisFn PlotIndex
forall i. Integral i => [String] -> AxisFn i
autoIndexAxis []

-- | Augment a list of values with index numbers for plotting.
addIndexes :: [a] -> [(PlotIndex,a)]
addIndexes :: forall a. [a] -> [(PlotIndex, a)]
addIndexes = (Int -> a -> (PlotIndex, a)) -> [Int] -> [a] -> [(PlotIndex, a)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
n a
x -> (Int -> PlotIndex
PlotIndex Int
n, a
x)) [Int
0..]

-- | Create an axis for values indexed by position. The
--   list of strings are the labels to be used.
autoIndexAxis' :: Integral i => Bool -> [String] -> AxisFn i
autoIndexAxis' :: forall i. Integral i => Bool -> [String] -> AxisFn i
autoIndexAxis' Bool
tks [String]
labels [i]
vs = AxisData {
    _axis_visibility :: AxisVisibility
_axis_visibility = AxisVisibility
forall a. Default a => a
def { _axis_show_ticks = False },
    _axis_viewport :: Range -> i -> Double
_axis_viewport = Range -> i -> Double
forall {a}. Integral a => Range -> a -> Double
vport,
    _axis_tropweiv :: Range -> Double -> i
_axis_tropweiv = Range -> Double -> i
invport,
    _axis_ticks :: [(i, Double)]
_axis_ticks    = if Bool
tks then (i -> (i, Double)) -> [i] -> [(i, Double)]
forall a b. (a -> b) -> [a] -> [b]
map (, Double
5) ([i] -> [(i, Double)]) -> [i] -> [(i, Double)]
forall a b. (a -> b) -> a -> b
$ Int -> [i] -> [i]
forall a. Int -> [a] -> [a]
take ([String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
labels) [i
0..] else [],
    _axis_labels :: [[(i, String)]]
_axis_labels   = [((i, String) -> Bool) -> [(i, String)] -> [(i, String)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(i
i,String
_) -> i
i i -> i -> Bool
forall a. Ord a => a -> a -> Bool
>= i
imin Bool -> Bool -> Bool
&& i
i i -> i -> Bool
forall a. Ord a => a -> a -> Bool
<= i
imax)
                             ([i] -> [String] -> [(i, String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [i
0..] [String]
labels)],
    _axis_grid :: [i]
_axis_grid     = []
    }
  where
    vport :: Range -> a -> Double
vport Range
r a
i = (Double -> Double) -> Range -> Range -> Double -> Double
forall a. (a -> Double) -> (a, a) -> Range -> a -> Double
linMap Double -> Double
forall a. a -> a
id ( i -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral i
imin Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.5
                          , i -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral i
imax Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.5) Range
r (a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
i)
    invport :: Range -> Double -> i
invport = (Double -> i) -> (i -> Double) -> (i, i) -> Range -> Double -> i
forall a.
(Double -> a) -> (a -> Double) -> (a, a) -> Range -> Double -> a
invLinMap Double -> i
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round i -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (i
imin, i
imax)
    imin :: i
imin = [i] -> i
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [i]
vs
    imax :: i
imax = [i] -> i
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [i]
vs

autoIndexAxis :: Integral i => [String] -> AxisFn i
autoIndexAxis :: forall i. Integral i => [String] -> AxisFn i
autoIndexAxis = Bool -> [String] -> AxisFn i
forall i. Integral i => Bool -> [String] -> AxisFn i
autoIndexAxis' Bool
False