-- A fractal consisting of circles and lines which looks a bit like
-- the workings of a clock.
import Graphics.Gloss
main
= animate (InWindow "Clock" (500, 500) (20, 20))
black frame
-- Build the fractal, scale it so it fits in the window
-- and rotate the whole thing as time moves on.
frame :: Float -> Picture
frame time = Color white
$ Scale 110 110
$ Rotate (time * 2*pi)
$ clockFractal 5 time
-- The basic fractal consists of three circles offset from the origin
-- as follows.
--
-- 1
-- |
-- .
-- / \
-- 2 3
--
-- The direction of rotation switches as n increases.
-- Components at higher iterations also spin faster.
--
clockFractal :: Int -> Float -> Picture
clockFractal 0 s = Blank
clockFractal n s = Pictures [circ1, circ2, circ3, lines]
where
-- y offset from origin to center of circle 1.
a = 1 / sin (2 * pi / 6)
-- x offset from origin to center of circles 2 and 3.
b = a * cos (2 * pi / 6)
nf = fromIntegral n
rot = if n `mod` 2 == 0
then 50 * s * (log (1 + nf))
else (-50 * s * (log (1 + nf)))
-- each element contains a copy of the (n-1) iteration contained
-- within a larger circle, and some text showing the time since
-- the animation started.
--
circNm1
= Pictures
[ circle 1
, Scale (a/2.5) (a/2.5) $ clockFractal (n-1) s
, if n > 2
then Color cyan
$ Translate (-0.15) 1
$ Scale 0.001 0.001
$ Text (show s)
else Blank
]
circ1 = Translate 0 a $ Rotate rot circNm1
circ2 = Translate 1 (-b) $ Rotate (-rot) circNm1
circ3 = Translate (-1) (-b) $ Rotate rot circNm1
-- join each iteration to the origin with some lines.
lines
= Pictures
[ Line [(0, 0), ( 0, a)]
, Line [(0, 0), ( 1, -b)]
, Line [(0, 0), (-1, -b)] ]