module Print (print) where import Prelude hiding (print) import Data.Array.Unboxed (UArray, bounds, (!)) import Data.ByteString.Char8 (ByteString, pack) import Numeric (showFFloat) import Types import Graphics print :: Graphics -> Header -> [Double] -> [Double] -> [ByteString] -> UArray Int Double -> UArray (Int, Int) Double -> [ByteString] print gfx header sticks vticks labels times coords = let bands = toPoints (bounds coords) times coords filled c = visual gfx (Just c) Nothing Nothing Nothing labels' = reverse labels colours = map colour labels' polygons = concat . zipWith (\c ps -> filled c (polygon gfx ps)) colours . map (map p) $ bands key = concat . zipWith3 (keyBox (gW + border * 2.5) (border * 1.5) (gH / 16)) [(0::Int) ..] colours $ labels' keyBox x y0 dy i c l = let y = y0 + fromIntegral i * dy in (filled c $ rect gfx (x, y + 0.1 * dy) (dy * 0.8, dy * 0.8)) ++ text gfx Nothing Start 15 (x + dy, y + dy * 0.6) [l] w = 1280 h = 720 gW = 960 - 2 * border gH = 720 - 3 * border border = 60 textOffset = 10 (xMin, xMax) = hSampleRange header (yMin, yMax) = hValueRange header gRange@((gx0,gy0),(gx1,gy1)) = ((border*1.5, gH + border*1.5), (gW + border*1.5, border*1.5)) p = rescalePoint ((xMin, yMin), (xMax, yMax)) gRange title = text gfx Nothing Middle 25 (w / 2, border * 0.75) [hJob header, pack " (", hDate header, pack ")"] background = filled white $ rect gfx (0,0) (w,h) box = filled white $ rect gfx (gx0,gy1) (gW,gH) leftLabel = text gfx (Just (-90)) Middle 20 (border/2, (gy0 + gy1)/2) [hValueUnit header] leftTicks = concatMap (\(y,l) -> let { (x1, y1) = p (xMin, y) ; (x2, y2) = p (xMax, y) } in line gfx (x1 - border/2, y1) (x2, y2) ++ if l then [] else text gfx Nothing End 15 (x1 - textOffset, y1 - textOffset) (showSI y) ) (zip vticks (replicate (length vticks - 1) False ++ [True])) bottomLabel = text gfx Nothing Middle 20 ((gx0 + gx1)/2, gy0 + border) [hSampleUnit header] bottomTicks = concatMap (\(x,l) -> let { (x1, y1) = p (x, yMin) ; (x2, y2) = p (x, yMax) } in line gfx (x1, y1 + border/2) (x2, y2) ++ if l then [] else text gfx Nothing Start 15 (x1 + textOffset, y1+2*textOffset) (showSI x) ) (zip sticks (replicate (length sticks - 1) False ++ [True])) in document gfx (w,h) . concat $ [ background , visual gfx (Just black) Nothing (Just black) (Just 1) $ concat [ title , leftLabel , bottomLabel , leftTicks , bottomTicks , visual gfx Nothing (Just 0.7) Nothing Nothing $ concat [ box , polygons , key ] ] ] toPoints :: ((Int,Int),(Int,Int)) -> UArray Int Double -> UArray (Int,Int) Double -> [[(Double,Double)]] toPoints ((b0,s0),(b1,s1)) times coords = [ fwd ++ rwd | b <- [b1, b1 - 1 .. b0 + 1] , let fwd = [ (times ! s, coords ! (b - 1, s)) | s <- up b ] , let rwd = [ (times ! s, coords ! (b, s)) | s <- down b ] ] where -- ugly hack to force recomputation instead of sharing a large list up b = [s0 + b - b .. s1] down b = [s1 + b - b, s1 - 1 .. s0] showSI :: Double -> [ByteString] showSI x | x < 1e3 = [ showF x "" ] | x < 1e6 = [ showF (x/1e3 ) "k" ] | x < 1e9 = [ showF (x/1e6 ) "M" ] | x < 1e12 = [ showF (x/1e9 ) "G" ] | x < 1e15 = [ showF (x/1e12) "T" ] | otherwise = [ showF (x/1e15) "P" ] where showF y si = let (xs, ys) = break ('.' ==) $ showFFloat (Just 3) y "" zs = reverse . dropWhile ('0' ==) . reverse . drop 1 $ ys in case zs of "" -> pack $ xs ++ si ws -> pack $ xs ++ "." ++ ws ++ si