Add bezier example.

This commit is contained in:
David 2019-02-15 19:52:27 +01:00
commit 0f118c4899
5 changed files with 52 additions and 1 deletions

View file

@ -8,6 +8,10 @@ The example gifs are rendered at 25 fps.
# Examples
## Bezier curves
![Bezier curves](gifs/bezier.gif)
## Sine wave
```haskell

BIN
gifs/bezier.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

View file

@ -32,8 +32,9 @@ executable reanimate-viewer
Reanimate.Render
Reanimate.Examples
Reanimate.Combinators
Reanimate.LaTeX
build-depends: base >=4.12 && <4.13, cairo >=0.13 && <0.14, gtk,
svgcairo, lucid-svg, time, text, unix, lucid, reanimate,
filepath, process, directory
filepath, process, directory, containers
hs-source-dirs: src
default-language: Haskell2010

View file

@ -71,6 +71,7 @@ approxFnData steps fn =
fn 0 : [ fn (fromIntegral n/fromIntegral steps) | n <- [0..steps] ]
renderPath :: Path -> Svg ()
renderPath [] = return ()
renderPath dat =
path_ [stroke_ "white", fill_ "translucent", d_ path]
where

View file

@ -5,6 +5,7 @@ import Lucid.Svg
import Data.Text (Text, pack)
import Data.Monoid ((<>))
import Control.Arrow (returnA, (>>>))
import Control.Monad
import Text.Printf
import Numeric
@ -347,3 +348,47 @@ latex_basic = proc () -> do
g_ [fill_ "white", num_ fill_opacity_ s] text
where
text = latex "\\sum_{k=1}^\\infty {1 \\over k^2} = {\\pi^2 \\over 6}"
bezier :: Ani ()
bezier = adjustSpeed 0.5 $ proc () -> do
emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"]
follow
[orderN [pointA, pointB]
,morph [pointA, pointA, pointB] [pointA, pointC, pointB]
,orderN [pointA, pointC, pointB]
,morph [pointA, pointC, pointB, pointB] [pointA, pointC, pointD, pointB]
,orderN [pointA, pointC, pointD, pointB]
,morph [pointA, pointC, pointD, pointB] [pointA, pointA, pointB, pointB]] -< ()
where
pointA = (70,130); pointB = (270,120); pointC = (30,30); pointD = (250,50)
morph old new = defineAnimation $ proc () -> do
duration 0.5 -< ()
s <- signal 0 1 -< ()
let new' = map (\(a,b) -> between a b s) (zip old new)
emit -< forM_ (zip new' (tail new')) $ \(a,b) -> do
renderPath $
approxFnData 1000 $ \idx ->
between a b idx
emit -< mapM_ circleAt new'
orderN lst = defineAnimation $ proc () -> do
duration 2 -< ()
s <- signalOscillate 0 1 -< ()
emit -< orderN' (map const lst) s
emit -< mapM_ circleAt lst
orderN' [a] s = do
renderPath $ take (round $ 1000*s) $ approxFnData 1000 $ \idx -> a idx
circle_ [num_ cx_ (fst (a s)), num_ cy_ (snd (a s)), num_ r_ 3, fill_ "red"]
orderN' lst s = do
forM_ (zip lst (tail lst)) $ \(a,b) -> renderPath $
approxFnData 1000 $ \idx ->
between (a s) (b s) idx
let middlePoints = map (\(a,b) -> \idx -> between (a idx) (b idx) idx) (zip lst (tail lst))
mapM_ (\p -> circleAt (p s)) middlePoints
orderN' middlePoints s
circleAt (x,y) = circle_ [num_ cx_ x, num_ cy_ y, num_ r_ 3, fill_ "green"]
between a b _ | a==b = a
between (x1, y1) (x2, y2) idx =
( x1 + idx * (x2 - x1)
, y1 + idx * (x2-x1) * (y2 - y1) / (x2 - x1))