-- CS-191 Functional Programming I - Coursework 2
-- Authors: 
-- Submission date: 
{-
You may use this file by copying it to your working directory 
and importing it by writing

import CW2_1234

at the beginning of your file.

Alternatively, you may do Questions 1,2,3 on your own 
as a voluntary exercise. 
-}

module CW2_1234   where

type Point   = (Float,Float)
type Bitmap  = Point -> Bool
type Picture = [[Bool]]
type Setting = (Point,Point,Int,Int) 

black, white :: Char
black = '@'
white = ' '

set0 :: Setting
set0 = ((-1,-1),(1,1),10,8)

discBm :: Bitmap
discBm (x,y) = x^2 + y^2 <= 1

discPic :: Picture
discPic = 
      [[False,False,False,False,False,True, False,False,False,False,False],
       [False,False,True, True, True, True, True, True, True, False,False],
       [False,True, True, True, True, True, True, True, True, True, False],
       [False,True, True, True, True, True, True, True, True, True, False],
       [True, True, True, True, True, True, True, True, True, True, True],
       [False,True, True, True, True, True, True, True, True, True, False],
       [False,True, True, True, True, True, True, True, True, True, False],
       [False,False,True, True, True, True, True, True, True, False,False],
       [False,False,False,False,False,True, False,False,False,False,False]]


-- Question 1

takePicture :: Setting -> Bitmap -> Picture
takePicture ((xbl,ybl),(xtr,ytr),n,m) bm = [ row j | j <- [0..m] ]

  where
   {
--  row :: Int -> [Bool] 
    row j = [ bm (point i j) | i <- [0..n] ] ; 

--  point :: Int -> Int -> Point
    point i j = (xbl+(fromIntegral i)*d,ytr-(fromIntegral j)*e) ;

    d = (xtr-xbl)/(fromIntegral n) ;
    e = (ytr-ybl)/(fromIntegral m) 
   }
   

{- Test:   
*Main> takePicture set0 discBm == discPic
True
-}


-- Question 2

showPicture :: Picture -> String
showPicture pic = concat ['\n' : map bool2Char bs | bs <- pic]

 where 
  {
-- bool2Char :: Bool -> Char
   bool2Char True  = black ;
   bool2Char False = white
  }
   
-- Question 3

pp :: Picture -> IO ()   -- print picture
pp = putStrLn . showPicture

pb :: Setting -> Bitmap -> IO ()
pb set bm = pp (takePicture set bm) 

{- Test:
*CW2_123> pp discPic

.....@.....
..@@@@@@@..
.@@@@@@@@@.
.@@@@@@@@@.
@@@@@@@@@@@
.@@@@@@@@@.
.@@@@@@@@@.
..@@@@@@@..
.....@.....
*CW2_123> pb set0 discBm

.....@.....
..@@@@@@@..
.@@@@@@@@@.
.@@@@@@@@@.
@@@@@@@@@@@
.@@@@@@@@@.
.@@@@@@@@@.
..@@@@@@@..
.....@.....

Please do NOT include such tests in your submission.
-}

-- Hints for Questions 4 and 6:

-- Question 4  

set1,set2,set3,set4,set5 :: Setting
set1 = ((-1.5,-1.5),(1.5,1.5),60,40)
set2 = ((-1.5,-1.5),(1.5,1.5),90,60)
set3 = ((-1.5,-1.5),(1.5,1.5),120,80)
set4 = ((-1.5,-1.5),(1.5,1.5),150,100)
set5 = ((-1.5,-1.5),(1.5,1.5),180,120)

tri :: Point -> Float -> Bitmap
tri (x,y) d (x',y') = x' <= x + d && y' <= y + d && x'+y' >= x+y+d 

bm1,bm2 :: Bitmap
bm1 = tri (-0.5,-0.30) 0.8
bm2 = tri (0,0) 0.7

pic1,pic2 :: Picture
pic1 = takePicture set1 bm1
pic2 = takePicture set1 bm2

-- Question 6

unionBm :: Bitmap -> Bitmap -> Bitmap
unionBm bm1 bm2 p = bm1 p || bm2 p

rotateBm :: Bitmap -> Float -> Bitmap
rotateBm bm alpha = \p -> bm (rotatePtAntiClockwise p alpha)

rotatePtAntiClockwise :: Point -> Float -> Point
rotatePtAntiClockwise (x,y) alpha = (x*b-y*a,x*a+y*b)

  where a = sin alpha
        b = cos alpha

bm3 :: Bitmap
bm3 = bm1 `unionBm` bm2

{-
pb set1 bm3
-}



