Exercise 3.2


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.


Leave a Reply

Your email address will not be published. Required fields are marked *