Advertisement
Guest User

Untitled

a guest
Aug 30th, 2014
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. calculate :: Mask -> XY -> Int -> Mask
  2. calculate msk@(A2D.Array2d cols rows _) c r =
  3.     let size = (cols, rows) in
  4.     let dirs = [ (i, j) | i <- [-1..1], j <- [-1..1], i /= 0 || j /= 0 ] in
  5.     foldl (\msk (i, j) -> let l1 = castLight c size 1 1.0 0.0 0 i j 0 False msk in
  6.                           let l2 = castLight c size 1 1.0 0.0 i 0 0 j False l1 in
  7.                           l2
  8.                       ) msk dirs
  9.  
  10.  where castLight :: XY -> (Int,Int) -> Int -> Double -> Double -> Int -> Int -> Int -> Int -> Bool -> Mask -> Mask
  11.        castLight c@(sx, sy) size@(width,height) row start end xx xy yx yy blocked mask =
  12.            if start < end
  13.            then mask
  14.            else loop1 row start 0.0 blocked mask
  15.         where loop1 :: Int -> Double -> Double -> Bool -> Mask -> Mask
  16.               loop1 distance start newStart blocked mask =
  17.                   let deltaY = -distance in
  18.                   if distance > r || blocked
  19.                   then mask
  20.                   else loop2 (-distance) (-distance) start newStart blocked mask
  21.                where loop2 :: Int -> Int -> Double -> Double -> Bool -> Mask -> Mask
  22.                      loop2 deltaY deltaX start newStart blocked mask =
  23.                          if deltaX > 0
  24.                          then mask
  25.                          else let currentX = sx + deltaX * xx + deltaY * xy in
  26.                               let currentY = sy + deltaX * yx + deltaY * yy in
  27.                               let leftSlope = fromIntegral deltaX - 0.5 / fromIntegral deltaY + 0.5 in
  28.                               let rightSlope = fromIntegral deltaX + 0.5 / fromIntegral deltaY - 0.5 in
  29.                               if not (currentX >= 0
  30.                                    && currentY >= 0
  31.                                    && currentX < width
  32.                                    && currentY < height)
  33.                                 || start < rightSlope
  34.                               then loop2 deltaY (deltaX + 1) start newStart blocked mask
  35.                               else if end > leftSlope
  36.                               then mask
  37.                               else let mask' = if inRadius (deltaX, deltaY) r
  38.                                               then A2D.put mask (currentX, currentY) True
  39.                                               else mask
  40.                                   in
  41.                                   if blocked
  42.                                   then if any not (A2D.get mask' (currentX, currentY) )
  43.                                         then loop2 deltaY (deltaX + 1) start rightSlope blocked mask'
  44.                                        else loop2 deltaY (deltaX + 1) newStart newStart False mask'
  45.                                    else if any not (A2D.get mask' (currentX, currentY))
  46.                                        then let mask'' = castLight c size (distance + 1) start leftSlope xx xy yx yy False mask' in
  47.                                              loop2 deltaY (deltaX + 1) start rightSlope True mask''
  48.                                         else loop2 deltaY (deltaX + 1) start newStart blocked mask'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement