module Graphics.Rendering.Chart.Axis.Int(
defaultIntAxis,
scaledIntAxis,
autoScaledIntAxis
) where
import Data.List(genericLength)
import Graphics.Rendering.Chart.Geometry
import Graphics.Rendering.Chart.Drawing
import Graphics.Rendering.Chart.Axis.Types
import Graphics.Rendering.Chart.Axis.Floating
instance PlotValue Int where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Integer where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
defaultIntAxis :: (Show a) => LinearAxisParams a
defaultIntAxis = LinearAxisParams {
_la_labelf = show,
_la_nLabels = 5,
_la_nTicks = 10
}
autoScaledIntAxis :: (Integral i, PlotValue i) =>
LinearAxisParams i -> AxisFn i
autoScaledIntAxis lap ps = scaledIntAxis lap (min,max) ps
where
(min,max) = (minimum ps,maximum ps)
scaledIntAxis :: (Integral i, PlotValue i) =>
LinearAxisParams i -> (i,i) -> AxisFn i
scaledIntAxis lap (min,max) ps =
makeAxis (_la_labelf lap) (labelvs,tickvs,gridvs)
where
range [] = (0,1)
range _ | min == max = (fromIntegral $ min1, fromIntegral $ min+1)
| otherwise = (fromIntegral $ min, fromIntegral $ max)
labelvs = stepsInt (fromIntegral $ _la_nLabels lap) r
tickvs = stepsInt (fromIntegral $ _la_nTicks lap)
( fromIntegral $ minimum labelvs
, fromIntegral $ maximum labelvs )
gridvs = labelvs
r = range ps
stepsInt :: Integral a => a -> Range -> [a]
stepsInt nSteps range = bestSize (goodness alt0) alt0 alts
where
bestSize n a (a':as) = let n' = goodness a' in
if n' < n then bestSize n' a' as else a
goodness vs = abs (genericLength vs nSteps)
(alt0:alts) = map (\n -> steps n range) sampleSteps
sampleSteps = [1,2,5] ++ sampleSteps1
sampleSteps1 = [10,20,25,50] ++ map (*10) sampleSteps1
steps size (min,max) = takeWhile (<b) [a,a+size..] ++ [b]
where
a = (floor (min / fromIntegral size)) * size
b = (ceiling (max / fromIntegral size)) * size