reanimate-0.3.2.0: examples/morphology_point_correspondence.hs
#!/usr/bin/env stack
-- stack runghc --package reanimate
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ParallelListComp #-}
module Main(main) where
import Codec.Picture
import Codec.Picture.Types
import Control.Monad (replicateM_)
import qualified Data.Text as T
import qualified Data.Vector as V
import Linear.V2
import Linear.Vector
import Reanimate
import Reanimate.Math.Polygon
import Reanimate.Morph.Common
import Reanimate.Morph.Linear
bgColor :: PixelRGBA8
bgColor = PixelRGBA8 252 252 252 0xFF
main :: IO ()
main = reanimate $
addStatic (mkBackgroundPixel bgColor) $
mapA (withStrokeWidth 0) $
mapA (withStrokeColor "black") $
mapA (withFillOpacity 1) $
sceneAnimation $ do
let pl1 = translate (-4) 0 $ mkGroup
[ lowerTransformations $ scale 3 $ withFillOpacity 1 $
withStrokeColor "black" $
withStrokeWidth defaultStrokeWidth $
withFillColor "lightgreen" $
polygonShape octogon
, lowerTransformations $ scale 3 $ polygonNumDots octogon 0
]
pl2 n t = translate 4 0 $ lowerTransformations $ scale 3 $ mkGroup
[ withFillOpacity 1 $
withStrokeColor "black" $
withStrokeWidth defaultStrokeWidth $
withFillColor "cyan" $
polygonShape (pSetOffset star n)
, polygonNumDots (pSetOffset star n) t ]
offset <- newVar 0
slide <- newVar 0
_ <- newSprite $ pl2 <$> unVar offset <*> unVar slide
_ <- newSpriteSVG $ pl1
let slideLeft = do
tweenVar slide 1 $ \v -> fromToS v 1 . curveS 4
writeVar slide 0
modifyVar offset succ
replicateM_ 8 $ do
offsetVal <- readVar offset
play $ step pl1 (pl2 offsetVal 0)
# setDuration 3
slideLeft
where
step from to =
signalA (curveS 2) $ animate $ morph rawLinear from to
octogon :: Polygon
octogon = mkPolygon $ V.fromList
[ realToFrac <$> V2 (cos phi) (sin phi)
| n <- [0..7]
, let phi = n*2*pi/8 + pi/8 :: Double
]
star :: Polygon
star = pScale 0.5 $ mkPolygon $ V.fromList
[ V2 0 1, V2 (-2) 2, V2 (-1) 0
, V2 (-2) (-2), V2 0 (-1), V2 2 (-2)
, V2 1 0, V2 2 2 ]
genColor :: Int -> Int -> PixelRGBA8
genColor n m =
promotePixel $ parula (fromIntegral (n+offset) / fromIntegral (m+offset))
where
offset = 5
polygonNumDots :: Polygon -> Double -> SVG
polygonNumDots p t = mkGroup $ reverse
[ mkGroup
[ colored n $ withStrokeWidth (defaultStrokeWidth*0.5) $ withStrokeColor "black" $
translate x y $ pathify $ mkCircle circR
, withFillColor "black" $
translate x y $ ppNum n ]
| n <- [0..pSize p-1]
, let a = realToFrac <$> pAccess p n
b = realToFrac <$> pAccess p (pNext p n)
V2 x y = lerp t b a ]
where
circR = 0.1
colored n =
let c = genColor n (pSize p-1)
in withFillColorPixel c
ppNum n = scaleToHeight (circR*1.5) $ center $ latex $ T.pack $ "\\texttt{" ++ show n ++ "}"
polygonShape :: Polygon -> SVG
polygonShape p = mkLinePathClosed
[ (x,y) | V2 x y <- map (fmap realToFrac) $ V.toList (polygonPoints p) ]