
-- A fractal consisting of circles and lines which looks a bit like
--	the workings of a clock.
import Graphics.Gloss

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 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)] ]
