{-# OPTIONS_GHC -Wno-orphans #-}
--------------------------------------------------------------------------------
-- |
-- Module      :  HGeometry.Polygon.Simple.PossiblyDegenerate
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- A Covnex polygon that may be degenerate, i.e. may also be a line segment or point.
--
--------------------------------------------------------------------------------
module HGeometry.Polygon.Simple.PossiblyDegenerate
  ( PossiblyDegenerateSimplePolygon(..)
  , HalfPlane_x_SimplePolygon_Component
  ) where

import Control.DeepSeq
import Control.Lens
import HGeometry.Ext
import HGeometry.HalfSpace
import HGeometry.Intersection
import HGeometry.LineSegment
import HGeometry.Point
import HGeometry.Point.Either
import HGeometry.Polygon.Simple.Type
import HGeometry.Properties
import Data.Bifoldable1
import HGeometry.Line
import Data.Foldable1
import Data.Bifoldable
import GHC.Generics (Generic)

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

-- | A simple polygon (or a "subtype" thereof) that may be degenerate; i.e. may be a single
-- vertex, or a point.
data PossiblyDegenerateSimplePolygon vertex polygon =
    DegenerateVertex vertex
  | DegenerateEdge (ClosedLineSegment vertex)
  | ActualPolygon polygon
  deriving (Int -> PossiblyDegenerateSimplePolygon vertex polygon -> ShowS
[PossiblyDegenerateSimplePolygon vertex polygon] -> ShowS
PossiblyDegenerateSimplePolygon vertex polygon -> String
(Int -> PossiblyDegenerateSimplePolygon vertex polygon -> ShowS)
-> (PossiblyDegenerateSimplePolygon vertex polygon -> String)
-> ([PossiblyDegenerateSimplePolygon vertex polygon] -> ShowS)
-> Show (PossiblyDegenerateSimplePolygon vertex polygon)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall vertex polygon.
(Show vertex, Show polygon) =>
Int -> PossiblyDegenerateSimplePolygon vertex polygon -> ShowS
forall vertex polygon.
(Show vertex, Show polygon) =>
[PossiblyDegenerateSimplePolygon vertex polygon] -> ShowS
forall vertex polygon.
(Show vertex, Show polygon) =>
PossiblyDegenerateSimplePolygon vertex polygon -> String
$cshowsPrec :: forall vertex polygon.
(Show vertex, Show polygon) =>
Int -> PossiblyDegenerateSimplePolygon vertex polygon -> ShowS
showsPrec :: Int -> PossiblyDegenerateSimplePolygon vertex polygon -> ShowS
$cshow :: forall vertex polygon.
(Show vertex, Show polygon) =>
PossiblyDegenerateSimplePolygon vertex polygon -> String
show :: PossiblyDegenerateSimplePolygon vertex polygon -> String
$cshowList :: forall vertex polygon.
(Show vertex, Show polygon) =>
[PossiblyDegenerateSimplePolygon vertex polygon] -> ShowS
showList :: [PossiblyDegenerateSimplePolygon vertex polygon] -> ShowS
Show,PossiblyDegenerateSimplePolygon vertex polygon
-> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
(PossiblyDegenerateSimplePolygon vertex polygon
 -> PossiblyDegenerateSimplePolygon vertex polygon -> Bool)
-> (PossiblyDegenerateSimplePolygon vertex polygon
    -> PossiblyDegenerateSimplePolygon vertex polygon -> Bool)
-> Eq (PossiblyDegenerateSimplePolygon vertex polygon)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall vertex polygon.
(Eq vertex, Eq polygon) =>
PossiblyDegenerateSimplePolygon vertex polygon
-> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
$c== :: forall vertex polygon.
(Eq vertex, Eq polygon) =>
PossiblyDegenerateSimplePolygon vertex polygon
-> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
== :: PossiblyDegenerateSimplePolygon vertex polygon
-> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
$c/= :: forall vertex polygon.
(Eq vertex, Eq polygon) =>
PossiblyDegenerateSimplePolygon vertex polygon
-> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
/= :: PossiblyDegenerateSimplePolygon vertex polygon
-> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
Eq,(forall a b.
 (a -> b)
 -> PossiblyDegenerateSimplePolygon vertex a
 -> PossiblyDegenerateSimplePolygon vertex b)
-> (forall a b.
    a
    -> PossiblyDegenerateSimplePolygon vertex b
    -> PossiblyDegenerateSimplePolygon vertex a)
-> Functor (PossiblyDegenerateSimplePolygon vertex)
forall a b.
a
-> PossiblyDegenerateSimplePolygon vertex b
-> PossiblyDegenerateSimplePolygon vertex a
forall a b.
(a -> b)
-> PossiblyDegenerateSimplePolygon vertex a
-> PossiblyDegenerateSimplePolygon vertex b
forall vertex a b.
a
-> PossiblyDegenerateSimplePolygon vertex b
-> PossiblyDegenerateSimplePolygon vertex a
forall vertex a b.
(a -> b)
-> PossiblyDegenerateSimplePolygon vertex a
-> PossiblyDegenerateSimplePolygon vertex b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall vertex a b.
(a -> b)
-> PossiblyDegenerateSimplePolygon vertex a
-> PossiblyDegenerateSimplePolygon vertex b
fmap :: forall a b.
(a -> b)
-> PossiblyDegenerateSimplePolygon vertex a
-> PossiblyDegenerateSimplePolygon vertex b
$c<$ :: forall vertex a b.
a
-> PossiblyDegenerateSimplePolygon vertex b
-> PossiblyDegenerateSimplePolygon vertex a
<$ :: forall a b.
a
-> PossiblyDegenerateSimplePolygon vertex b
-> PossiblyDegenerateSimplePolygon vertex a
Functor,(forall x.
 PossiblyDegenerateSimplePolygon vertex polygon
 -> Rep (PossiblyDegenerateSimplePolygon vertex polygon) x)
-> (forall x.
    Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
    -> PossiblyDegenerateSimplePolygon vertex polygon)
-> Generic (PossiblyDegenerateSimplePolygon vertex polygon)
forall x.
Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
-> PossiblyDegenerateSimplePolygon vertex polygon
forall x.
PossiblyDegenerateSimplePolygon vertex polygon
-> Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall vertex polygon x.
Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
-> PossiblyDegenerateSimplePolygon vertex polygon
forall vertex polygon x.
PossiblyDegenerateSimplePolygon vertex polygon
-> Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
$cfrom :: forall vertex polygon x.
PossiblyDegenerateSimplePolygon vertex polygon
-> Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
from :: forall x.
PossiblyDegenerateSimplePolygon vertex polygon
-> Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
$cto :: forall vertex polygon x.
Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
-> PossiblyDegenerateSimplePolygon vertex polygon
to :: forall x.
Rep (PossiblyDegenerateSimplePolygon vertex polygon) x
-> PossiblyDegenerateSimplePolygon vertex polygon
Generic)

instance (NFData vertex, NFData polygon
         ) => NFData (PossiblyDegenerateSimplePolygon vertex polygon)

instance Foldable (PossiblyDegenerateSimplePolygon vertex) where
  foldMap :: forall m a.
Monoid m =>
(a -> m) -> PossiblyDegenerateSimplePolygon vertex a -> m
foldMap a -> m
f = \case
    ActualPolygon a
poly -> a -> m
f a
poly
    PossiblyDegenerateSimplePolygon vertex a
_                  -> m
forall a. Monoid a => a
mempty

instance Bifunctor PossiblyDegenerateSimplePolygon where
  bimap :: forall a b c d.
(a -> b)
-> (c -> d)
-> PossiblyDegenerateSimplePolygon a c
-> PossiblyDegenerateSimplePolygon b d
bimap a -> b
f c -> d
g = \case
    DegenerateVertex a
v -> b -> PossiblyDegenerateSimplePolygon b d
forall vertex polygon.
vertex -> PossiblyDegenerateSimplePolygon vertex polygon
DegenerateVertex (a -> b
f a
v)
    DegenerateEdge ClosedLineSegment a
e   -> ClosedLineSegment b -> PossiblyDegenerateSimplePolygon b d
forall vertex polygon.
ClosedLineSegment vertex
-> PossiblyDegenerateSimplePolygon vertex polygon
DegenerateEdge ((a -> b) -> ClosedLineSegment a -> ClosedLineSegment b
forall a b.
(a -> b)
-> LineSegment (EndPoint 'Closed) a
-> LineSegment (EndPoint 'Closed) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f ClosedLineSegment a
e)
    ActualPolygon c
poly -> d -> PossiblyDegenerateSimplePolygon b d
forall vertex polygon.
polygon -> PossiblyDegenerateSimplePolygon vertex polygon
ActualPolygon (c -> d
g c
poly)


instance Bifoldable1 PossiblyDegenerateSimplePolygon where
  bifoldMap1 :: forall m a b.
Semigroup m =>
(a -> m) -> (b -> m) -> PossiblyDegenerateSimplePolygon a b -> m
bifoldMap1 a -> m
f b -> m
g = \case
    DegenerateVertex a
v -> a -> m
f a
v
    DegenerateEdge ClosedLineSegment a
e   -> (a -> m) -> ClosedLineSegment a -> m
forall m a.
Semigroup m =>
(a -> m) -> LineSegment (EndPoint 'Closed) a -> m
forall (t :: * -> *) m a.
(Foldable1 t, Semigroup m) =>
(a -> m) -> t a -> m
foldMap1 a -> m
f ClosedLineSegment a
e
    ActualPolygon b
poly -> b -> m
g b
poly

instance Bifoldable PossiblyDegenerateSimplePolygon where
  bifoldMap :: forall m a b.
Monoid m =>
(a -> m) -> (b -> m) -> PossiblyDegenerateSimplePolygon a b -> m
bifoldMap = (a -> m) -> (b -> m) -> PossiblyDegenerateSimplePolygon a b -> m
forall m a b.
Semigroup m =>
(a -> m) -> (b -> m) -> PossiblyDegenerateSimplePolygon a b -> m
forall (t :: * -> * -> *) m a b.
(Bifoldable1 t, Semigroup m) =>
(a -> m) -> (b -> m) -> t a b -> m
bifoldMap1

type instance NumType   (PossiblyDegenerateSimplePolygon vertex polygon) = NumType vertex
type instance Dimension (PossiblyDegenerateSimplePolygon vertex polygon) = 2

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

-- | A HalfPlane and a simple polygon intersect in a bunch of components, each of
-- which is a possiblyDegenerate simple polygon.
type instance Intersection (HalfSpaceF line) (SimplePolygonF f point) =
  [HalfPlane_x_SimplePolygon_Component f (NumType point) point]
-- | A single Component of a HalfPlane x SimplePolygon intersection.

type HalfPlane_x_SimplePolygon_Component f r vertex =
  PossiblyDegenerateSimplePolygon vertex (SimplePolygonF f (OriginalOrExtra vertex (Point 2 r)))

-- | If we drag along extra information in the halfplane polygon intersection we lose it
type instance Intersection (HalfSpaceF line :+ extra) (SimplePolygonF f point :+ extra') =
  Intersection (HalfSpaceF line) (SimplePolygonF f point)


--------------------------------------------------------------------------------
-- * Intersecting lines and possibly degenerate polygons

instance ( Point_ vertex 2 r, Num r, Ord r
         , LinePV 2 r `HasIntersectionWith` polygon
         ) => LinePV 2 r
                `HasIntersectionWith` PossiblyDegenerateSimplePolygon vertex polygon where
  LinePV 2 r
line intersects :: LinePV 2 r
-> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
`intersects` PossiblyDegenerateSimplePolygon vertex polygon
region = case PossiblyDegenerateSimplePolygon vertex polygon
region of
    DegenerateVertex vertex
v -> (vertex
vvertex -> Getting (Point 2 r) vertex (Point 2 r) -> Point 2 r
forall s a. s -> Getting a s a -> a
^.Getting (Point 2 r) vertex (Point 2 r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' vertex (Point 2 r)
asPoint) Point 2 r -> LinePV 2 r -> Bool
forall line (d :: Nat) point r.
(HasOnLine line d, Point_ point d r, Num r, Eq r, r ~ NumType line,
 d ~ Dimension line) =>
point -> line -> Bool
forall point r.
(Point_ point 2 r, Num r, Eq r, r ~ NumType (LinePV 2 r),
 2 ~ Dimension (LinePV 2 r)) =>
point -> LinePV 2 r -> Bool
`onLine`     LinePV 2 r
line
    DegenerateEdge ClosedLineSegment vertex
e   -> LinePV 2 r
line         LinePV 2 r -> LineSegment (EndPoint 'Closed) (Point 2 r) -> Bool
forall g h. HasIntersectionWith g h => g -> h -> Bool
`intersects` (Getting (Point 2 r) vertex (Point 2 r) -> vertex -> Point 2 r
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Point 2 r) vertex (Point 2 r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' vertex (Point 2 r)
asPoint (vertex -> Point 2 r)
-> ClosedLineSegment vertex
-> LineSegment (EndPoint 'Closed) (Point 2 r)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ClosedLineSegment vertex
e)
    ActualPolygon polygon
poly -> LinePV 2 r
line         LinePV 2 r -> polygon -> Bool
forall g h. HasIntersectionWith g h => g -> h -> Bool
`intersects` polygon
poly


instance ( Point_ vertex 2 r, Num r, Ord r
         , Point 2 r `HasIntersectionWith` polygon
         ) => Point 2 r
                `HasIntersectionWith` PossiblyDegenerateSimplePolygon vertex polygon where
  Point 2 r
q intersects :: Point 2 r -> PossiblyDegenerateSimplePolygon vertex polygon -> Bool
`intersects` PossiblyDegenerateSimplePolygon vertex polygon
region = case PossiblyDegenerateSimplePolygon vertex polygon
region of
    DegenerateVertex vertex
v -> Point 2 r
q Point 2 r -> Point 2 r -> Bool
forall a. Eq a => a -> a -> Bool
== vertex
vvertex -> Getting (Point 2 r) vertex (Point 2 r) -> Point 2 r
forall s a. s -> Getting a s a -> a
^.Getting (Point 2 r) vertex (Point 2 r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' vertex (Point 2 r)
asPoint
    DegenerateEdge ClosedLineSegment vertex
e   -> Point 2 r
q Point 2 r -> LineSegment (EndPoint 'Closed) (Point 2 r) -> Bool
forall g h. HasIntersectionWith g h => g -> h -> Bool
`intersects` (Getting (Point 2 r) vertex (Point 2 r) -> vertex -> Point 2 r
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Point 2 r) vertex (Point 2 r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' vertex (Point 2 r)
asPoint (vertex -> Point 2 r)
-> ClosedLineSegment vertex
-> LineSegment (EndPoint 'Closed) (Point 2 r)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ClosedLineSegment vertex
e)
    ActualPolygon polygon
poly -> Point 2 r
q Point 2 r -> polygon -> Bool
forall g h. HasIntersectionWith g h => g -> h -> Bool
`intersects` polygon
poly