From the text:
spaceClose :: Window -> IO ()
spaceClose w = do k <- getKey w
if k==' ' then closeWindow w else spaceClose w
minSize :: Int
minSize = 8
The exercise:
mulcos30 :: Int -> Int
mulcos30 n = n * 86603 `div` 100000
equiTri :: Color -> Window -> Int -> Int -> Int -> Int -> IO ()
equiTri color w x y yorient size
= let halfsize = size `div` 2
height = mulcos30 size
a = (x, y)
b = (x + halfsize, y - (height * yorient))
c = (x + size, y)
in drawInWindow w (withColor color
(polygon [a, b, c, a]))
defaultColors :: [Color]
defaultColors = [Blue, Green, Red, Cyan, Magenta, Yellow]
starOfDavid :: [Color] -> Window -> Int -> Int -> Int -> IO ()
starOfDavid (c:cs) w x y size
= let twothirdsheight = 2 * (mulcos30 size) `div` 3
fourninthsheight = 4 * (mulcos30 size) `div` 9
twoninthsheight = fourninthsheight `div` 2
onethirdsize = size `div` 3
in do equiTri c w x y 1 size
equiTri c w x (y-twothirdsheight) (-1) size
if size >= minSize
then do starOfDavid cs w x y onethirdsize
starOfDavid cs w (x + onethirdsize * 2)
y onethirdsize
starOfDavid cs w (x + onethirdsize)
(y - twothirdsheight) onethirdsize
starOfDavid cs w (x + onethirdsize * 2)
(y - fourninthsheight) onethirdsize
starOfDavid cs w x (y - fourninthsheight) onethirdsize
starOfDavid cs w (x + onethirdsize)
(y + twoninthsheight) onethirdsize
else return ()
starOfDavid [] w x y size = starOfDavid defaultColors w x y size
main = runGraphics (
do w <- openWindow "Snowflake Fractal" (1000,1000)
starOfDavid [] w 120 720 729
spaceClose w
)
Again, this is looking clumsy with the 6 lines of procedural code. See the blogroll for more elegant solutions (albeit using functionality not yet presented in the book). Pattern matching the empty list was my newbie way of specifying default parameters and cycling the colours. mulcos30 is also a clumsy way to multiply an integer by cosine 30° - Haskell seems to make type conversion harder than C++. I'm not sure if this is a good thing or a bad thing. If this were production code, I'd bite the bullet and do the calculations in high precision, converting to integers only for display.