{-# language RecordWildCards #-}

module CodeWorld.Test.Relative (
  Components(..),
  RelativePicSpec(..),
  SpatialQuery,
  (===),
  toRelative,
  isSouthOf,
  isNorthOf,
  isWestOf,
  isEastOf,
  isSouthEastOf,
  isSouthWestOf,
  isNorthEastOf,
  isNorthWestOf,
  isBelow,
  isAbove,
  isLeftOf,
  isRightOf,
  atSamePosition,
  )where


import Data.List                        (sort)

import CodeWorld.Tasks.API              (Drawable(..))
import CodeWorld.Test.AbsTypes          (Position(..), fromPosition)
import CodeWorld.Test.Normalize (
  NormalizedPicture(..),
  getSubPictures,
  stripTranslation,
  getTranslation,
  couldHaveTranslation,
  contains,
  )


{- |
Alias for queries on spatial relationships.
-}
type SpatialQuery = [RelativePicSpec] -> Bool

data DirectionV = South deriving (DirectionV -> DirectionV -> Bool
(DirectionV -> DirectionV -> Bool)
-> (DirectionV -> DirectionV -> Bool) -> Eq DirectionV
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DirectionV -> DirectionV -> Bool
== :: DirectionV -> DirectionV -> Bool
$c/= :: DirectionV -> DirectionV -> Bool
/= :: DirectionV -> DirectionV -> Bool
Eq,Eq DirectionV
Eq DirectionV =>
(DirectionV -> DirectionV -> Ordering)
-> (DirectionV -> DirectionV -> Bool)
-> (DirectionV -> DirectionV -> Bool)
-> (DirectionV -> DirectionV -> Bool)
-> (DirectionV -> DirectionV -> Bool)
-> (DirectionV -> DirectionV -> DirectionV)
-> (DirectionV -> DirectionV -> DirectionV)
-> Ord DirectionV
DirectionV -> DirectionV -> Bool
DirectionV -> DirectionV -> Ordering
DirectionV -> DirectionV -> DirectionV
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
$ccompare :: DirectionV -> DirectionV -> Ordering
compare :: DirectionV -> DirectionV -> Ordering
$c< :: DirectionV -> DirectionV -> Bool
< :: DirectionV -> DirectionV -> Bool
$c<= :: DirectionV -> DirectionV -> Bool
<= :: DirectionV -> DirectionV -> Bool
$c> :: DirectionV -> DirectionV -> Bool
> :: DirectionV -> DirectionV -> Bool
$c>= :: DirectionV -> DirectionV -> Bool
>= :: DirectionV -> DirectionV -> Bool
$cmax :: DirectionV -> DirectionV -> DirectionV
max :: DirectionV -> DirectionV -> DirectionV
$cmin :: DirectionV -> DirectionV -> DirectionV
min :: DirectionV -> DirectionV -> DirectionV
Ord,Int -> DirectionV -> ShowS
[DirectionV] -> ShowS
DirectionV -> String
(Int -> DirectionV -> ShowS)
-> (DirectionV -> String)
-> ([DirectionV] -> ShowS)
-> Show DirectionV
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DirectionV -> ShowS
showsPrec :: Int -> DirectionV -> ShowS
$cshow :: DirectionV -> String
show :: DirectionV -> String
$cshowList :: [DirectionV] -> ShowS
showList :: [DirectionV] -> ShowS
Show)
data DirectionH = West | East deriving (DirectionH -> DirectionH -> Bool
(DirectionH -> DirectionH -> Bool)
-> (DirectionH -> DirectionH -> Bool) -> Eq DirectionH
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DirectionH -> DirectionH -> Bool
== :: DirectionH -> DirectionH -> Bool
$c/= :: DirectionH -> DirectionH -> Bool
/= :: DirectionH -> DirectionH -> Bool
Eq,Eq DirectionH
Eq DirectionH =>
(DirectionH -> DirectionH -> Ordering)
-> (DirectionH -> DirectionH -> Bool)
-> (DirectionH -> DirectionH -> Bool)
-> (DirectionH -> DirectionH -> Bool)
-> (DirectionH -> DirectionH -> Bool)
-> (DirectionH -> DirectionH -> DirectionH)
-> (DirectionH -> DirectionH -> DirectionH)
-> Ord DirectionH
DirectionH -> DirectionH -> Bool
DirectionH -> DirectionH -> Ordering
DirectionH -> DirectionH -> DirectionH
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
$ccompare :: DirectionH -> DirectionH -> Ordering
compare :: DirectionH -> DirectionH -> Ordering
$c< :: DirectionH -> DirectionH -> Bool
< :: DirectionH -> DirectionH -> Bool
$c<= :: DirectionH -> DirectionH -> Bool
<= :: DirectionH -> DirectionH -> Bool
$c> :: DirectionH -> DirectionH -> Bool
> :: DirectionH -> DirectionH -> Bool
$c>= :: DirectionH -> DirectionH -> Bool
>= :: DirectionH -> DirectionH -> Bool
$cmax :: DirectionH -> DirectionH -> DirectionH
max :: DirectionH -> DirectionH -> DirectionH
$cmin :: DirectionH -> DirectionH -> DirectionH
min :: DirectionH -> DirectionH -> DirectionH
Ord,Int -> DirectionH -> ShowS
[DirectionH] -> ShowS
DirectionH -> String
(Int -> DirectionH -> ShowS)
-> (DirectionH -> String)
-> ([DirectionH] -> ShowS)
-> Show DirectionH
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DirectionH -> ShowS
showsPrec :: Int -> DirectionH -> ShowS
$cshow :: DirectionH -> String
show :: DirectionH -> String
$cshowList :: [DirectionH] -> ShowS
showList :: [DirectionH] -> ShowS
Show)

data Direction = Direction {
  Direction -> Maybe DirectionV
vertical :: Maybe DirectionV,
  Direction -> Maybe DirectionH
horizontal :: Maybe DirectionH
} deriving (Direction -> Direction -> Bool
(Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool) -> Eq Direction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Direction -> Direction -> Bool
== :: Direction -> Direction -> Bool
$c/= :: Direction -> Direction -> Bool
/= :: Direction -> Direction -> Bool
Eq,Eq Direction
Eq Direction =>
(Direction -> Direction -> Ordering)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Direction)
-> (Direction -> Direction -> Direction)
-> Ord Direction
Direction -> Direction -> Bool
Direction -> Direction -> Ordering
Direction -> Direction -> Direction
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
$ccompare :: Direction -> Direction -> Ordering
compare :: Direction -> Direction -> Ordering
$c< :: Direction -> Direction -> Bool
< :: Direction -> Direction -> Bool
$c<= :: Direction -> Direction -> Bool
<= :: Direction -> Direction -> Bool
$c> :: Direction -> Direction -> Bool
> :: Direction -> Direction -> Bool
$c>= :: Direction -> Direction -> Bool
>= :: Direction -> Direction -> Bool
$cmax :: Direction -> Direction -> Direction
max :: Direction -> Direction -> Direction
$cmin :: Direction -> Direction -> Direction
min :: Direction -> Direction -> Direction
Ord)


{- |
Abstract representation of spatial positioning between two picture components.
-}
data RelativePicSpec
  = Is NormalizedPicture Direction NormalizedPicture
  | Alone NormalizedPicture
  deriving(RelativePicSpec -> RelativePicSpec -> Bool
(RelativePicSpec -> RelativePicSpec -> Bool)
-> (RelativePicSpec -> RelativePicSpec -> Bool)
-> Eq RelativePicSpec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RelativePicSpec -> RelativePicSpec -> Bool
== :: RelativePicSpec -> RelativePicSpec -> Bool
$c/= :: RelativePicSpec -> RelativePicSpec -> Bool
/= :: RelativePicSpec -> RelativePicSpec -> Bool
Eq,Eq RelativePicSpec
Eq RelativePicSpec =>
(RelativePicSpec -> RelativePicSpec -> Ordering)
-> (RelativePicSpec -> RelativePicSpec -> Bool)
-> (RelativePicSpec -> RelativePicSpec -> Bool)
-> (RelativePicSpec -> RelativePicSpec -> Bool)
-> (RelativePicSpec -> RelativePicSpec -> Bool)
-> (RelativePicSpec -> RelativePicSpec -> RelativePicSpec)
-> (RelativePicSpec -> RelativePicSpec -> RelativePicSpec)
-> Ord RelativePicSpec
RelativePicSpec -> RelativePicSpec -> Bool
RelativePicSpec -> RelativePicSpec -> Ordering
RelativePicSpec -> RelativePicSpec -> RelativePicSpec
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
$ccompare :: RelativePicSpec -> RelativePicSpec -> Ordering
compare :: RelativePicSpec -> RelativePicSpec -> Ordering
$c< :: RelativePicSpec -> RelativePicSpec -> Bool
< :: RelativePicSpec -> RelativePicSpec -> Bool
$c<= :: RelativePicSpec -> RelativePicSpec -> Bool
<= :: RelativePicSpec -> RelativePicSpec -> Bool
$c> :: RelativePicSpec -> RelativePicSpec -> Bool
> :: RelativePicSpec -> RelativePicSpec -> Bool
$c>= :: RelativePicSpec -> RelativePicSpec -> Bool
>= :: RelativePicSpec -> RelativePicSpec -> Bool
$cmax :: RelativePicSpec -> RelativePicSpec -> RelativePicSpec
max :: RelativePicSpec -> RelativePicSpec -> RelativePicSpec
$cmin :: RelativePicSpec -> RelativePicSpec -> RelativePicSpec
min :: RelativePicSpec -> RelativePicSpec -> RelativePicSpec
Ord)


{- |
Abstract representation of a picture in terms of its components
and the pairwise spatial positioning between them.
-}
newtype Components = Components (NormalizedPicture,[RelativePicSpec]) deriving (Components -> Components -> Bool
(Components -> Components -> Bool)
-> (Components -> Components -> Bool) -> Eq Components
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Components -> Components -> Bool
== :: Components -> Components -> Bool
$c/= :: Components -> Components -> Bool
/= :: Components -> Components -> Bool
Eq,Eq Components
Eq Components =>
(Components -> Components -> Ordering)
-> (Components -> Components -> Bool)
-> (Components -> Components -> Bool)
-> (Components -> Components -> Bool)
-> (Components -> Components -> Bool)
-> (Components -> Components -> Components)
-> (Components -> Components -> Components)
-> Ord Components
Components -> Components -> Bool
Components -> Components -> Ordering
Components -> Components -> Components
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
$ccompare :: Components -> Components -> Ordering
compare :: Components -> Components -> Ordering
$c< :: Components -> Components -> Bool
< :: Components -> Components -> Bool
$c<= :: Components -> Components -> Bool
<= :: Components -> Components -> Bool
$c> :: Components -> Components -> Bool
> :: Components -> Components -> Bool
$c>= :: Components -> Components -> Bool
>= :: Components -> Components -> Bool
$cmax :: Components -> Components -> Components
max :: Components -> Components -> Components
$cmin :: Components -> Components -> Components
min :: Components -> Components -> Components
Ord,Int -> Components -> ShowS
[Components] -> ShowS
Components -> String
(Int -> Components -> ShowS)
-> (Components -> String)
-> ([Components] -> ShowS)
-> Show Components
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Components -> ShowS
showsPrec :: Int -> Components -> ShowS
$cshow :: Components -> String
show :: Components -> String
$cshowList :: [Components] -> ShowS
showList :: [Components] -> ShowS
Show)


instance Show Direction where
  show :: Direction -> String
show Direction{Maybe DirectionH
Maybe DirectionV
vertical :: Direction -> Maybe DirectionV
horizontal :: Direction -> Maybe DirectionH
vertical :: Maybe DirectionV
horizontal :: Maybe DirectionH
..} = case (Maybe DirectionV
vertical, Maybe DirectionH
horizontal) of
    (Maybe DirectionV
Nothing, Maybe DirectionH
Nothing) -> String
"OnTop"
    (Maybe DirectionV
Nothing, Just DirectionH
a)  -> DirectionH -> String
forall a. Show a => a -> String
show DirectionH
a
    (Just DirectionV
a, Maybe DirectionH
Nothing)  -> DirectionV -> String
forall a. Show a => a -> String
show DirectionV
a
    (Just DirectionV
a, Just DirectionH
b)   -> DirectionV -> String
forall a. Show a => a -> String
show DirectionV
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ DirectionH -> String
forall a. Show a => a -> String
show DirectionH
b


instance Show RelativePicSpec where
  show :: RelativePicSpec -> String
show (Is NormalizedPicture
p1 Direction
dir NormalizedPicture
p2) = NormalizedPicture -> String
forall a. Show a => a -> String
show NormalizedPicture
p1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" is " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Direction -> String
forall a. Show a => a -> String
show Direction
dir String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" of " String -> ShowS
forall a. [a] -> [a] -> [a]
++ NormalizedPicture -> String
forall a. Show a => a -> String
show NormalizedPicture
p2
  show (Alone NormalizedPicture
p) = NormalizedPicture -> String
forall a. Show a => a -> String
show NormalizedPicture
p



(===) :: NormalizedPicture -> NormalizedPicture -> Bool
NormalizedPicture
p1 === :: NormalizedPicture -> NormalizedPicture -> Bool
=== NormalizedPicture
p2 = NormalizedPicture -> Components
toRelative NormalizedPicture
p1 Components -> Components -> Bool
forall a. Eq a => a -> a -> Bool
== NormalizedPicture -> Components
toRelative NormalizedPicture
p2


southOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southOf NormalizedPicture
p1 = NormalizedPicture
-> Direction -> NormalizedPicture -> RelativePicSpec
Is NormalizedPicture
p1 (Maybe DirectionV -> Maybe DirectionH -> Direction
Direction (DirectionV -> Maybe DirectionV
forall a. a -> Maybe a
Just DirectionV
South) Maybe DirectionH
forall a. Maybe a
Nothing)


northOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec)
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
forall a b c. (a -> b -> c) -> b -> a -> c
flip NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southOf


westOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
westOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
westOf NormalizedPicture
p1 = NormalizedPicture
-> Direction -> NormalizedPicture -> RelativePicSpec
Is NormalizedPicture
p1 (Maybe DirectionV -> Maybe DirectionH -> Direction
Direction  Maybe DirectionV
forall a. Maybe a
Nothing (DirectionH -> Maybe DirectionH
forall a. a -> Maybe a
Just DirectionH
West))


eastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
eastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
eastOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec)
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
forall a b c. (a -> b -> c) -> b -> a -> c
flip NormalizedPicture -> NormalizedPicture -> RelativePicSpec
westOf


onTopOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
onTopOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
onTopOf NormalizedPicture
p1 = NormalizedPicture
-> Direction -> NormalizedPicture -> RelativePicSpec
Is NormalizedPicture
p1 (Maybe DirectionV -> Maybe DirectionH -> Direction
Direction Maybe DirectionV
forall a. Maybe a
Nothing Maybe DirectionH
forall a. Maybe a
Nothing)


southwestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southwestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southwestOf NormalizedPicture
p1 = NormalizedPicture
-> Direction -> NormalizedPicture -> RelativePicSpec
Is NormalizedPicture
p1 (Maybe DirectionV -> Maybe DirectionH -> Direction
Direction (DirectionV -> Maybe DirectionV
forall a. a -> Maybe a
Just DirectionV
South) (DirectionH -> Maybe DirectionH
forall a. a -> Maybe a
Just DirectionH
West))


southeastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southeastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southeastOf NormalizedPicture
p1 = NormalizedPicture
-> Direction -> NormalizedPicture -> RelativePicSpec
Is NormalizedPicture
p1 (Maybe DirectionV -> Maybe DirectionH -> Direction
Direction (DirectionV -> Maybe DirectionV
forall a. a -> Maybe a
Just DirectionV
South) (DirectionH -> Maybe DirectionH
forall a. a -> Maybe a
Just DirectionH
East))


northwestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northwestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northwestOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec)
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
forall a b c. (a -> b -> c) -> b -> a -> c
flip NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southeastOf


northeastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northeastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northeastOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec)
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
forall a b c. (a -> b -> c) -> b -> a -> c
flip NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southwestOf


alone :: NormalizedPicture -> RelativePicSpec
alone :: NormalizedPicture -> RelativePicSpec
alone = NormalizedPicture -> RelativePicSpec
Alone


containedSouthOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) Maybe DirectionH
Nothing) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedSouthOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedNorthOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) Maybe DirectionH
Nothing) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedNorthOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedWestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedWestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedWestOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
Nothing (Just DirectionH
West)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedWestOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
Nothing (Just DirectionH
East)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedWestOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedEastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedEastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedEastOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
Nothing (Just DirectionH
East)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedEastOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
Nothing (Just DirectionH
West)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedEastOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedSouthWestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthWestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthWestOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) (Just DirectionH
West)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedSouthWestOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedSouthEastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthEastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthEastOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) (Just DirectionH
East)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedSouthEastOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedNorthWestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthWestOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthWestOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) (Just DirectionH
East)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedNorthWestOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedNorthEastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthEastOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthEastOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) (Just DirectionH
West)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedNorthEastOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedAbove :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedAbove :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedAbove NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) Maybe DirectionH
_) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedAbove NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedBelow :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedBelow :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedBelow NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction (Just DirectionV
South) Maybe DirectionH
_) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedBelow NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedLeftOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedLeftOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedLeftOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
_ (Just DirectionH
West)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedLeftOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
_ (Just DirectionH
East)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedLeftOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedRightOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedRightOf :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedRightOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
_ (Just DirectionH
East)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q
containedRightOf NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
_ (Just DirectionH
West)) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedRightOf NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


containedSameSpot :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSameSpot :: NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSameSpot NormalizedPicture
p NormalizedPicture
q (Is NormalizedPicture
p1 (Direction Maybe DirectionV
Nothing Maybe DirectionH
Nothing) NormalizedPicture
p2) =
  NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
|| NormalizedPicture
p1 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
q Bool -> Bool -> Bool
&& NormalizedPicture
p2 NormalizedPicture -> NormalizedPicture -> Bool
`contains` NormalizedPicture
p
containedSameSpot NormalizedPicture
_ NormalizedPicture
_ RelativePicSpec
_ = Bool
False


{- |
True if the first argument is below the second and aligned on the X-axis.
-}
isSouthOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isSouthOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isSouthOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthOf


{- |
True if the first argument is above the second and aligned on the X-axis.
-}
isNorthOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isNorthOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isNorthOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthOf


{- |
True if the first argument is left of the second and aligned on the Y-axis.
-}
isWestOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isWestOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isWestOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedWestOf


{- |
True if the first argument is right of the second and aligned on the Y-axis.
-}
isEastOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isEastOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isEastOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedEastOf


{- |
True if the first argument is below and to the left of the second.
-}
isSouthWestOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isSouthWestOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isSouthWestOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthWestOf


{- |
True if the first argument is below and to the right of the second.
-}
isSouthEastOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isSouthEastOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isSouthEastOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSouthEastOf


{- |
True if the first argument is above and to the left of the second.
-}
isNorthWestOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isNorthWestOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isNorthWestOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthWestOf


{- |
True if the first argument is above and to the right of the second.
-}
isNorthEastOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isNorthEastOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isNorthEastOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedNorthEastOf


{- |
True if the first argument is above the second, ignoring horizontal positioning.
-}
isAbove :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isAbove :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isAbove = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedAbove


{- |
True if the first argument is below the second, ignoring horizontal positioning.
-}
isBelow :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isBelow :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isBelow = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedBelow


{- |
True if the first argument is left of the second, ignoring vertical positioning.
-}
isLeftOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isLeftOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isLeftOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedLeftOf


{- |
True if the first argument is right of the second, ignoring vertical positioning.
-}
isRightOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isRightOf :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
isRightOf = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedRightOf


{- |
True if the first argument is at the same position as the second.
-}
atSamePosition :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
atSamePosition :: NormalizedPicture -> NormalizedPicture -> SpatialQuery
atSamePosition = (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
containedSameSpot


compositeRelation
  :: (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
  -> NormalizedPicture
  -> NormalizedPicture
  -> SpatialQuery
compositeRelation :: (NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool)
-> NormalizedPicture -> NormalizedPicture -> SpatialQuery
compositeRelation NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
g NormalizedPicture
p NormalizedPicture
q [RelativePicSpec]
rs = ((RelativePicSpec -> Bool) -> Bool)
-> [RelativePicSpec -> Bool] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((RelativePicSpec -> Bool) -> SpatialQuery
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
`any` [RelativePicSpec]
rs) [RelativePicSpec -> Bool]
allRelations
  where
    allRelations :: [RelativePicSpec -> Bool]
allRelations = [NormalizedPicture -> NormalizedPicture -> RelativePicSpec -> Bool
g NormalizedPicture
x NormalizedPicture
y | NormalizedPicture
x <- NormalizedPicture -> [NormalizedPicture]
getSubPictures NormalizedPicture
p, NormalizedPicture
y <- NormalizedPicture -> [NormalizedPicture]
getSubPictures NormalizedPicture
q]


toRelative :: NormalizedPicture -> Components
toRelative :: NormalizedPicture -> Components
toRelative NormalizedPicture
p = case NormalizedPicture
p of
  Pictures [NormalizedPicture]
ps -> (NormalizedPicture, [RelativePicSpec]) -> Components
Components ([NormalizedPicture] -> NormalizedPicture
Pictures ([NormalizedPicture] -> NormalizedPicture)
-> [NormalizedPicture] -> NormalizedPicture
forall a b. (a -> b) -> a -> b
$ (NormalizedPicture -> NormalizedPicture)
-> [NormalizedPicture] -> [NormalizedPicture]
forall a b. (a -> b) -> [a] -> [b]
map NormalizedPicture -> NormalizedPicture
stripTranslation [NormalizedPicture]
ps, [RelativePicSpec] -> [RelativePicSpec]
forall a. Ord a => [a] -> [a]
sort ([RelativePicSpec] -> [RelativePicSpec])
-> [RelativePicSpec] -> [RelativePicSpec]
forall a b. (a -> b) -> a -> b
$ [NormalizedPicture] -> [RelativePicSpec]
relativePosition [NormalizedPicture]
ps)
  NormalizedPicture
a           -> let noTranslation :: NormalizedPicture
noTranslation = NormalizedPicture -> NormalizedPicture
stripTranslation NormalizedPicture
a in
    (NormalizedPicture, [RelativePicSpec]) -> Components
Components (NormalizedPicture
noTranslation,[NormalizedPicture -> RelativePicSpec
alone NormalizedPicture
noTranslation])


relativePosition :: [NormalizedPicture] -> [RelativePicSpec]
relativePosition :: [NormalizedPicture] -> [RelativePicSpec]
relativePosition [] = []
relativePosition (NormalizedPicture
p:[NormalizedPicture]
ps)
  | NormalizedPicture -> Bool
couldHaveTranslation NormalizedPicture
p = [RelativePicSpec]
othersTrans [RelativePicSpec] -> [RelativePicSpec] -> [RelativePicSpec]
forall a. [a] -> [a] -> [a]
++ [NormalizedPicture] -> [RelativePicSpec]
relativePosition [NormalizedPicture]
ps
  | Bool
otherwise = [RelativePicSpec]
others [RelativePicSpec] -> [RelativePicSpec] -> [RelativePicSpec]
forall a. [a] -> [a] -> [a]
++ [NormalizedPicture] -> [RelativePicSpec]
relativePosition [NormalizedPicture]
ps
  where
    (Position
pX,Position
pY) = NormalizedPicture -> (Position, Position)
getTranslation NormalizedPicture
p

    asCenter :: NormalizedPicture -> NormalizedPicture
asCenter NormalizedPicture
pic = let (Position
bX,Position
bY) = NormalizedPicture -> (Position, Position)
getTranslation NormalizedPicture
pic in
      Double -> Double -> NormalizedPicture -> NormalizedPicture
forall a. Drawable a => Double -> Double -> a -> a
translated (Position -> Double
fromPosition (Position -> Double) -> Position -> Double
forall a b. (a -> b) -> a -> b
$ Position
bXPosition -> Position -> Position
forall a. Num a => a -> a -> a
-Position
pX) (Position -> Double
fromPosition (Position -> Double) -> Position -> Double
forall a b. (a -> b) -> a -> b
$ Position
bYPosition -> Position -> Position
forall a. Num a => a -> a -> a
-Position
pY) (NormalizedPicture -> NormalizedPicture)
-> NormalizedPicture -> NormalizedPicture
forall a b. (a -> b) -> a -> b
$ NormalizedPicture -> NormalizedPicture
stripTranslation NormalizedPicture
pic

    othersTrans :: [RelativePicSpec]
othersTrans = (NormalizedPicture -> RelativePicSpec)
-> [NormalizedPicture] -> [RelativePicSpec]
forall a b. (a -> b) -> [a] -> [b]
map (\NormalizedPicture
pic ->
        NormalizedPicture
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
orientation (NormalizedPicture -> NormalizedPicture
asCenter NormalizedPicture
pic) (NormalizedPicture -> NormalizedPicture
stripTranslation NormalizedPicture
p) (NormalizedPicture -> RelativePicSpec)
-> NormalizedPicture -> RelativePicSpec
forall a b. (a -> b) -> a -> b
$ NormalizedPicture -> NormalizedPicture
stripTranslation NormalizedPicture
pic
        )
      [NormalizedPicture]
ps

    others :: [RelativePicSpec]
others = (NormalizedPicture -> RelativePicSpec)
-> [NormalizedPicture] -> [RelativePicSpec]
forall a b. (a -> b) -> [a] -> [b]
map (\NormalizedPicture
pic -> NormalizedPicture
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
orientation NormalizedPicture
pic NormalizedPicture
p (NormalizedPicture -> RelativePicSpec)
-> NormalizedPicture -> RelativePicSpec
forall a b. (a -> b) -> a -> b
$ NormalizedPicture -> NormalizedPicture
stripTranslation NormalizedPicture
pic) [NormalizedPicture]
ps


orientation
  :: NormalizedPicture
  -> NormalizedPicture
  -> NormalizedPicture
  -> RelativePicSpec
orientation :: NormalizedPicture
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
orientation = (Position, Position)
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
toDirection ((Position, Position)
 -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec)
-> (NormalizedPicture -> (Position, Position))
-> NormalizedPicture
-> NormalizedPicture
-> NormalizedPicture
-> RelativePicSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NormalizedPicture -> (Position, Position)
getTranslation
  where
    toDirection :: (Position, Position)
-> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
toDirection (Position
a,Position
b) = case (Position
a,Position
b) of
      (Position
Zero , Neg Double
_) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northOf
      (Position
Zero , Pos Double
_) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southOf
      (Neg Double
_, Position
Zero ) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
eastOf
      (Pos Double
_, Position
Zero ) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
westOf
      (Pos Double
_, Pos Double
_) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southwestOf
      (Pos Double
_, Neg Double
_) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northwestOf
      (Neg Double
_, Pos Double
_) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
southeastOf
      (Neg Double
_, Neg Double
_) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
northeastOf
      (Position
Zero , Position
Zero ) -> NormalizedPicture -> NormalizedPicture -> RelativePicSpec
onTopOf