1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
-----------------------------------------------------------------------------
-- |
-- Module : Graphics.Rendering.Chart.Axis.Int
-- Copyright : (c) Tim Docker 2010, 2014
-- License : BSD-style (see chart/COPYRIGHT)
--
-- Calculate and render integer indexed axes
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Graphics.Rendering.Chart.Axis.Int(
defaultIntAxis,
scaledIntAxis,
autoScaledIntAxis
) where
import Data.List(genericLength)
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word8, Word16, Word32, Word64)
import Graphics.Rendering.Chart.Geometry
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 Int8 where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Int16 where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Int32 where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Int64 where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Word where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Word8 where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Word16 where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Word32 where
toValue = fromIntegral
fromValue = round
autoAxis = autoScaledIntAxis defaultIntAxis
instance PlotValue Word64 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 = map show,
_la_nLabels = 5,
_la_nTicks = 10
}
autoScaledIntAxis :: (Integral i, PlotValue i) =>
LinearAxisParams i -> AxisFn i
autoScaledIntAxis lap ps = scaledIntAxis lap rs ps
where
rs = (minimum ps,maximum ps)
scaledIntAxis :: (Integral i, PlotValue i) =>
LinearAxisParams i -> (i,i) -> AxisFn i
scaledIntAxis lap (minI,maxI) ps =
makeAxis (_la_labelf lap) (labelvs,tickvs,gridvs)
where
range [] = (0,1)
range _ | minI == maxI = (fromIntegral $ minI-1, fromIntegral $ minI+1)
| otherwise = (fromIntegral minI, fromIntegral maxI)
-- labelvs :: [i]
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
bestSize _ _ [] = []
goodness vs = abs (genericLength vs - nSteps)
(alt0:alts) = map (\n -> steps n range) sampleSteps'
-- throw away sampleSteps that are definitely too small as
-- they takes a long time to process
sampleSteps' = let rangeMag = ceiling (snd range - fst range)
(s1,s2) = span (< (rangeMag `div` nSteps)) sampleSteps
in ((reverse . take 5 . reverse) s1) ++ s2
-- generate all possible step sizes
sampleSteps = [1,2,5] ++ sampleSteps1
sampleSteps1 = [10,20,25,50] ++ map (*10) sampleSteps1
steps size (minV,maxV) = takeWhile (<b) [a,a+size..] ++ [b]
where
a = (floor (minV / fromIntegral size)) * size
b = (ceiling (maxV / fromIntegral size)) * size
|