module Graphics.Rendering.Chart.Simple.Internal where
import Data.Maybe ( catMaybes )
import Data.Colour
import Data.Colour.Names
import Data.Default.Class
import Graphics.Rendering.Chart
import Graphics.Rendering.Chart.Utils
styleColor :: Int -> AlphaColour Double
styleColor ind = colorSequence !! ind
where colorSequence = cycle $ map opaque [ blue, red, green, yellow
, cyan, magenta, black ]
styleSymbol :: Int -> PlotKind
styleSymbol ind = symbolSequence !! ind
where symbolSequence = cycle [ Ex, HollowCircle, Square, Diamond
, Triangle, DownTriangle, Plus, Star
, FilledCircle ]
iplot :: (PlotValue x, PlotValue y) => [InternalPlot x y] -> Layout x y
iplot foobar = def {
_layout_plots = concat $ zipWith toplot (ip foobar) [0..]
}
where
ip (xs@(IPX _ _):xyss) = map (\ys -> (xs,ys)) yss ++ ip rest
where yss = takeWhile isIPY xyss
rest = dropWhile isIPY xyss
ip (_:xyss) = ip xyss
ip [] = []
isIPY (IPY _ _) = True
isIPY _ = False
toplot (IPX xs _, IPY ys yks) ind = plots
where
vs = zip xs ys
plots = case catMaybes $ map plotas yks of
[] -> [ toPlot $ def
{ _plot_lines_title = name yks,
_plot_lines_values = [vs],
_plot_lines_style = solidLine 1 (styleColor ind)
} ]
xs -> xs
plotas Solid = Just $ toPlot $ def
{ _plot_lines_title = name yks,
_plot_lines_values = [vs],
_plot_lines_style = solidLine 1 (styleColor ind) }
plotas Dashed = Just $ toPlot $ def
{ _plot_lines_title = name yks,
_plot_lines_values = [vs],
_plot_lines_style = dashedLine 1 [10,10]
(styleColor ind) }
plotas Dotted = Just $ toPlot $ def
{ _plot_lines_title = name yks,
_plot_lines_values = [vs],
_plot_lines_style = dashedLine 1 [1,11]
(styleColor ind) }
plotas FilledCircle = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = filledCircles 4
(styleColor ind) }
plotas HollowCircle = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = hollowCircles 5 1
(styleColor ind) }
plotas Triangle = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = hollowPolygon 7 1 3 False
(styleColor ind) }
plotas DownTriangle = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = hollowPolygon 7 1 3 True
(styleColor ind) }
plotas Square = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = hollowPolygon 7 1 4 False
(styleColor ind) }
plotas Diamond = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = hollowPolygon 7 1 4 True
(styleColor ind) }
plotas Plus = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = plusses 7 1 (styleColor ind) }
plotas Ex = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = exes 7 1 (styleColor ind) }
plotas Star = Just $ toPlot $ def
{ _plot_points_title = name yks,
_plot_points_values = vs,
_plot_points_style = stars 7 1 (styleColor ind) }
plotas Symbols = plotas (styleSymbol ind)
plotas _ = Nothing
name :: [PlotKind] -> String
name (Name s:_) = s
name (_:ks) = name ks
name [] = ""
str2k :: String -> [PlotKind]
str2k "" = []
str2k ". " = [Dotted]
str2k s@('?':_) = str2khelper s Symbols
str2k s@('@':_) = str2khelper s FilledCircle
str2k s@('#':_) = str2khelper s Square
str2k s@('v':_) = str2khelper s DownTriangle
str2k s@('^':_) = str2khelper s Triangle
str2k s@('o':_) = str2khelper s HollowCircle
str2k s@('+':_) = str2khelper s Plus
str2k s@('x':_) = str2khelper s Ex
str2k s@('*':_) = str2khelper s Star
str2k s@('.':_) = str2khelper s LittleDot
str2k "- " = [Dashed]
str2k "-" = [Solid]
str2k n = [Name n]
str2khelper :: String -> PlotKind -> [PlotKind]
str2khelper s@(_:r) x = case str2k r of
[] -> [x]
[Name _] -> [Name s]
xs -> x:xs
data PlotKind = Name String | FilledCircle | HollowCircle
| Triangle | DownTriangle | Square | Diamond
| Plus | Ex | Star | Symbols
| LittleDot | Dashed | Dotted | Solid
deriving ( Eq, Show, Ord )
data InternalPlot x y = IPY [y] [PlotKind] | IPX [x] [PlotKind]
newtype LayoutDDD = LayoutDDD { plotLayout :: Layout Double Double }
layoutDddToRenderable :: LayoutDDD -> Renderable (LayoutPick Double Double Double)
layoutDddToRenderable = layoutToRenderable . plotLayout
instance ToRenderable LayoutDDD where
toRenderable = setPickFn nullPickFn . toRenderable
uplot :: [UPlot] -> LayoutDDD
uplot us = LayoutDDD $ iplot $ nameDoubles $ evalfuncs us
where
nameDoubles :: [UPlot] -> [InternalPlot Double Double]
nameDoubles (X xs: uus) = case grabName uus of
(ks,uus') -> IPX (filter isValidNumber xs) ks
: nameDoubles uus'
nameDoubles (UDoubles xs:uus)= case grabName uus of
(ks,uus') -> IPY (filter isValidNumber xs) ks
: nameDoubles uus'
nameDoubles (_:uus) = nameDoubles uus
nameDoubles [] = []
evalfuncs :: [UPlot] -> [UPlot]
evalfuncs (UDoubles xs:uus) = X xs : map ef (takeWhile (not.isX) uus)
++ evalfuncs (dropWhile (not.isX) uus)
where ef (UFunction f) = UDoubles (map f xs)
ef u = u
evalfuncs (X xs:uus) = X xs : map ef (takeWhile (not.isX) uus)
++ evalfuncs (dropWhile (not.isX) uus)
where ef (UFunction f) = UDoubles (map f xs)
ef u = u
evalfuncs (u:uus) = u : evalfuncs uus
evalfuncs [] = []
grabName :: [UPlot] -> ([PlotKind],[UPlot])
grabName (UString n:uus) = case grabName uus of
(ks,uus') -> (str2k n++ks,uus')
grabName (UKind ks:uus) = case grabName uus of
(ks',uus') -> (ks++ks',uus')
grabName uus = ([],uus)
isX (X _) = True
isX _ = False
plot :: PlotType a => a
plot = pl []
class PlotType t where
pl :: [UPlot] -> t
instance (PlotArg a, PlotType r) => PlotType (a -> r) where
pl args = \ a -> pl (toUPlot a ++ args)
instance PlotType LayoutDDD where
pl args = uplot (reverse args)
plotPDF :: PlotPDFType a => String -> a
plotPDF fn = pld fn []
class PlotPDFType t where
pld :: FilePath -> [UPlot] -> t
instance (PlotArg a, PlotPDFType r) => PlotPDFType (a -> r) where
pld fn args = \ a -> pld fn (toUPlot a ++ args)
plotPS :: PlotPSType a => String -> a
plotPS fn = pls fn []
class PlotPSType t where
pls :: FilePath -> [UPlot] -> t
instance (PlotArg a, PlotPSType r) => PlotPSType (a -> r) where
pls fn args = \ a -> pls fn (toUPlot a ++ args)
plotPNG :: PlotPNGType a => String -> a
plotPNG fn = plp fn []
class PlotPNGType t where
plp :: FilePath -> [UPlot] -> t
instance (PlotArg a, PlotPNGType r) => PlotPNGType (a -> r) where
plp fn args = \ a -> plp fn (toUPlot a ++ args)
data UPlot = UString String | UDoubles [Double] | UFunction (Double -> Double)
| UKind [PlotKind] | X [Double]
xcoords :: [Double] -> UPlot
xcoords = X
class PlotArg a where
toUPlot :: a -> [UPlot]
instance IsPlot p => PlotArg [p] where
toUPlot = toUPlot'
instance (Real a, Real b, Fractional a, Fractional b) => PlotArg (a -> b) where
toUPlot x = [UFunction (realToFrac . x . realToFrac)]
instance (Real a, Real b, Fractional a, Fractional b) => IsPlot (a -> b) where
toUPlot' = reverse . concatMap f
where f x = [UFunction (realToFrac . x . realToFrac)]
instance PlotArg UPlot where
toUPlot = (:[])
instance PlotArg PlotKind where
toUPlot = (:[]) . UKind . (:[])
class IsPlot c where
toUPlot' :: [c] -> [UPlot]
instance IsPlot PlotKind where
toUPlot' = (:[]) . UKind
instance IsPlot Double where
toUPlot' = (:[]) . UDoubles
instance IsPlot Char where
toUPlot' = (:[]) . UString
instance IsPlot p => IsPlot [p] where
toUPlot' = reverse . concatMap toUPlot'
instance (IsPlot p, IsPlot q, IsPlot r) => IsPlot (p,q,r) where
toUPlot' = reverse . concatMap f
where f (p,q,r) = toUPlot' [p] ++ toUPlot' [q] ++ toUPlot' [r]
instance (IsPlot p, IsPlot q) => IsPlot (p,q) where
toUPlot' = reverse . concatMap f
where f (p,q) = toUPlot' [p] ++ toUPlot' [q]