module System.Console.Ansigraph.Internal.Horizontal ( displayRV , displayCV , simpleRender , simpleRenderR ) where import System.Console.Ansigraph.Internal.Core import Data.Complex ---- Graphing Infrastructure ---- barChars = "█▇▆▅▄▃▂▁" -- These values delineate regions for rounding to the nearest 1/8. barVals :: [Double] barVals = (+ 0.0625) . (/8) <$> [7,6..0] -- = [15/16, 13/16, 11/16, 9/16, 7/16, 5/16, 3/16, 1/16] {- forward and reverse versions of unicode bar selection for positive and negative graph regions respectively -} bars, barsR :: [(Double,Char)] bars = zipWith (,) barVals barChars barsR = zipWith (,) barVals (reverse barChars) selectBar, selectBarR :: Double -> Char selectBar x = let l = filter (\p -> fst p < x) bars in case l of [] -> ' ' (p:ss) -> snd p selectBarR x = let l = filter (\p -> fst p < x) barsR in case l of [] -> '█' (p:ss) -> snd p -- | Simple vector rendering. Yields a string of unicode chars representing graph bars -- varying in units of 1/8. To be primarily invoked via 'graph', 'graphWith', -- 'animate', 'animateWith'. simpleRender :: [Double] -> String simpleRender xs = let mx = maximum xs in (selectBar . (/mx)) <$> xs -- | Simple vector rendering – inverted version. Rarely used directly. -- It is needed to render negative graph regions. simpleRenderR :: [Double] -> String simpleRenderR xs = let mx = maximum xs in (selectBarR . (/mx)) <$> xs renderCV :: [Complex Double] -> (String,String,String,String) renderCV l = let rp = realPart <$> l rm = negate <$> rp ip = imagPart <$> l im = negate <$> ip mx = maximum $ rp ++ rm ++ ip ++ im in (selectBar . (/mx) <$> rp, selectBarR . (/mx) <$> rm, selectBar . (/mx) <$> ip, selectBarR . (/mx) <$> im) renderRV :: [Double] -> (String,String) renderRV l = let rp = l rm = negate <$> rp mx = maximum $ rp ++ rm in (selectBar . (/mx) <$> rp, selectBarR . (/mx) <$> rm) -- | ANSI based display for complex vectors. To be primarily invoked via 'graph', 'graphWith', -- 'animate', 'animateWith'. displayCV :: AGSettings -> [Complex Double] -> IO () displayCV s l = let (rp,rm,ip,im) = renderCV l (rcol,icol) = colorSets s in do withColoring rcol $ putStr rp withColoring (invert rcol) $ putStr rm withColoring icol $ putStr ip withColoring (invert icol) $ putStr im -- | ANSI based display for real vectors. To be primarily invoked via 'graph', 'graphWith', -- 'animate', 'animateWith'. displayRV :: AGSettings -> [Double] -> IO () displayRV s l = let (rp,rm) = renderRV l rcol = realColors s in do withColoring rcol $ putStr rp withColoring (invert rcol) $ putStr rm