packages feed

gloss-examples-1.9.3.1: picture/Visibility/Draw.hs

{-# LANGUAGE PatternGuards #-}
module Draw
        ( drawState
        , drawWorld)
where
import State
import World
import Geometry.Segment
import Graphics.Gloss
import Graphics.Gloss.Geometry.Line
import qualified Data.Vector.Unboxed    as V
import Data.Maybe


drawState :: State -> Picture
drawState state
        | ModeDisplayWorld      <- stateModeDisplay state
        = drawWorldWithViewPos 
                (stateModeOverlay state)
                (stateViewPos     state) 
                (stateTargetPos   state)
                (stateWorld       state)

        | ModeDisplayNormalised <- stateModeDisplay state
        = drawWorldWithViewPos 
                (stateModeOverlay state)
                (0, 0) 
                Nothing
                $ normaliseWorld (stateViewPos state)
                $ stateWorld state

        | otherwise
        = Blank
        

drawWorldWithViewPos :: ModeOverlay -> Point -> Maybe Point -> World -> Picture
drawWorldWithViewPos 
        modeOverlay
        pView@(vx, vy) 
        mTarget
        world
 = let  
        -- the world 
        picWorld        = Color white
                        $ drawWorld world

        -- view position indicator
        picView         = Color red
                        $ Translate vx vy
                        $ ThickCircle 2 4

        -- target position indicator
        picTargets
                | Just pTarget@(px, py) <- mTarget
                = let   picTarget       = Translate px py $ ThickCircle 2 4

                        -- line between view and target pos
                        picLine         = Line [pView, pTarget]
                        
                        picSegsHit      = Pictures
                                        $ [ Line [p1, p2]
                                                | (_, p1, p2)   <- V.toList $ worldSegments world
                                                , isJust $ intersectSegSeg p1 p2 pView pTarget ]
                  in    Color red $ Pictures [picTarget, picLine, picSegsHit]

                | otherwise
                = blank

        -- overlay
        picOverlay
                | ModeOverlayVisApprox  <- modeOverlay
                = drawVisGrid 10 pView world

                | otherwise
                = blank

   in   Pictures [picOverlay, picWorld, picView, picTargets]


-- | Draw a grid of points showing what is visible from a view position
drawVisGrid :: Float -> Point -> World -> Picture
drawVisGrid cellSize pView world
 = let  
        visible pTarget = not $ any isJust
                        $ map (\(_, p1, p2) -> intersectSegSeg pView pTarget p1 p2)
                        $ V.toList 
                        $ worldSegments world
                        
        picGrid         = Pictures
                        $ [ if visible (x, y) 
                                then Color (dim green) $ Translate x y $ rectangleSolid cellSize cellSize
                                else Color (greyN 0.2) $ Translate x y $ rectangleSolid cellSize cellSize
                                | x     <- [-400, -400 + cellSize .. 400]
                                , y     <- [-400, -400 + cellSize .. 400] ]

   in   picGrid


-- | Draw the segments in the world.
drawWorld :: World -> Picture
drawWorld world
        = drawSegments
        $ worldSegments world


-- | Draw an array of segments.
drawSegments :: V.Vector Segment -> Picture
drawSegments segments
        = Pictures
        $ map drawSegment
        $ V.toList 
        $ segments


-- | Draw a single segment.
drawSegment :: Segment -> Picture
drawSegment (_, (x1, y1), (x2, y2))
        = Line [(f x1, f y1), (f x2, f y2)]
        where   f       = fromRational . toRational