content: {-|
  Module      : Reanimate.Builtin.CirclePlot
  Copyright   : Written by David Himmelstrup
  License     : Unlicense
  Maintainer  : lemmih@gmail.com
  Stability   : experimental
  Portability : POSIX
  
  Convenience module for rendering circle plots.
  
  -}
  module Reanimate.Builtin.CirclePlot
    ( circlePlot
    ) where
  
  import           Codec.Picture       (PixelRGBA8 (..), generateImage)
  import           Graphics.SvgTree    (Tree)
  import           Reanimate.Constants (screenHeight)
  import           Reanimate.Raster    (embedImage)
  import           Reanimate.Svg       (flipYAxis, scaleToHeight)
  
  -- | Circle plots are scaled to 'screenHeight'.
  --
  --   Example:
  --
  -- @
  -- 'circlePlot' 500 $ \\ang r ->
  --   'Codec.Picture.Types.promotePixel' $ toRGB8 $ uncurryRGB sRGB $ hsv (ang/pi*180) r 1
  -- @
  --
  --   <<docs/gifs/doc_circlePlot.gif>>
  circlePlot :: Int -- ^ Number of diagonal pixels. Only affects quality, not size.
             -> (Double -> Double -> PixelRGBA8)
                -- ^ Angle and radius in radians and percent respectively.
             -> Tree
  circlePlot density fn =
      scaleToHeight screenHeight $ flipYAxis $
      embedImage $ generateImage gen density density
    where
      cN = fromIntegral $ density `div` 2 - 1
      gen x y =
        let radius = sqrt ((fromIntegral x-cN)**2 + (fromIntegral y-cN)**2)
            ang = atan2 (fromIntegral y-cN) (fromIntegral x-cN)
        in if radius > cN
          then PixelRGBA8 0 0 0 0
          else fn ang (radius / cN)
  