{-# language DeriveDataTypeable #-}
{-# language FlexibleInstances #-}

module CodeWorld.Test.Abstract (
  AbstractPicture(..),
  contains,
  couldHaveTranslation,
  count,
  getColor,
  getRotation,
  getExactRotation,
  getScalingFactors,
  getExactScalingFactors,
  getTranslation,
  getExactTranslation,
  getReflectionAngle,
  getExactReflectionAngle,
  getCircleRadius,
  getExactCircleRadius,
  getRectangleLengths,
  getExactRectangleLengths,
  getExactPointList,
  getSubPictures,
  stripTranslation,
  toConcretePicture,
  ) where


import Data.Data                        (Data)
import Data.Text                        (Text)
import Data.List.Extra                  (headDef)
import Data.Maybe                       (listToMaybe)
import Data.Tuple.Extra                 (both)
import Data.Generics.Uniplate.Data      (universe)

import CodeWorld.Tasks.API              (Drawable(..))
import CodeWorld.Tasks.VectorSpace (
  Point,
  atOriginWithOffset,
  )
import CodeWorld.Test.AbsTypes

import qualified CodeWorld.Tasks.Picture as P
import qualified CodeWorld.Tasks.Types as PT


{- |
A more abstract syntax tree representing images.
Comparisons between values of this type are intentionally fuzzy:
Concrete number or point values are abstracted into coarser categories.
Notably, those values are not lost and can be retrieved if desired.

The constructors of this type are not exposed.
Values are built using the CodeWorld API.
-}
data AbstractPicture
  = Rectangle !ShapeKind !Size !Size
  | Circle !ShapeKind !Size
  | Lettering !Text
  | Color !AbsColor !AbstractPicture
  | Translate !Position !Position !AbstractPicture
  | Scale !Factor !Factor !AbstractPicture
  | Rotate !Angle !AbstractPicture
  | Pictures [AbstractPicture]
  | CoordinatePlane
  | 
  | Blank
  | Polyline !ShapeKind [AbsPoint]
  | Curve !ShapeKind [AbsPoint]
  | Arc !ShapeKind !Angle !Angle !Size
  | Reflect !Angle !AbstractPicture
  | Clip !Size !Size !AbstractPicture
  deriving (Int -> AbstractPicture -> ShowS
[AbstractPicture] -> ShowS
AbstractPicture -> String
(Int -> AbstractPicture -> ShowS)
-> (AbstractPicture -> String)
-> ([AbstractPicture] -> ShowS)
-> Show AbstractPicture
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AbstractPicture -> ShowS
showsPrec :: Int -> AbstractPicture -> ShowS
$cshow :: AbstractPicture -> String
show :: AbstractPicture -> String
$cshowList :: [AbstractPicture] -> ShowS
showList :: [AbstractPicture] -> ShowS
Show,AbstractPicture -> AbstractPicture -> Bool
(AbstractPicture -> AbstractPicture -> Bool)
-> (AbstractPicture -> AbstractPicture -> Bool)
-> Eq AbstractPicture
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AbstractPicture -> AbstractPicture -> Bool
== :: AbstractPicture -> AbstractPicture -> Bool
$c/= :: AbstractPicture -> AbstractPicture -> Bool
/= :: AbstractPicture -> AbstractPicture -> Bool
Eq,Eq AbstractPicture
Eq AbstractPicture =>
(AbstractPicture -> AbstractPicture -> Ordering)
-> (AbstractPicture -> AbstractPicture -> Bool)
-> (AbstractPicture -> AbstractPicture -> Bool)
-> (AbstractPicture -> AbstractPicture -> Bool)
-> (AbstractPicture -> AbstractPicture -> Bool)
-> (AbstractPicture -> AbstractPicture -> AbstractPicture)
-> (AbstractPicture -> AbstractPicture -> AbstractPicture)
-> Ord AbstractPicture
AbstractPicture -> AbstractPicture -> Bool
AbstractPicture -> AbstractPicture -> Ordering
AbstractPicture -> AbstractPicture -> AbstractPicture
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 :: AbstractPicture -> AbstractPicture -> Ordering
compare :: AbstractPicture -> AbstractPicture -> Ordering
$c< :: AbstractPicture -> AbstractPicture -> Bool
< :: AbstractPicture -> AbstractPicture -> Bool
$c<= :: AbstractPicture -> AbstractPicture -> Bool
<= :: AbstractPicture -> AbstractPicture -> Bool
$c> :: AbstractPicture -> AbstractPicture -> Bool
> :: AbstractPicture -> AbstractPicture -> Bool
$c>= :: AbstractPicture -> AbstractPicture -> Bool
>= :: AbstractPicture -> AbstractPicture -> Bool
$cmax :: AbstractPicture -> AbstractPicture -> AbstractPicture
max :: AbstractPicture -> AbstractPicture -> AbstractPicture
$cmin :: AbstractPicture -> AbstractPicture -> AbstractPicture
min :: AbstractPicture -> AbstractPicture -> AbstractPicture
Ord,Typeable AbstractPicture
Typeable AbstractPicture =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> AbstractPicture -> c AbstractPicture)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c AbstractPicture)
-> (AbstractPicture -> Constr)
-> (AbstractPicture -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c AbstractPicture))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c AbstractPicture))
-> ((forall b. Data b => b -> b)
    -> AbstractPicture -> AbstractPicture)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r)
-> (forall u.
    (forall d. Data d => d -> u) -> AbstractPicture -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> AbstractPicture -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> AbstractPicture -> m AbstractPicture)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> AbstractPicture -> m AbstractPicture)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> AbstractPicture -> m AbstractPicture)
-> Data AbstractPicture
AbstractPicture -> Constr
AbstractPicture -> DataType
(forall b. Data b => b -> b) -> AbstractPicture -> AbstractPicture
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int -> (forall d. Data d => d -> u) -> AbstractPicture -> u
forall u. (forall d. Data d => d -> u) -> AbstractPicture -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c AbstractPicture
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> AbstractPicture -> c AbstractPicture
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c AbstractPicture)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c AbstractPicture)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> AbstractPicture -> c AbstractPicture
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> AbstractPicture -> c AbstractPicture
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c AbstractPicture
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c AbstractPicture
$ctoConstr :: AbstractPicture -> Constr
toConstr :: AbstractPicture -> Constr
$cdataTypeOf :: AbstractPicture -> DataType
dataTypeOf :: AbstractPicture -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c AbstractPicture)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c AbstractPicture)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c AbstractPicture)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c AbstractPicture)
$cgmapT :: (forall b. Data b => b -> b) -> AbstractPicture -> AbstractPicture
gmapT :: (forall b. Data b => b -> b) -> AbstractPicture -> AbstractPicture
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> AbstractPicture -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> AbstractPicture -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> AbstractPicture -> [u]
$cgmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> AbstractPicture -> u
gmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> AbstractPicture -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> AbstractPicture -> m AbstractPicture
Data)


instance Drawable AbstractPicture where

  pictures :: [AbstractPicture] -> AbstractPicture
pictures = [AbstractPicture] -> AbstractPicture
Pictures

  AbstractPicture
p1 & :: AbstractPicture -> AbstractPicture -> AbstractPicture
& AbstractPicture
p2 = [AbstractPicture] -> AbstractPicture
Pictures [AbstractPicture
p1,AbstractPicture
p2]

  blank :: AbstractPicture
blank = AbstractPicture
Blank

  coordinatePlane :: AbstractPicture
coordinatePlane = AbstractPicture
CoordinatePlane
  codeWorldLogo :: AbstractPicture
codeWorldLogo = AbstractPicture
Logo

  circle :: Double -> AbstractPicture
circle = ShapeKind -> Size -> AbstractPicture
Circle (Thickness -> ShapeKind
Hollow Thickness
Normal) (Size -> AbstractPicture)
-> (Double -> Size) -> Double -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Size
toSize

  solidCircle :: Double -> AbstractPicture
solidCircle = ShapeKind -> Size -> AbstractPicture
Circle ShapeKind
Solid (Size -> AbstractPicture)
-> (Double -> Size) -> Double -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Size
toSize

  thickCircle :: Double -> Double -> AbstractPicture
thickCircle Double
t = ShapeKind -> Size -> AbstractPicture
Circle (Thickness -> ShapeKind
Hollow (Thickness -> ShapeKind) -> Thickness -> ShapeKind
forall a b. (a -> b) -> a -> b
$ Double -> Thickness
forall a. (Eq a, Fractional a) => a -> Thickness
thickness Double
t) (Size -> AbstractPicture)
-> (Double -> Size) -> Double -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Size
toSize

  rectangle :: Double -> Double -> AbstractPicture
rectangle Double
l Double
w = ShapeKind -> Size -> Size -> AbstractPicture
Rectangle (Thickness -> ShapeKind
Hollow Thickness
Normal) (Double -> Size
toSize Double
l) (Double -> Size
toSize Double
w)

  solidRectangle :: Double -> Double -> AbstractPicture
solidRectangle Double
l Double
w = ShapeKind -> Size -> Size -> AbstractPicture
Rectangle ShapeKind
Solid (Double -> Size
toSize Double
l) (Double -> Size
toSize Double
w)

  thickRectangle :: Double -> Double -> Double -> AbstractPicture
thickRectangle Double
t Double
l Double
w = ShapeKind -> Size -> Size -> AbstractPicture
Rectangle (Thickness -> ShapeKind
Hollow (Thickness -> ShapeKind) -> Thickness -> ShapeKind
forall a b. (a -> b) -> a -> b
$ Double -> Thickness
forall a. (Eq a, Fractional a) => a -> Thickness
thickness Double
t) (Double -> Size
toSize Double
l) (Double -> Size
toSize Double
w)

  arc :: Double -> Double -> Double -> AbstractPicture
arc Double
a1 Double
a2 Double
r = ShapeKind -> Angle -> Angle -> Size -> AbstractPicture
Arc (Thickness -> ShapeKind
Hollow Thickness
Normal) (Double -> Angle
toAngle Double
a1) (Double -> Angle
toAngle Double
a2) (Double -> Size
toSize Double
r)
  sector :: Double -> Double -> Double -> AbstractPicture
sector Double
a1 Double
a2 Double
r = ShapeKind -> Angle -> Angle -> Size -> AbstractPicture
Arc ShapeKind
Solid (Double -> Angle
toAngle Double
a1) (Double -> Angle
toAngle Double
a2) (Double -> Size
toSize Double
r)
  thickArc :: Double -> Double -> Double -> Double -> AbstractPicture
thickArc Double
t Double
a1 Double
a2 Double
r = ShapeKind -> Angle -> Angle -> Size -> AbstractPicture
Arc (Thickness -> ShapeKind
Hollow (Thickness -> ShapeKind) -> Thickness -> ShapeKind
forall a b. (a -> b) -> a -> b
$ Double -> Thickness
forall a. (Eq a, Fractional a) => a -> Thickness
thickness Double
t) (Double -> Angle
toAngle Double
a1) (Double -> Angle
toAngle Double
a2) (Double -> Size
toSize Double
r)

  curve :: [Point] -> AbstractPicture
curve = ShapeKind -> [AbsPoint] -> AbstractPicture
Curve (Thickness -> ShapeKind
Hollow Thickness
Normal) ([AbsPoint] -> AbstractPicture)
-> ([Point] -> [AbsPoint]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point -> AbsPoint) -> [Point] -> [AbsPoint]
forall a b. (a -> b) -> [a] -> [b]
map Point -> AbsPoint
toAbsPoint
  thickCurve :: Double -> [Point] -> AbstractPicture
thickCurve Double
t = ShapeKind -> [AbsPoint] -> AbstractPicture
Curve (Thickness -> ShapeKind
Hollow (Thickness -> ShapeKind) -> Thickness -> ShapeKind
forall a b. (a -> b) -> a -> b
$ Double -> Thickness
forall a. (Eq a, Fractional a) => a -> Thickness
thickness Double
t) ([AbsPoint] -> AbstractPicture)
-> ([Point] -> [AbsPoint]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point -> AbsPoint) -> [Point] -> [AbsPoint]
forall a b. (a -> b) -> [a] -> [b]
map Point -> AbsPoint
toAbsPoint
  solidClosedCurve :: [Point] -> AbstractPicture
solidClosedCurve = ShapeKind -> [AbsPoint] -> AbstractPicture
Curve ShapeKind
Solid ([AbsPoint] -> AbstractPicture)
-> ([Point] -> [AbsPoint]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point -> AbsPoint) -> [Point] -> [AbsPoint]
forall a b. (a -> b) -> [a] -> [b]
map Point -> AbsPoint
toAbsPoint ([Point] -> [AbsPoint])
-> ([Point] -> [Point]) -> [Point] -> [AbsPoint]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Point] -> [Point]
toOpenShape

  closedCurve :: [Point] -> AbstractPicture
closedCurve        = [Point] -> AbstractPicture
forall a. Drawable a => [Point] -> a
curve ([Point] -> AbstractPicture)
-> ([Point] -> [Point]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Point] -> [Point]
toOpenShape
  thickClosedCurve :: Double -> [Point] -> AbstractPicture
thickClosedCurve Double
t = Double -> [Point] -> AbstractPicture
forall a. Drawable a => Double -> [Point] -> a
thickCurve Double
t ([Point] -> AbstractPicture)
-> ([Point] -> [Point]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Point] -> [Point]
toOpenShape

  polyline :: [Point] -> AbstractPicture
polyline        = ShapeKind -> [AbsPoint] -> AbstractPicture
Polyline (Thickness -> ShapeKind
Hollow Thickness
Normal) ([AbsPoint] -> AbstractPicture)
-> ([Point] -> [AbsPoint]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point -> AbsPoint) -> [Point] -> [AbsPoint]
forall a b. (a -> b) -> [a] -> [b]
map Point -> AbsPoint
toAbsPoint
  thickPolyline :: Double -> [Point] -> AbstractPicture
thickPolyline Double
t = ShapeKind -> [AbsPoint] -> AbstractPicture
Polyline (Thickness -> ShapeKind
Hollow (Thickness -> ShapeKind) -> Thickness -> ShapeKind
forall a b. (a -> b) -> a -> b
$ Double -> Thickness
forall a. (Eq a, Fractional a) => a -> Thickness
thickness Double
t) ([AbsPoint] -> AbstractPicture)
-> ([Point] -> [AbsPoint]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point -> AbsPoint) -> [Point] -> [AbsPoint]
forall a b. (a -> b) -> [a] -> [b]
map Point -> AbsPoint
toAbsPoint
  solidPolygon :: [Point] -> AbstractPicture
solidPolygon    = ShapeKind -> [AbsPoint] -> AbstractPicture
Polyline ShapeKind
Solid ([AbsPoint] -> AbstractPicture)
-> ([Point] -> [AbsPoint]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point -> AbsPoint) -> [Point] -> [AbsPoint]
forall a b. (a -> b) -> [a] -> [b]
map Point -> AbsPoint
toAbsPoint ([Point] -> [AbsPoint])
-> ([Point] -> [Point]) -> [Point] -> [AbsPoint]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Point] -> [Point]
toOpenShape

  polygon :: [Point] -> AbstractPicture
polygon        = [Point] -> AbstractPicture
forall a. Drawable a => [Point] -> a
polyline ([Point] -> AbstractPicture)
-> ([Point] -> [Point]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Point] -> [Point]
toOpenShape
  thickPolygon :: Double -> [Point] -> AbstractPicture
thickPolygon Double
t = Double -> [Point] -> AbstractPicture
forall a. Drawable a => Double -> [Point] -> a
thickPolyline Double
t ([Point] -> AbstractPicture)
-> ([Point] -> [Point]) -> [Point] -> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Point] -> [Point]
toOpenShape

  lettering :: Text -> AbstractPicture
lettering = Text -> AbstractPicture
Lettering

  styledLettering :: TextStyle -> Font -> Text -> AbstractPicture
styledLettering TextStyle
_ Font
_ = Text -> AbstractPicture
Lettering

  translated :: Double -> Double -> AbstractPicture -> AbstractPicture
translated Double
x Double
y = Position -> Position -> AbstractPicture -> AbstractPicture
Translate (Double -> Position
toPosition Double
x) (Double -> Position
toPosition Double
y)

  colored :: Color -> AbstractPicture -> AbstractPicture
colored Color
c = AbsColor -> AbstractPicture -> AbstractPicture
Color (Color -> AbsColor
toAbsColor Color
c)

  dilated :: Double -> AbstractPicture -> AbstractPicture
dilated Double
fac = Double -> Double -> AbstractPicture -> AbstractPicture
forall a. Drawable a => Double -> Double -> a -> a
scaled Double
fac Double
fac

  scaled :: Double -> Double -> AbstractPicture -> AbstractPicture
scaled Double
fac1 Double
fac2 = Factor -> Factor -> AbstractPicture -> AbstractPicture
Scale (Double -> Factor
toFactor Double
fac1) (Double -> Factor
toFactor Double
fac2)

  rotated :: Double -> AbstractPicture -> AbstractPicture
rotated Double
a = Angle -> AbstractPicture -> AbstractPicture
Rotate (Double -> Angle
toAngle Double
a)

  reflected :: Double -> AbstractPicture -> AbstractPicture
reflected Double
a = Angle -> AbstractPicture -> AbstractPicture
Reflect (Double -> Angle
toAngle Double
a)

  -- TODO: clip free shapes?
  clipped :: Double -> Double -> AbstractPicture -> AbstractPicture
clipped Double
x Double
y = Size -> Size -> AbstractPicture -> AbstractPicture
Clip (Double -> Size
toSize Double
x) (Double -> Size
toSize Double
y)


toOpenShape :: [Point] -> [Point]
toOpenShape :: [Point] -> [Point]
toOpenShape [Point]
ps = [Point]
ps [Point] -> [Point] -> [Point]
forall a. [a] -> [a] -> [a]
++ Int -> [Point] -> [Point]
forall a. Int -> [a] -> [a]
take Int
1 [Point]
ps


{-|
True if the first image contains the second image.
This uses fuzzy comparison.
-}
contains :: AbstractPicture -> AbstractPicture -> Bool
AbstractPicture
p contains :: AbstractPicture -> AbstractPicture -> Bool
`contains` (Pictures [AbstractPicture]
ps) = (AbstractPicture -> Bool) -> [AbstractPicture] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (AbstractPicture -> AbstractPicture -> Bool
contains AbstractPicture
p) [AbstractPicture]
ps
(Pictures [AbstractPicture]
ps) `contains` AbstractPicture
p = (AbstractPicture -> Bool) -> [AbstractPicture] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
p) [AbstractPicture]
ps
AbstractPicture
p `contains` AbstractPicture
q = AbstractPicture
p AbstractPicture -> AbstractPicture -> Bool
forall a. Eq a => a -> a -> Bool
== AbstractPicture
q Bool -> Bool -> Bool
|| case AbstractPicture
p of
  Translate Position
x Position
y AbstractPicture
pic -> case AbstractPicture
q of
    Translate Position
x2 Position
y2 AbstractPicture
innerP -> Position
x2 Position -> Position -> Bool
forall a. Eq a => a -> a -> Bool
== Position
x Bool -> Bool -> Bool
&& Position
y Position -> Position -> Bool
forall a. Eq a => a -> a -> Bool
== Position
y2 Bool -> Bool -> Bool
&& AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
innerP
    AbstractPicture
_                      -> AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
q
  Rotate Angle
a AbstractPicture
pic -> case AbstractPicture
q of
    Rotate Angle
a2 AbstractPicture
innerP -> Angle
a2 Angle -> Angle -> Bool
forall a. Eq a => a -> a -> Bool
== Angle
a Bool -> Bool -> Bool
&& AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
innerP
    AbstractPicture
_                -> AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
q
  Reflect Angle
a AbstractPicture
pic -> case AbstractPicture
q of
    Reflect Angle
a2 AbstractPicture
innerP -> Angle
a Angle -> Angle -> Bool
forall a. Eq a => a -> a -> Bool
== Angle
a2 Bool -> Bool -> Bool
&& AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
innerP
    AbstractPicture
_                 -> AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
q
  Scale Factor
f1 Factor
f2 AbstractPicture
pic -> case AbstractPicture
q of
    Scale Factor
g1 Factor
g2 AbstractPicture
innerP -> Factor
f1 Factor -> Factor -> Bool
forall a. Eq a => a -> a -> Bool
== Factor
g1 Bool -> Bool -> Bool
&& Factor
f2 Factor -> Factor -> Bool
forall a. Eq a => a -> a -> Bool
== Factor
g2 Bool -> Bool -> Bool
&& AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
innerP
    AbstractPicture
_                  -> AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
q
  Color AbsColor
c AbstractPicture
pic -> case AbstractPicture
q of
    Color AbsColor
c2 AbstractPicture
innerP -> AbsColor
c AbsColor -> AbsColor -> Bool
forall a. Eq a => a -> a -> Bool
== AbsColor
c2 Bool -> Bool -> Bool
&& AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
innerP
    AbstractPicture
_               -> AbstractPicture
pic AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
q
  AbstractPicture
_ -> Bool
False


{- |
Returns how often a subpicture appears in the image.
-}
count :: AbstractPicture -> AbstractPicture -> Int
count :: AbstractPicture -> AbstractPicture -> Int
count AbstractPicture
thing AbstractPicture
inside = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (AbstractPicture -> Int) -> [AbstractPicture] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map AbstractPicture -> Int
singleCount ([AbstractPicture] -> [Int]) -> [AbstractPicture] -> [Int]
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> [AbstractPicture]
getSubPictures AbstractPicture
thing
  where
    singleCount :: AbstractPicture -> Int
singleCount AbstractPicture
p = [AbstractPicture] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([AbstractPicture] -> Int) -> [AbstractPicture] -> Int
forall a b. (a -> b) -> a -> b
$ (AbstractPicture -> Bool) -> [AbstractPicture] -> [AbstractPicture]
forall a. (a -> Bool) -> [a] -> [a]
filter (AbstractPicture -> AbstractPicture -> Bool
`contains` AbstractPicture
p) ([AbstractPicture] -> [AbstractPicture])
-> [AbstractPicture] -> [AbstractPicture]
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> [AbstractPicture]
getSubPictures AbstractPicture
inside


stripTranslation :: AbstractPicture -> AbstractPicture
stripTranslation :: AbstractPicture -> AbstractPicture
stripTranslation (Translate Position
_ Position
_ AbstractPicture
p) = AbstractPicture
p
stripTranslation (Color AbsColor
c AbstractPicture
p) = AbsColor -> AbstractPicture -> AbstractPicture
Color AbsColor
c (AbstractPicture -> AbstractPicture)
-> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> AbstractPicture
stripTranslation AbstractPicture
p
stripTranslation AbstractPicture
p                 = AbstractPicture
p


{-|
Returns the abstract translation of the image.
Neutral translation if none.
-}
getTranslation :: AbstractPicture -> (Position, Position)
getTranslation :: AbstractPicture -> (Position, Position)
getTranslation (Translate Position
x Position
y AbstractPicture
_)   = (Position
x,Position
y)
getTranslation (Color AbsColor
_ AbstractPicture
p)         = AbstractPicture -> (Position, Position)
getTranslation AbstractPicture
p
getTranslation AbstractPicture
p                   = case AbstractPicture
p of
  (Polyline ShapeKind
_ [AbsPoint]
points) -> [AbsPoint] -> (Position, Position)
absPointsToAbsTranslation [AbsPoint]
points
  (Curve ShapeKind
_ [AbsPoint]
points) -> [AbsPoint] -> (Position, Position)
absPointsToAbsTranslation ([AbsPoint] -> (Position, Position))
-> [AbsPoint] -> (Position, Position)
forall a b. (a -> b) -> a -> b
$ Int -> [AbsPoint] -> [AbsPoint]
forall a. Int -> [a] -> [a]
drop Int
1 [AbsPoint]
points
  AbstractPicture
_ -> (Position
0,Position
0)
  where
    absPointsToAbsTranslation :: [AbsPoint] -> (Position, Position)
absPointsToAbsTranslation =
      (Double -> Position) -> Point -> (Position, Position)
forall a b. (a -> b) -> (a, a) -> (b, b)
both Double -> Position
toPosition (Point -> (Position, Position))
-> ([AbsPoint] -> Point) -> [AbsPoint] -> (Position, Position)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Point], Point) -> Point
forall a b. (a, b) -> b
snd (([Point], Point) -> Point)
-> ([AbsPoint] -> ([Point], Point)) -> [AbsPoint] -> Point
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Point] -> ([Point], Point)
atOriginWithOffset ([Point] -> ([Point], Point))
-> ([AbsPoint] -> [Point]) -> [AbsPoint] -> ([Point], Point)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AbsPoint -> Point) -> [AbsPoint] -> [Point]
forall a b. (a -> b) -> [a] -> [b]
map AbsPoint -> Point
fromAbsPoint


{-|
Returns the actual translation of the image.
(0,0) if none.
-}
getExactTranslation :: AbstractPicture -> (Double, Double)
getExactTranslation :: AbstractPicture -> Point
getExactTranslation = (Position -> Double) -> (Position, Position) -> Point
forall a b. (a -> b) -> (a, a) -> (b, b)
both Position -> Double
fromPosition ((Position, Position) -> Point)
-> (AbstractPicture -> (Position, Position))
-> AbstractPicture
-> Point
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractPicture -> (Position, Position)
getTranslation


couldHaveTranslation :: AbstractPicture -> Bool
couldHaveTranslation :: AbstractPicture -> Bool
couldHaveTranslation Translate {} = Bool
True
couldHaveTranslation Polyline {}  = Bool
True
couldHaveTranslation Curve {}     = Bool
True
couldHaveTranslation (Color AbsColor
_ (Translate {})) = Bool
True
couldHaveTranslation AbstractPicture
_            = Bool
False


{-|
Returns the `AbsColor` of the image.
Nothing if it is one of logo or coordinate plane.
Black if none.
-}
getColor :: AbstractPicture -> Maybe AbsColor
getColor :: AbstractPicture -> Maybe AbsColor
getColor (Color AbsColor
c AbstractPicture
_) = AbsColor -> Maybe AbsColor
forall a. a -> Maybe a
Just AbsColor
c
getColor AbstractPicture
Blank       = Maybe AbsColor
forall a. Maybe a
Nothing
getColor AbstractPicture
Logo        = Maybe AbsColor
forall a. Maybe a
Nothing
getColor AbstractPicture
_           = AbsColor -> Maybe AbsColor
forall a. a -> Maybe a
Just (AbsColor -> Maybe AbsColor) -> AbsColor -> Maybe AbsColor
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> AbsColor
Tone Double
0 Double
0 Double
0


{-|
Returns the abstract scaling factors of the image.
Neutral factors if none.
-}
getScalingFactors :: AbstractPicture -> (Factor,Factor)
getScalingFactors :: AbstractPicture -> (Factor, Factor)
getScalingFactors AbstractPicture
p = (Factor, Factor) -> [(Factor, Factor)] -> (Factor, Factor)
forall a. a -> [a] -> a
headDef (Factor
Same,Factor
Same) [(Factor
f1,Factor
f2) | AbstractPicture -> Bool
isBasic AbstractPicture
p, Scale Factor
f1 Factor
f2 AbstractPicture
_ <- AbstractPicture -> [AbstractPicture]
forall on. Uniplate on => on -> [on]
universe AbstractPicture
p]


{-|
Returns actual scaling factors of the image.
(1,1) if none.
-}
getExactScalingFactors :: AbstractPicture -> (Double,Double)
getExactScalingFactors :: AbstractPicture -> Point
getExactScalingFactors = (Factor -> Double) -> (Factor, Factor) -> Point
forall a b. (a -> b) -> (a, a) -> (b, b)
both Factor -> Double
fromFactor ((Factor, Factor) -> Point)
-> (AbstractPicture -> (Factor, Factor))
-> AbstractPicture
-> Point
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractPicture -> (Factor, Factor)
getScalingFactors


{-|
Returns abstract rotation of the image if it has any.
-}
getRotation :: AbstractPicture -> Maybe Angle
getRotation :: AbstractPicture -> Maybe Angle
getRotation AbstractPicture
p = [Angle] -> Maybe Angle
forall a. [a] -> Maybe a
listToMaybe [Angle
a | AbstractPicture -> Bool
isBasic AbstractPicture
p, Rotate Angle
a AbstractPicture
_ <- AbstractPicture -> [AbstractPicture]
forall on. Uniplate on => on -> [on]
universe AbstractPicture
p]


{-|
Returns actual rotation of the image if it has any.
-}
getExactRotation :: AbstractPicture -> Double
getExactRotation :: AbstractPicture -> Double
getExactRotation = Double -> (Angle -> Double) -> Maybe Angle -> Double
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Double
0 Angle -> Double
fromAngle (Maybe Angle -> Double)
-> (AbstractPicture -> Maybe Angle) -> AbstractPicture -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractPicture -> Maybe Angle
getRotation


{-|
Returns abstract reflection of the image if it has any.
-}
getReflectionAngle :: AbstractPicture -> Maybe Angle
getReflectionAngle :: AbstractPicture -> Maybe Angle
getReflectionAngle AbstractPicture
p = [Angle] -> Maybe Angle
forall a. [a] -> Maybe a
listToMaybe [Angle
a | AbstractPicture -> Bool
isBasic AbstractPicture
p, Reflect Angle
a AbstractPicture
_ <- AbstractPicture -> [AbstractPicture]
forall on. Uniplate on => on -> [on]
universe AbstractPicture
p]


{-|
Returns actual reflection of the image if it has any.
-}
getExactReflectionAngle :: AbstractPicture -> Double
getExactReflectionAngle :: AbstractPicture -> Double
getExactReflectionAngle = Double -> (Angle -> Double) -> Maybe Angle -> Double
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Double
0 Angle -> Double
fromAngle (Maybe Angle -> Double)
-> (AbstractPicture -> Maybe Angle) -> AbstractPicture -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractPicture -> Maybe Angle
getReflectionAngle


{-|
Returns abstract radius of the image if it actually a circle or circle segment.
-}
getCircleRadius :: AbstractPicture -> Maybe Size
getCircleRadius :: AbstractPicture -> Maybe Size
getCircleRadius AbstractPicture
p
  | AbstractPicture -> Bool
isBasic AbstractPicture
p = let elements :: [AbstractPicture]
elements = AbstractPicture -> [AbstractPicture]
forall on. Uniplate on => on -> [on]
universe AbstractPicture
p
    in [Size] -> Maybe Size
forall a. [a] -> Maybe a
listToMaybe ([Size] -> Maybe Size) -> [Size] -> Maybe Size
forall a b. (a -> b) -> a -> b
$
      [Size
s | Circle ShapeKind
_ Size
s  <- [AbstractPicture]
elements] [Size] -> [Size] -> [Size]
forall a. [a] -> [a] -> [a]
++
      [Size
s | Arc ShapeKind
_ Angle
_ Angle
_ Size
s <- [AbstractPicture]
elements]
  | Bool
otherwise = Maybe Size
forall a. Maybe a
Nothing


{-|
Returns actual radius of the image if it actually a circle or circle segment.
-}
getExactCircleRadius :: AbstractPicture -> Maybe Double
getExactCircleRadius :: AbstractPicture -> Maybe Double
getExactCircleRadius = (Size -> Double) -> Maybe Size -> Maybe Double
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Size -> Double
fromSize (Maybe Size -> Maybe Double)
-> (AbstractPicture -> Maybe Size)
-> AbstractPicture
-> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractPicture -> Maybe Size
getCircleRadius


{-|
Returns abstract side lengths of the image if it actually a rectangle.
-}
getRectangleLengths :: AbstractPicture -> Maybe (Size,Size)
getRectangleLengths :: AbstractPicture -> Maybe (Size, Size)
getRectangleLengths AbstractPicture
p = [(Size, Size)] -> Maybe (Size, Size)
forall a. [a] -> Maybe a
listToMaybe [(Size
sx,Size
sy) | AbstractPicture -> Bool
isBasic AbstractPicture
p, Rectangle ShapeKind
_ Size
sx Size
sy <- AbstractPicture -> [AbstractPicture]
forall on. Uniplate on => on -> [on]
universe AbstractPicture
p]


{-|
Returns actual side lengths of the image if it actually a rectangle.
-}
getExactRectangleLengths :: AbstractPicture -> Maybe (Double,Double)
getExactRectangleLengths :: AbstractPicture -> Maybe Point
getExactRectangleLengths = ((Size, Size) -> Point) -> Maybe (Size, Size) -> Maybe Point
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Size -> Double) -> (Size, Size) -> Point
forall a b. (a -> b) -> (a, a) -> (b, b)
both Size -> Double
fromSize) (Maybe (Size, Size) -> Maybe Point)
-> (AbstractPicture -> Maybe (Size, Size))
-> AbstractPicture
-> Maybe Point
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractPicture -> Maybe (Size, Size)
getRectangleLengths


{-|
Returns actual list of points in the image if it is a \"free shape\",
[] otherwise.
-}
getExactPointList :: AbstractPicture -> [Point]
getExactPointList :: AbstractPicture -> [Point]
getExactPointList (Curve ShapeKind
_ [AbsPoint]
ps) = (AbsPoint -> Point) -> [AbsPoint] -> [Point]
forall a b. (a -> b) -> [a] -> [b]
map AbsPoint -> Point
fromAbsPoint [AbsPoint]
ps
getExactPointList (Polyline ShapeKind
_ [AbsPoint]
ps) = (AbsPoint -> Point) -> [AbsPoint] -> [Point]
forall a b. (a -> b) -> [a] -> [b]
map AbsPoint -> Point
fromAbsPoint [AbsPoint]
ps
getExactPointList AbstractPicture
_               = []


-- To access translation before it is abstracted away
getSubPictures :: AbstractPicture -> [AbstractPicture]
getSubPictures :: AbstractPicture -> [AbstractPicture]
getSubPictures (Pictures [AbstractPicture]
xs) = [AbstractPicture]
xs
getSubPictures AbstractPicture
p = [AbstractPicture
p]



isBasic :: AbstractPicture -> Bool
isBasic :: AbstractPicture -> Bool
isBasic (Pictures {}) = Bool
False
isBasic (Clip {}) = Bool
False
isBasic AbstractPicture
_ = Bool
True


{- |
Transform an `AbstractPicture` into a t`CodeWorld.Test.Picture`.
Used to compare normalized sample solution to student submission in plain form.
This only makes sense if there's exactly one way to solve the given task.
-}
toConcretePicture :: AbstractPicture -> P.Picture
toConcretePicture :: AbstractPicture -> Picture
toConcretePicture AbstractPicture
p = case AbstractPicture
p of
  Rectangle ShapeKind
sk Size
sx Size
sy -> Style -> Double -> Double -> Picture
P.AnyRectangle (ShapeKind -> Style
toStyle ShapeKind
sk) (Size -> Double
fromSize Size
sx) (Size -> Double
fromSize Size
sy)
  Circle ShapeKind
sk Size
s -> Style -> Double -> Picture
P.AnyCircle (ShapeKind -> Style
toStyle ShapeKind
sk) (Size -> Double
fromSize Size
s)
  Lettering Text
t -> Text -> Picture
P.Lettering Text
t
  Color AbsColor
c AbstractPicture
q -> Color -> Picture -> Picture
P.Color (AbsColor -> Color
fromAbsColor AbsColor
c) (Picture -> Picture) -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> Picture
toConcretePicture AbstractPicture
q
  Translate Position
x Position
y AbstractPicture
q -> Double -> Double -> Picture -> Picture
P.Translate (Position -> Double
fromPosition Position
x) (Position -> Double
fromPosition Position
y) (Picture -> Picture) -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> Picture
toConcretePicture AbstractPicture
q
  Scale Factor
f1 Factor
f2 AbstractPicture
q -> Double -> Double -> Picture -> Picture
P.Scale (Factor -> Double
fromFactor Factor
f1) (Factor -> Double
fromFactor Factor
f2) (Picture -> Picture) -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> Picture
toConcretePicture AbstractPicture
q
  Rotate Angle
a AbstractPicture
q -> Double -> Picture -> Picture
P.Rotate (Angle -> Double
fromAngle Angle
a) (Picture -> Picture) -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> Picture
toConcretePicture AbstractPicture
q
  Pictures [AbstractPicture]
qs -> [Picture] -> Picture
P.Pictures ([Picture] -> Picture) -> [Picture] -> Picture
forall a b. (a -> b) -> a -> b
$ (AbstractPicture -> Picture) -> [AbstractPicture] -> [Picture]
forall a b. (a -> b) -> [a] -> [b]
map AbstractPicture -> Picture
toConcretePicture [AbstractPicture]
qs
  AbstractPicture
CoordinatePlane -> Picture
P.CoordinatePlane
  AbstractPicture
Logo -> Picture
P.Logo
  AbstractPicture
Blank -> Picture
P.Blank
  Polyline ShapeKind
sk [AbsPoint]
ps -> (Shape -> [Point] -> Picture) -> (Shape, [Point]) -> Picture
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Shape -> [Point] -> Picture
P.AnyPolyline ((Shape, [Point]) -> Picture) -> (Shape, [Point]) -> Picture
forall a b. (a -> b) -> a -> b
$ ShapeKind -> [Point] -> (Shape, [Point])
forall {a}. ShapeKind -> [a] -> (Shape, [a])
toShape ShapeKind
sk ([Point] -> (Shape, [Point])) -> [Point] -> (Shape, [Point])
forall a b. (a -> b) -> a -> b
$ (AbsPoint -> Point) -> [AbsPoint] -> [Point]
forall a b. (a -> b) -> [a] -> [b]
map AbsPoint -> Point
fromAbsPoint [AbsPoint]
ps
  Curve ShapeKind
sk [AbsPoint]
ps -> (Shape -> [Point] -> Picture) -> (Shape, [Point]) -> Picture
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Shape -> [Point] -> Picture
P.AnyCurve ((Shape, [Point]) -> Picture) -> (Shape, [Point]) -> Picture
forall a b. (a -> b) -> a -> b
$ ShapeKind -> [Point] -> (Shape, [Point])
forall {a}. ShapeKind -> [a] -> (Shape, [a])
toShape ShapeKind
sk ([Point] -> (Shape, [Point])) -> [Point] -> (Shape, [Point])
forall a b. (a -> b) -> a -> b
$ (AbsPoint -> Point) -> [AbsPoint] -> [Point]
forall a b. (a -> b) -> [a] -> [b]
map AbsPoint -> Point
fromAbsPoint [AbsPoint]
ps
  Arc ShapeKind
sk Angle
a1 Angle
a2 Size
s -> Style -> Double -> Double -> Double -> Picture
P.AnyArc (ShapeKind -> Style
toStyle ShapeKind
sk) (Angle -> Double
fromAngle Angle
a1) (Angle -> Double
fromAngle Angle
a2) (Size -> Double
fromSize Size
s)
  Reflect Angle
a AbstractPicture
q -> Double -> Picture -> Picture
P.Reflect (Angle -> Double
fromAngle Angle
a) (Picture -> Picture) -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> Picture
toConcretePicture AbstractPicture
q
  Clip Size
sx Size
sy AbstractPicture
q -> Double -> Double -> Picture -> Picture
P.Clip (Size -> Double
fromSize Size
sx) (Size -> Double
fromSize Size
sy) (Picture -> Picture) -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> Picture
toConcretePicture AbstractPicture
q
  where
    toStyle :: ShapeKind -> Style
toStyle (Hollow Thickness
Normal) = Maybe Double -> Style
PT.Outline Maybe Double
forall a. Maybe a
Nothing
    toStyle (Hollow Thickness
Thick) = Maybe Double -> Style
PT.Outline (Maybe Double -> Style) -> Maybe Double -> Style
forall a b. (a -> b) -> a -> b
$ Double -> Maybe Double
forall a. a -> Maybe a
Just Double
1
    toStyle ShapeKind
Solid = Style
PT.Solid

    toShape :: ShapeKind -> [a] -> (Shape, [a])
toShape (Hollow Thickness
Normal) [a]
ps = (Maybe Double -> Shape
PT.Open Maybe Double
forall a. Maybe a
Nothing, [a]
ps)
    toShape (Hollow Thickness
Thick) [a]
ps = (Maybe Double -> Shape
PT.Open (Maybe Double -> Shape) -> Maybe Double -> Shape
forall a b. (a -> b) -> a -> b
$ Double -> Maybe Double
forall a. a -> Maybe a
Just Double
1, [a]
ps)
    toShape ShapeKind
Solid [a]
ps = (Style -> Shape
PT.Closed Style
PT.Solid, [a] -> [a]
forall a. HasCallStack => [a] -> [a]
init [a]
ps)