mirror of
https://github.com/reanimate/reanimate.git
synced 2026-09-14 09:32:22 +00:00
Add fourier example.
This commit is contained in:
parent
35f2aa92ed
commit
ec25437a9f
1 changed files with 90 additions and 0 deletions
90
examples/fourier.hs
Executable file
90
examples/fourier.hs
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/env stack
|
||||
-- stack --resolver lts-12.26 runghc --package reanimate
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
module Main (main) where
|
||||
|
||||
import Control.Lens
|
||||
import Data.Complex
|
||||
import qualified Data.Text as T
|
||||
|
||||
import Graphics.SvgTree
|
||||
import Reanimate.Driver (reanimate)
|
||||
import Reanimate.LaTeX (latex)
|
||||
import Reanimate.Monad
|
||||
import Reanimate.Svg
|
||||
|
||||
waveMultiplier :: Int
|
||||
-- waveMultiplier = 1 -- Sawtooth wave
|
||||
waveMultiplier = 2 -- Square wave
|
||||
|
||||
main :: IO ()
|
||||
main = reanimate $
|
||||
fourierAnimation 1 `before`
|
||||
fourierAnimation 2 `before`
|
||||
fourierAnimation 3 `before`
|
||||
fourierAnimation 5 `before`
|
||||
fourierAnimation 10 `before`
|
||||
fourierAnimation 25 `before`
|
||||
fourierAnimation 50 `before`
|
||||
fourierAnimation 100
|
||||
|
||||
sWidth = 0.5
|
||||
|
||||
fourierAnimation :: Int -> Animation
|
||||
fourierAnimation nCircles = repeatAnimation 2 $ mkAnimation 3 $ do
|
||||
emit $ mkBackground "black"
|
||||
phi <- signal 0 (2*pi)
|
||||
mapF (translate (-100) 0) $ do
|
||||
drawNCircles nCircles phi
|
||||
emit $ withStrokeColor "white" $
|
||||
withStrokeWidth (Num sWidth) $
|
||||
withFillOpacity 0 $
|
||||
translate 80 0 $
|
||||
mkCirclePath nCircles phi
|
||||
emit $ withStrokeWidth (Num sWidth) $
|
||||
withFillColor "white" $
|
||||
translate (-140) (-80) $
|
||||
scale 2 $ latex $ T.pack $ "Circles: " ++ show nCircles
|
||||
|
||||
drawNCircles totalCircles phi = do
|
||||
worker circles
|
||||
let x :+ y = sum circles
|
||||
emit $ withStrokeWidth (Num sWidth) $
|
||||
withStrokeColor "white" $
|
||||
mkLine (Num x, Num y) (Num 80, Num y)
|
||||
where
|
||||
circles = [ nthCircle n phi | n <- [0..totalCircles-1] ]
|
||||
worker [] = return ()
|
||||
worker (x :+ y : rest) = do
|
||||
let radius = sqrt(x*x+y*y)
|
||||
emit $ withStrokeWidth (Num sWidth) $
|
||||
withStrokeColor "grey" $
|
||||
withFillOpacity 0 $
|
||||
CircleTree $ defaultSvg
|
||||
& circleCenter .~ (Num 0, Num 0)
|
||||
& circleRadius .~ Num radius
|
||||
mapF (translate x y) $ worker rest
|
||||
emit $ withStrokeWidth (Num sWidth) $
|
||||
withStrokeColor "white" $
|
||||
mkLine (Num 0, Num 0) (Num x, Num y)
|
||||
|
||||
mkCirclePath nCircles phiOffset = mkLinePath $ take 2000 $
|
||||
zip [ 50 * i/granularity | i <- [0..]]
|
||||
$ drop (round $ (1-phiOffset/(2*pi)) * granularity) $
|
||||
cycle $ [ fourierYValue nCircles phi
|
||||
| x <- reverse [1..granularity]
|
||||
, let phi = 2*pi*(x/granularity)
|
||||
]
|
||||
where
|
||||
granularity = 500
|
||||
|
||||
fourierYValue n phi =
|
||||
imagPart (sum [ nthCircle i phi | i <- [0..n-1]])
|
||||
|
||||
nthCircle :: Int -> Double -> Complex Double
|
||||
nthCircle n phi = x :+ y
|
||||
where
|
||||
n' = fromIntegral (n*waveMultiplier+1)
|
||||
x = cos (n'*phi) * radius
|
||||
y = sin (n'*phi) * radius
|
||||
radius = 40 * (2 / (n'*pi))
|
||||
Loading…
Reference in a new issue