module Fractal.GRUFF where
import System.IO (hFlush, stdout)
import Fractal.RUFF.Types.Complex (Complex((:+)))
type Animation = [(Image, FilePath)]
data Image = Image
{ imageWindow :: !Window
, imageViewport :: !Viewport
, imageLocation :: !Location
, imageColours :: !Colours
, imageLabels :: [Label]
, imageLines :: [Line]
}
deriving (Read, Show, Eq)
data Window = Window
{ width :: !Int
, height :: !Int
, supersamples :: !Double
}
deriving (Read, Show, Eq)
data Viewport = Viewport
{ aspect :: !Double
, orient :: !Double
}
deriving (Read, Show, Eq)
data Location = Location
{ center :: !(Complex Rational)
, radius :: !Double
}
deriving (Read, Show, Eq)
data Colours = Colours
{ colourInterior :: !Colour
, colourBoundary :: !Colour
, colourExterior :: !Colour
}
deriving (Read, Show, Eq)
data Colour = Colour !Double !Double !Double
deriving (Read, Show, Eq)
data Label = Label
{ labelCoords :: !(Complex Rational)
, labelColour :: !Colour
, labelText :: String
}
deriving (Read, Show, Eq)
labelAppend :: Complex Rational -> Colour -> String -> Image -> Image
labelAppend c v t i = i{ imageLabels = imageLabels i ++ [Label{ labelCoords = c, labelColour = v, labelText = t }] }
labelPrepend :: Complex Rational -> Colour -> String -> Image -> Image
labelPrepend c v t i = i{ imageLabels = [Label{ labelCoords = c, labelColour = v, labelText = t }] ++ imageLabels i }
data Line = Line
{ lineSegments :: [(Complex Rational, Complex Rational)]
, lineColour :: !Colour
}
deriving (Read, Show, Eq)
fromScreenCoords :: (Fractional r, Real r) => Window -> Viewport -> Location -> Complex Double -> Complex r
fromScreenCoords w v l = \(x :+ y) ->
let x1 = (2 * x w') / w' * p
y1 = (h' 2 * y) / h' / p
x2 = co * x1 + si * y1
y2 = si * x1 + co * y1
x3 = r * toRational x2
y3 = r * toRational y2
x4 :+ y4 = (x3 :+ y3) + c
in fromRational x4 :+ fromRational y4
where
p = sqrt (aspect v)
w' = fromIntegral (width w)
h' = fromIntegral (height w)
a = orient v
co = cos a
si = sin a
r = toRational $ radius l
c = center l
toScreenCoords :: Real r => Window -> Viewport -> Location -> Complex r -> Complex Double
toScreenCoords w v l = \(x' :+ y') ->
let x = (x1 / p * w' + w') / 2
y = (y1 * p * h' h') / (2)
x1 = co * x2 + si * y2
y1 = si * x2 + co * y2
x2 = fromRational (x3 / r)
y2 = fromRational (y3 / r)
x3 :+ y3 = (toRational x' :+ toRational y') c
in x :+ y
where
p = sqrt (aspect v)
w' = fromIntegral (width w)
h' = fromIntegral (height w)
a = orient v
co = cos a
si = sin a
r = toRational (radius l)
c = center l
defaultMain :: Animation -> IO ()
defaultMain a = do
mapM_ (\f -> print f >> hFlush stdout) a