--------------------------------------------------------------------------------
-- |
-- Module      :  Data.Geometry.Directions
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
--------------------------------------------------------------------------------
module Data.Geometry.Directions( CardinalDirection(..)
                               -- , _North, _East, _South, _West
                               , oppositeDirection

                                , InterCardinalDirection(..)
                                -- , _NorthWest, _NorthEast, _SouthEast, _SouthWest

                                , interCardinalsOf
                                ) where

import Data.Util
import GHC.Generics (Generic)

--------------------------------------------------------------------------------

-- | The four cardinal directions.
data CardinalDirection = North | East | South | West deriving (Int -> CardinalDirection -> ShowS
[CardinalDirection] -> ShowS
CardinalDirection -> String
(Int -> CardinalDirection -> ShowS)
-> (CardinalDirection -> String)
-> ([CardinalDirection] -> ShowS)
-> Show CardinalDirection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CardinalDirection] -> ShowS
$cshowList :: [CardinalDirection] -> ShowS
show :: CardinalDirection -> String
$cshow :: CardinalDirection -> String
showsPrec :: Int -> CardinalDirection -> ShowS
$cshowsPrec :: Int -> CardinalDirection -> ShowS
Show,ReadPrec [CardinalDirection]
ReadPrec CardinalDirection
Int -> ReadS CardinalDirection
ReadS [CardinalDirection]
(Int -> ReadS CardinalDirection)
-> ReadS [CardinalDirection]
-> ReadPrec CardinalDirection
-> ReadPrec [CardinalDirection]
-> Read CardinalDirection
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CardinalDirection]
$creadListPrec :: ReadPrec [CardinalDirection]
readPrec :: ReadPrec CardinalDirection
$creadPrec :: ReadPrec CardinalDirection
readList :: ReadS [CardinalDirection]
$creadList :: ReadS [CardinalDirection]
readsPrec :: Int -> ReadS CardinalDirection
$creadsPrec :: Int -> ReadS CardinalDirection
Read,CardinalDirection -> CardinalDirection -> Bool
(CardinalDirection -> CardinalDirection -> Bool)
-> (CardinalDirection -> CardinalDirection -> Bool)
-> Eq CardinalDirection
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CardinalDirection -> CardinalDirection -> Bool
$c/= :: CardinalDirection -> CardinalDirection -> Bool
== :: CardinalDirection -> CardinalDirection -> Bool
$c== :: CardinalDirection -> CardinalDirection -> Bool
Eq,Eq CardinalDirection
Eq CardinalDirection
-> (CardinalDirection -> CardinalDirection -> Ordering)
-> (CardinalDirection -> CardinalDirection -> Bool)
-> (CardinalDirection -> CardinalDirection -> Bool)
-> (CardinalDirection -> CardinalDirection -> Bool)
-> (CardinalDirection -> CardinalDirection -> Bool)
-> (CardinalDirection -> CardinalDirection -> CardinalDirection)
-> (CardinalDirection -> CardinalDirection -> CardinalDirection)
-> Ord CardinalDirection
CardinalDirection -> CardinalDirection -> Bool
CardinalDirection -> CardinalDirection -> Ordering
CardinalDirection -> CardinalDirection -> CardinalDirection
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CardinalDirection -> CardinalDirection -> CardinalDirection
$cmin :: CardinalDirection -> CardinalDirection -> CardinalDirection
max :: CardinalDirection -> CardinalDirection -> CardinalDirection
$cmax :: CardinalDirection -> CardinalDirection -> CardinalDirection
>= :: CardinalDirection -> CardinalDirection -> Bool
$c>= :: CardinalDirection -> CardinalDirection -> Bool
> :: CardinalDirection -> CardinalDirection -> Bool
$c> :: CardinalDirection -> CardinalDirection -> Bool
<= :: CardinalDirection -> CardinalDirection -> Bool
$c<= :: CardinalDirection -> CardinalDirection -> Bool
< :: CardinalDirection -> CardinalDirection -> Bool
$c< :: CardinalDirection -> CardinalDirection -> Bool
compare :: CardinalDirection -> CardinalDirection -> Ordering
$ccompare :: CardinalDirection -> CardinalDirection -> Ordering
$cp1Ord :: Eq CardinalDirection
Ord,Int -> CardinalDirection
CardinalDirection -> Int
CardinalDirection -> [CardinalDirection]
CardinalDirection -> CardinalDirection
CardinalDirection -> CardinalDirection -> [CardinalDirection]
CardinalDirection
-> CardinalDirection -> CardinalDirection -> [CardinalDirection]
(CardinalDirection -> CardinalDirection)
-> (CardinalDirection -> CardinalDirection)
-> (Int -> CardinalDirection)
-> (CardinalDirection -> Int)
-> (CardinalDirection -> [CardinalDirection])
-> (CardinalDirection -> CardinalDirection -> [CardinalDirection])
-> (CardinalDirection -> CardinalDirection -> [CardinalDirection])
-> (CardinalDirection
    -> CardinalDirection -> CardinalDirection -> [CardinalDirection])
-> Enum CardinalDirection
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: CardinalDirection
-> CardinalDirection -> CardinalDirection -> [CardinalDirection]
$cenumFromThenTo :: CardinalDirection
-> CardinalDirection -> CardinalDirection -> [CardinalDirection]
enumFromTo :: CardinalDirection -> CardinalDirection -> [CardinalDirection]
$cenumFromTo :: CardinalDirection -> CardinalDirection -> [CardinalDirection]
enumFromThen :: CardinalDirection -> CardinalDirection -> [CardinalDirection]
$cenumFromThen :: CardinalDirection -> CardinalDirection -> [CardinalDirection]
enumFrom :: CardinalDirection -> [CardinalDirection]
$cenumFrom :: CardinalDirection -> [CardinalDirection]
fromEnum :: CardinalDirection -> Int
$cfromEnum :: CardinalDirection -> Int
toEnum :: Int -> CardinalDirection
$ctoEnum :: Int -> CardinalDirection
pred :: CardinalDirection -> CardinalDirection
$cpred :: CardinalDirection -> CardinalDirection
succ :: CardinalDirection -> CardinalDirection
$csucc :: CardinalDirection -> CardinalDirection
Enum,CardinalDirection
CardinalDirection -> CardinalDirection -> Bounded CardinalDirection
forall a. a -> a -> Bounded a
maxBound :: CardinalDirection
$cmaxBound :: CardinalDirection
minBound :: CardinalDirection
$cminBound :: CardinalDirection
Bounded)
-- makePrisms ''CardinalDirection

--------------------------------------------------------------------------------
-- * Functions on Cardinal Directions

-- | Computes the direction opposite to the given one.
oppositeDirection :: CardinalDirection -> CardinalDirection
oppositeDirection :: CardinalDirection -> CardinalDirection
oppositeDirection = \case
  CardinalDirection
North -> CardinalDirection
South
  CardinalDirection
East  -> CardinalDirection
West
  CardinalDirection
South -> CardinalDirection
North
  CardinalDirection
West  -> CardinalDirection
East

--------------------------------------------------------------------------------

-- | Intercardinal directions
data InterCardinalDirection = NorthWest | NorthEast | SouthEast | SouthWest
  deriving (Int -> InterCardinalDirection -> ShowS
[InterCardinalDirection] -> ShowS
InterCardinalDirection -> String
(Int -> InterCardinalDirection -> ShowS)
-> (InterCardinalDirection -> String)
-> ([InterCardinalDirection] -> ShowS)
-> Show InterCardinalDirection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [InterCardinalDirection] -> ShowS
$cshowList :: [InterCardinalDirection] -> ShowS
show :: InterCardinalDirection -> String
$cshow :: InterCardinalDirection -> String
showsPrec :: Int -> InterCardinalDirection -> ShowS
$cshowsPrec :: Int -> InterCardinalDirection -> ShowS
Show,ReadPrec [InterCardinalDirection]
ReadPrec InterCardinalDirection
Int -> ReadS InterCardinalDirection
ReadS [InterCardinalDirection]
(Int -> ReadS InterCardinalDirection)
-> ReadS [InterCardinalDirection]
-> ReadPrec InterCardinalDirection
-> ReadPrec [InterCardinalDirection]
-> Read InterCardinalDirection
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [InterCardinalDirection]
$creadListPrec :: ReadPrec [InterCardinalDirection]
readPrec :: ReadPrec InterCardinalDirection
$creadPrec :: ReadPrec InterCardinalDirection
readList :: ReadS [InterCardinalDirection]
$creadList :: ReadS [InterCardinalDirection]
readsPrec :: Int -> ReadS InterCardinalDirection
$creadsPrec :: Int -> ReadS InterCardinalDirection
Read,InterCardinalDirection -> InterCardinalDirection -> Bool
(InterCardinalDirection -> InterCardinalDirection -> Bool)
-> (InterCardinalDirection -> InterCardinalDirection -> Bool)
-> Eq InterCardinalDirection
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: InterCardinalDirection -> InterCardinalDirection -> Bool
$c/= :: InterCardinalDirection -> InterCardinalDirection -> Bool
== :: InterCardinalDirection -> InterCardinalDirection -> Bool
$c== :: InterCardinalDirection -> InterCardinalDirection -> Bool
Eq,Eq InterCardinalDirection
Eq InterCardinalDirection
-> (InterCardinalDirection -> InterCardinalDirection -> Ordering)
-> (InterCardinalDirection -> InterCardinalDirection -> Bool)
-> (InterCardinalDirection -> InterCardinalDirection -> Bool)
-> (InterCardinalDirection -> InterCardinalDirection -> Bool)
-> (InterCardinalDirection -> InterCardinalDirection -> Bool)
-> (InterCardinalDirection
    -> InterCardinalDirection -> InterCardinalDirection)
-> (InterCardinalDirection
    -> InterCardinalDirection -> InterCardinalDirection)
-> Ord InterCardinalDirection
InterCardinalDirection -> InterCardinalDirection -> Bool
InterCardinalDirection -> InterCardinalDirection -> Ordering
InterCardinalDirection
-> InterCardinalDirection -> InterCardinalDirection
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: InterCardinalDirection
-> InterCardinalDirection -> InterCardinalDirection
$cmin :: InterCardinalDirection
-> InterCardinalDirection -> InterCardinalDirection
max :: InterCardinalDirection
-> InterCardinalDirection -> InterCardinalDirection
$cmax :: InterCardinalDirection
-> InterCardinalDirection -> InterCardinalDirection
>= :: InterCardinalDirection -> InterCardinalDirection -> Bool
$c>= :: InterCardinalDirection -> InterCardinalDirection -> Bool
> :: InterCardinalDirection -> InterCardinalDirection -> Bool
$c> :: InterCardinalDirection -> InterCardinalDirection -> Bool
<= :: InterCardinalDirection -> InterCardinalDirection -> Bool
$c<= :: InterCardinalDirection -> InterCardinalDirection -> Bool
< :: InterCardinalDirection -> InterCardinalDirection -> Bool
$c< :: InterCardinalDirection -> InterCardinalDirection -> Bool
compare :: InterCardinalDirection -> InterCardinalDirection -> Ordering
$ccompare :: InterCardinalDirection -> InterCardinalDirection -> Ordering
$cp1Ord :: Eq InterCardinalDirection
Ord,Int -> InterCardinalDirection
InterCardinalDirection -> Int
InterCardinalDirection -> [InterCardinalDirection]
InterCardinalDirection -> InterCardinalDirection
InterCardinalDirection
-> InterCardinalDirection -> [InterCardinalDirection]
InterCardinalDirection
-> InterCardinalDirection
-> InterCardinalDirection
-> [InterCardinalDirection]
(InterCardinalDirection -> InterCardinalDirection)
-> (InterCardinalDirection -> InterCardinalDirection)
-> (Int -> InterCardinalDirection)
-> (InterCardinalDirection -> Int)
-> (InterCardinalDirection -> [InterCardinalDirection])
-> (InterCardinalDirection
    -> InterCardinalDirection -> [InterCardinalDirection])
-> (InterCardinalDirection
    -> InterCardinalDirection -> [InterCardinalDirection])
-> (InterCardinalDirection
    -> InterCardinalDirection
    -> InterCardinalDirection
    -> [InterCardinalDirection])
-> Enum InterCardinalDirection
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: InterCardinalDirection
-> InterCardinalDirection
-> InterCardinalDirection
-> [InterCardinalDirection]
$cenumFromThenTo :: InterCardinalDirection
-> InterCardinalDirection
-> InterCardinalDirection
-> [InterCardinalDirection]
enumFromTo :: InterCardinalDirection
-> InterCardinalDirection -> [InterCardinalDirection]
$cenumFromTo :: InterCardinalDirection
-> InterCardinalDirection -> [InterCardinalDirection]
enumFromThen :: InterCardinalDirection
-> InterCardinalDirection -> [InterCardinalDirection]
$cenumFromThen :: InterCardinalDirection
-> InterCardinalDirection -> [InterCardinalDirection]
enumFrom :: InterCardinalDirection -> [InterCardinalDirection]
$cenumFrom :: InterCardinalDirection -> [InterCardinalDirection]
fromEnum :: InterCardinalDirection -> Int
$cfromEnum :: InterCardinalDirection -> Int
toEnum :: Int -> InterCardinalDirection
$ctoEnum :: Int -> InterCardinalDirection
pred :: InterCardinalDirection -> InterCardinalDirection
$cpred :: InterCardinalDirection -> InterCardinalDirection
succ :: InterCardinalDirection -> InterCardinalDirection
$csucc :: InterCardinalDirection -> InterCardinalDirection
Enum,(forall x. InterCardinalDirection -> Rep InterCardinalDirection x)
-> (forall x.
    Rep InterCardinalDirection x -> InterCardinalDirection)
-> Generic InterCardinalDirection
forall x. Rep InterCardinalDirection x -> InterCardinalDirection
forall x. InterCardinalDirection -> Rep InterCardinalDirection x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep InterCardinalDirection x -> InterCardinalDirection
$cfrom :: forall x. InterCardinalDirection -> Rep InterCardinalDirection x
Generic)
-- makePrisms ''InterCardinalDirection

--------------------------------------------------------------------------------
-- * Functions on InterCardinal Directions

-- | Get the two intercardinal directions, in increasing order,
-- corresponding to the cardinal direction.
interCardinalsOf :: CardinalDirection -> Two InterCardinalDirection
interCardinalsOf :: CardinalDirection -> Two InterCardinalDirection
interCardinalsOf = \case
  CardinalDirection
North -> InterCardinalDirection
-> InterCardinalDirection -> Two InterCardinalDirection
forall a. a -> a -> Two a
Two InterCardinalDirection
NorthWest InterCardinalDirection
NorthEast
  CardinalDirection
East  -> InterCardinalDirection
-> InterCardinalDirection -> Two InterCardinalDirection
forall a. a -> a -> Two a
Two InterCardinalDirection
NorthEast InterCardinalDirection
SouthEast
  CardinalDirection
South -> InterCardinalDirection
-> InterCardinalDirection -> Two InterCardinalDirection
forall a. a -> a -> Two a
Two InterCardinalDirection
SouthEast InterCardinalDirection
SouthWest
  CardinalDirection
West  -> InterCardinalDirection
-> InterCardinalDirection -> Two InterCardinalDirection
forall a. a -> a -> Two a
Two InterCardinalDirection
SouthWest InterCardinalDirection
NorthWest