packages feed

hps-cairo-0.11: Help/animation.hs

module Main where

import System.Random
import Graphics.PS
import Graphics.PS.Cairo
import qualified Graphics.UI.Gtk as G
import Data.IORef

type R = Double
data A = A R R R R

semiann :: A -> R -> Image
semiann (A gs ir xr a) sa =
    let  x = 250
         y = 250
         z = 250
         sa' = sa * 2.0 * pi
         a' = a * pi
         ir' = min ir xr
         xr' = max ir xr
         shift = translate x y . scale z z
    in Fill (greyGS gs) (shift (annular origin ir' xr' sa' a'))

-- | Group a list into a list of n element lists.
clump :: Int -> [a] -> [[a]]
clump _ [] = []
clump n l =
    let (i,j) = splitAt n l
    in i : clump n j

-- | Generate a list of n random numbers in the range [l,r].
randn :: Int -> Int -> R -> R -> [R]
randn s n l r =
    let f i = i * (r - l) + l
    in (map f . take n . randoms . mkStdGen) s

--
settings :: [(A, R, R)]
settings =
    let g [a,b,c,d,e,f] = (A a b c d, e, f)
        g _ = undefined
    in map g (clump 6 (randn 0 66 0 1))

as :: [A]
as = map (\(a,_,_) -> a) settings

ns :: [R]
ns = map (\(_,n,_) -> n/100) settings

is :: [R]
is = map (\(_,_,i) -> i) settings

main :: IO ()
main = do
  _ <- G.initGUI
  window <- G.windowNew
  canvas <- G.drawingAreaNew
  ss <- newIORef is
  G.windowSetResizable window False
  G.widgetSetSizeRequest window 500 500
  _ <- G.onKeyPress window (const (G.widgetDestroy window >> return True))
  _ <- G.onDestroy window G.mainQuit
  _ <- G.onExpose canvas (const (updateCanvas canvas ss))
  _ <- G.timeoutAdd (G.widgetQueueDraw window >> return True) 42
  G.set window [G.containerChild G.:= canvas]
  G.widgetShowAll window
  G.mainGUI

updateCanvas :: G.DrawingArea -> IORef [R] -> IO Bool
updateCanvas canvas ss = do
  window <- G.widgetGetDrawWindow canvas
  modifyIORef ss (zipWith (+) ns)
  aa <- readIORef ss
  let i = foldl1 over (zipWith semiann as aa)
  G.renderWithDrawable window (renderImage i)
  return True