content: {-# LANGUAGE OverloadedStrings #-}
  
  -- A fractal consisting of circles and lines which looks a bit like
  --      the workings of a clock.
  module Main where
  
  import Brillo
  import Data.Text qualified as T
  import Prelude hiding (lines)
  
  
  main :: IO ()
  main =
    animate
      (InWindow "Clock" (600, 600) (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 120 120 $
        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 _ = 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 (T.pack $ 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)]
          ]
  