--------------------------------------------------------------------------------
-- |
-- Module      :  HGeometry.Polygon.Instances
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- Arbitrary instances for the polygon types in hgeometry
--
--------------------------------------------------------------------------------
module HGeometry.Polygon.Instances
  ( allSimplePolygons
  , shrinkPolygon
  -- , runConvert
  ) where

import           Control.Lens hiding (elements)
-- import           Control.Monad.State
import           Data.Aeson (eitherDecodeFileStrict)
import           Data.List.NonEmpty (NonEmpty(..))
import           Data.Maybe (maybeToList)
import           HGeometry.Kernel
import           HGeometry.Number.Real.Rational
import           HGeometry.Number.Real.Interval
import           HGeometry.Polygon.Class
-- import           HGeometry.Polygon.Monotone
import           HGeometry.Polygon.Simple
import           Paths_hgeometry_polygon
import           System.IO.Unsafe
-- import           System.Random.Stateful
import           Test.QuickCheck hiding (vector)
import           Test.QuickCheck.Instances ()

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

allSimplePolygons :: [SimplePolygon (Point 2 Double)]
allSimplePolygons :: [SimplePolygon (Point 2 Double)]
allSimplePolygons = (Double -> Double) -> [SimplePolygon (Point 2 Double)]
forall r.
(Ord r, Fractional r) =>
(Double -> r) -> [SimplePolygon (Point 2 r)]
allSimplePolygonsWith Double -> Double
forall a. a -> a
id

allSimplePolygons' :: [SimplePolygon (Point 2 Rational)]
allSimplePolygons' :: [SimplePolygon (Point 2 Rational)]
allSimplePolygons' = (Double -> Rational) -> [SimplePolygon (Point 2 Rational)]
forall r.
(Ord r, Fractional r) =>
(Double -> r) -> [SimplePolygon (Point 2 r)]
allSimplePolygonsWith Double -> Rational
forall a b. (Real a, Fractional b) => a -> b
realToFrac
  -- note: don't use map (realToFrac <$>) allSimplePolygons since that may create
  -- self-intersecting polygons

{-# NOINLINE allSimplePolygonsWith #-}
allSimplePolygonsWith   :: forall r.
                            (Ord r, Fractional r) => (Double -> r) -> [SimplePolygon (Point 2 r)]
allSimplePolygonsWith :: forall r.
(Ord r, Fractional r) =>
(Double -> r) -> [SimplePolygon (Point 2 r)]
allSimplePolygonsWith Double -> r
f = IO [SimplePolygon (Point 2 r)] -> [SimplePolygon (Point 2 r)]
forall a. IO a -> a
unsafePerformIO (IO [SimplePolygon (Point 2 r)] -> [SimplePolygon (Point 2 r)])
-> IO [SimplePolygon (Point 2 r)] -> [SimplePolygon (Point 2 r)]
forall a b. (a -> b) -> a -> b
$ do
  fp <- FilePath -> IO FilePath
getDataFileName FilePath
"polygons.simple.json"
  eitherDecodeFileStrict fp >>= \case
    Left FilePath
msg  -> FilePath -> IO [SimplePolygon (Point 2 r)]
forall a. HasCallStack => FilePath -> a
error FilePath
msg
    Right [SimplePolygon (Point 2 Double)]
pgs -> [SimplePolygon (Point 2 r)] -> IO [SimplePolygon (Point 2 r)]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [ SimplePolygon (Point 2 Double)
pgSimplePolygon (Point 2 Double)
-> (SimplePolygon (Point 2 Double) -> SimplePolygon (Point 2 r))
-> SimplePolygon (Point 2 r)
forall a b. a -> (a -> b) -> b
&(Point 2 Double -> Identity (Point 2 r))
-> SimplePolygon (Point 2 Double)
-> Identity (SimplePolygon (Point 2 r))
forall (d :: Nat) r r'.
(Point_ (Point 2 Double) d r, Point_ (Point 2 r) d r',
 NumType (SimplePolygon (Point 2 Double)) ~ r,
 NumType (SimplePolygon (Point 2 r)) ~ r',
 Dimension (SimplePolygon (Point 2 Double)) ~ d,
 Dimension (SimplePolygon (Point 2 r)) ~ d) =>
Traversal1
  (SimplePolygon (Point 2 Double))
  (SimplePolygon (Point 2 r))
  (Point 2 Double)
  (Point 2 r)
forall s t point point' (d :: Nat) r r'.
(HasPoints s t point point', Point_ point d r, Point_ point' d r',
 NumType s ~ r, NumType t ~ r', Dimension s ~ d, Dimension t ~ d) =>
Traversal1 s t point point'
Traversal1
  (SimplePolygon (Point 2 Double))
  (SimplePolygon (Point 2 r))
  (Point 2 Double)
  (Point 2 r)
allPoints ((Point 2 Double -> Identity (Point 2 r))
 -> SimplePolygon (Point 2 Double)
 -> Identity (SimplePolygon (Point 2 r)))
-> (Point 2 Double -> Point 2 r)
-> SimplePolygon (Point 2 Double)
-> SimplePolygon (Point 2 r)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ \Point 2 Double
p -> Point 2 Double
pPoint 2 Double -> (Point 2 Double -> Point 2 r) -> Point 2 r
forall a b. a -> (a -> b) -> b
&(Double -> Identity r) -> Point 2 Double -> Identity (Point 2 r)
(NumType (Point 2 Double) -> Identity (NumType (Point 2 r)))
-> Point 2 Double -> Identity (Point 2 r)
forall point point'.
HasCoordinates point point' =>
IndexedTraversal1 Int point point' (NumType point) (NumType point')
IndexedTraversal1
  Int
  (Point 2 Double)
  (Point 2 r)
  (NumType (Point 2 Double))
  (NumType (Point 2 r))
coordinates ((Double -> Identity r) -> Point 2 Double -> Identity (Point 2 r))
-> (Double -> r) -> Point 2 Double -> Point 2 r
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Double -> r
f
                      | (SimplePolygon (Point 2 Double)
pg :: SimplePolygon (Point 2 Double)) <- [SimplePolygon (Point 2 Double)]
pgs
                      ]

-- runConvert :: IO ()
-- runConvert = do
--   fp <- getDataFileName "polygons.simple.json"
--   eitherDecodeFileStrict fp >>= \case
--     Left msg  -> error msg
--     Right pgs -> encodeFile "polygons.simple.out" $
--                    [ (pg  :: SimplePolygon (Point 2 Double))
--                    | (pg' :: SimplePolygon (Point 2 Double)) <- pgs
--                    , Just pg <- [fromPoints $ toNonEmptyOf outerBoundary pg']
--                    ]

      -- pure [ pg&allPoints %~ \p -> p&coordinates %~ f
      --                 | (pg :: SimplePolygon (Point 2 Double)) <- pgs
      --                 ]




-- tojson = encodeFile "out.json" $ allSimplePolygons


{-

allMultiPolygons :: [MultiPolygon () Double]
allMultiPolygons = allMultiPolygonsWith id

allMultiPolygons' :: [MultiPolygon () Rational]
allMultiPolygons' = allMultiPolygonsWith realToFrac

{-# NOINLINE allMultiPolygonsWith #-}
allMultiPolygonsWith   :: (Ord r, Fractional r) => (Double -> r) -> [MultiPolygon () r]
allMultiPolygonsWith f = unsafePerformIO $ do
  inp <- BS.readFile =<< getDataFileName "polygons.multi"
  case decode inp of
    Left msg -> error msg
    Right pts -> pure $
      [ MultiPolygon (toSimple boundary) (map toSimple holes)
      | (boundary:holes) <- pts
      ]
  where
    toSimple lst = simpleFromPoints [ ext (f <$> Point2 x y) | (x,y) <- lst ]

-}

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


instance Arbitrary (SimplePolygon (Point 2 Rational)) where
  arbitrary :: Gen (SimplePolygon (Point 2 Rational))
arbitrary = do
    p <- [SimplePolygon (Point 2 Rational)]
-> Gen (SimplePolygon (Point 2 Rational))
forall a. HasCallStack => [a] -> Gen a
elements [SimplePolygon (Point 2 Rational)]
allSimplePolygons'
    n <- chooseInt (0, numVertices p-1)
    pure $ rotateLeft n p -- rotates the indices of the polygon so
      -- that we get a somewhat random starting coordinate as well.
  shrink :: SimplePolygon (Point 2 Rational)
-> [SimplePolygon (Point 2 Rational)]
shrink = SimplePolygon (Point 2 Rational)
-> [SimplePolygon (Point 2 Rational)]
forall r.
(Ord r, Fractional r, Real r) =>
SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
shrinkPolygon


instance Arbitrary (SimplePolygon (Point 2 Double)) where
  arbitrary :: Gen (SimplePolygon (Point 2 Double))
arbitrary = do
    p <- [SimplePolygon (Point 2 Double)]
-> Gen (SimplePolygon (Point 2 Double))
forall a. HasCallStack => [a] -> Gen a
elements [SimplePolygon (Point 2 Double)]
allSimplePolygons
    n <- chooseInt (0, numVertices p-1)
    pure $ rotateLeft n p
  -- shrink p
  --   | isTriangle p = simplifyP p
  --   | otherwise = cutEars p ++ simplifyP p


instance Arbitrary (SimplePolygon (Point 2 (IntervalReal (RealNumber (p::Nat))))) where
  arbitrary :: Gen (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
arbitrary = ASetter
  (SimplePolygon (Point 2 (RealNumber p)))
  (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
  (RealNumber p)
  (IntervalReal (RealNumber p))
-> (RealNumber p -> IntervalReal (RealNumber p))
-> SimplePolygon (Point 2 (RealNumber p))
-> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((Vertex (SimplePolygon (Point 2 (RealNumber p)))
 -> Identity
      (Vertex (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))))
-> SimplePolygon (Point 2 (RealNumber p))
-> Identity (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
(Point 2 (RealNumber p)
 -> Identity (Point 2 (IntervalReal (RealNumber p))))
-> SimplePolygon (Point 2 (RealNumber p))
-> Identity (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 (RealNumber p))))
  (SimplePolygon (Point 2 (RealNumber p)))
  (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
  (Vertex (SimplePolygon (Point 2 (RealNumber p))))
  (Vertex (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))))
vertices((Point 2 (RealNumber p)
  -> Identity (Point 2 (IntervalReal (RealNumber p))))
 -> SimplePolygon (Point 2 (RealNumber p))
 -> Identity
      (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))))
-> ((RealNumber p -> Identity (IntervalReal (RealNumber p)))
    -> Point 2 (RealNumber p)
    -> Identity (Point 2 (IntervalReal (RealNumber p))))
-> ASetter
     (SimplePolygon (Point 2 (RealNumber p)))
     (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
     (RealNumber p)
     (IntervalReal (RealNumber p))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(RealNumber p -> Identity (IntervalReal (RealNumber p)))
-> Point 2 (RealNumber p)
-> Identity (Point 2 (IntervalReal (RealNumber p)))
(NumType (Point 2 (RealNumber p))
 -> Identity (NumType (Point 2 (IntervalReal (RealNumber p)))))
-> Point 2 (RealNumber p)
-> Identity (Point 2 (IntervalReal (RealNumber p)))
forall point point'.
HasCoordinates point point' =>
IndexedTraversal1 Int point point' (NumType point) (NumType point')
IndexedTraversal1
  Int
  (Point 2 (RealNumber p))
  (Point 2 (IntervalReal (RealNumber p)))
  (NumType (Point 2 (RealNumber p)))
  (NumType (Point 2 (IntervalReal (RealNumber p))))
coordinates) RealNumber p -> IntervalReal (RealNumber p)
forall a b. (Real a, Fractional b) => a -> b
realToFrac
           (SimplePolygon (Point 2 (RealNumber p))
 -> SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
-> Gen (SimplePolygon (Point 2 (RealNumber p)))
-> Gen (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Gen (SimplePolygon (Point 2 (RealNumber p)))
forall a. Arbitrary a => Gen a
arbitrary :: Gen (SimplePolygon (Point 2 (RealNumber p))))
  shrink :: SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> [SimplePolygon (Point 2 (IntervalReal (RealNumber p)))]
shrink = (SimplePolygon (Point 2 (RealNumber p))
 -> SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
-> [SimplePolygon (Point 2 (RealNumber p))]
-> [SimplePolygon (Point 2 (IntervalReal (RealNumber p)))]
forall a b. (a -> b) -> [a] -> [b]
map (ASetter
  (SimplePolygon (Point 2 (RealNumber p)))
  (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
  (RealNumber p)
  (IntervalReal (RealNumber p))
-> (RealNumber p -> IntervalReal (RealNumber p))
-> SimplePolygon (Point 2 (RealNumber p))
-> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((Vertex (SimplePolygon (Point 2 (RealNumber p)))
 -> Identity
      (Vertex (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))))
-> SimplePolygon (Point 2 (RealNumber p))
-> Identity (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
(Point 2 (RealNumber p)
 -> Identity (Point 2 (IntervalReal (RealNumber p))))
-> SimplePolygon (Point 2 (RealNumber p))
-> Identity (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 (RealNumber p))))
  (SimplePolygon (Point 2 (RealNumber p)))
  (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
  (Vertex (SimplePolygon (Point 2 (RealNumber p))))
  (Vertex (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))))
vertices((Point 2 (RealNumber p)
  -> Identity (Point 2 (IntervalReal (RealNumber p))))
 -> SimplePolygon (Point 2 (RealNumber p))
 -> Identity
      (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))))
-> ((RealNumber p -> Identity (IntervalReal (RealNumber p)))
    -> Point 2 (RealNumber p)
    -> Identity (Point 2 (IntervalReal (RealNumber p))))
-> ASetter
     (SimplePolygon (Point 2 (RealNumber p)))
     (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
     (RealNumber p)
     (IntervalReal (RealNumber p))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(RealNumber p -> Identity (IntervalReal (RealNumber p)))
-> Point 2 (RealNumber p)
-> Identity (Point 2 (IntervalReal (RealNumber p)))
(NumType (Point 2 (RealNumber p))
 -> Identity (NumType (Point 2 (IntervalReal (RealNumber p)))))
-> Point 2 (RealNumber p)
-> Identity (Point 2 (IntervalReal (RealNumber p)))
forall point point'.
HasCoordinates point point' =>
IndexedTraversal1 Int point point' (NumType point) (NumType point')
IndexedTraversal1
  Int
  (Point 2 (RealNumber p))
  (Point 2 (IntervalReal (RealNumber p)))
  (NumType (Point 2 (RealNumber p)))
  (NumType (Point 2 (IntervalReal (RealNumber p))))
coordinates) RealNumber p -> IntervalReal (RealNumber p)
forall a b. (Real a, Fractional b) => a -> b
realToFrac) ([SimplePolygon (Point 2 (RealNumber p))]
 -> [SimplePolygon (Point 2 (IntervalReal (RealNumber p)))])
-> (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
    -> [SimplePolygon (Point 2 (RealNumber p))])
-> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> [SimplePolygon (Point 2 (IntervalReal (RealNumber p)))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimplePolygon (Point 2 (RealNumber p))
-> [SimplePolygon (Point 2 (RealNumber p))]
forall a. Arbitrary a => a -> [a]
shrink (SimplePolygon (Point 2 (RealNumber p))
 -> [SimplePolygon (Point 2 (RealNumber p))])
-> (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
    -> SimplePolygon (Point 2 (RealNumber p)))
-> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> [SimplePolygon (Point 2 (RealNumber p))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> SimplePolygon (Point 2 (RealNumber p))
trunc
    where
      trunc :: SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
            -> SimplePolygon (Point 2               (RealNumber p))
      trunc :: SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> SimplePolygon (Point 2 (RealNumber p))
trunc = ASetter
  (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
  (SimplePolygon (Point 2 (RealNumber p)))
  (IntervalReal (RealNumber p))
  (RealNumber p)
-> (IntervalReal (RealNumber p) -> RealNumber p)
-> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> SimplePolygon (Point 2 (RealNumber p))
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((Vertex (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
 -> Identity (Vertex (SimplePolygon (Point 2 (RealNumber p)))))
-> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> Identity (SimplePolygon (Point 2 (RealNumber p)))
(Point 2 (IntervalReal (RealNumber p))
 -> Identity (Point 2 (RealNumber p)))
-> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
-> Identity (SimplePolygon (Point 2 (RealNumber p)))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))))
  (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
  (SimplePolygon (Point 2 (RealNumber p)))
  (Vertex (SimplePolygon (Point 2 (IntervalReal (RealNumber p)))))
  (Vertex (SimplePolygon (Point 2 (RealNumber p))))
vertices((Point 2 (IntervalReal (RealNumber p))
  -> Identity (Point 2 (RealNumber p)))
 -> SimplePolygon (Point 2 (IntervalReal (RealNumber p)))
 -> Identity (SimplePolygon (Point 2 (RealNumber p))))
-> ((IntervalReal (RealNumber p) -> Identity (RealNumber p))
    -> Point 2 (IntervalReal (RealNumber p))
    -> Identity (Point 2 (RealNumber p)))
-> ASetter
     (SimplePolygon (Point 2 (IntervalReal (RealNumber p))))
     (SimplePolygon (Point 2 (RealNumber p)))
     (IntervalReal (RealNumber p))
     (RealNumber p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(IntervalReal (RealNumber p) -> Identity (RealNumber p))
-> Point 2 (IntervalReal (RealNumber p))
-> Identity (Point 2 (RealNumber p))
(NumType (Point 2 (IntervalReal (RealNumber p)))
 -> Identity (NumType (Point 2 (RealNumber p))))
-> Point 2 (IntervalReal (RealNumber p))
-> Identity (Point 2 (RealNumber p))
forall point point'.
HasCoordinates point point' =>
IndexedTraversal1 Int point point' (NumType point) (NumType point')
IndexedTraversal1
  Int
  (Point 2 (IntervalReal (RealNumber p)))
  (Point 2 (RealNumber p))
  (NumType (Point 2 (IntervalReal (RealNumber p))))
  (NumType (Point 2 (RealNumber p)))
coordinates) IntervalReal (RealNumber p) -> RealNumber p
forall a b. (Real a, Fractional b) => a -> b
realToFrac

instance Arbitrary (SimplePolygon (Point 2 (RealNumber (p::Nat)))) where
  arbitrary :: Gen (SimplePolygon (Point 2 (RealNumber p)))
arbitrary = ASetter
  (SimplePolygon (Point 2 Rational))
  (SimplePolygon (Point 2 (RealNumber p)))
  Rational
  (RealNumber p)
-> (Rational -> RealNumber p)
-> SimplePolygon (Point 2 Rational)
-> SimplePolygon (Point 2 (RealNumber p))
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((Vertex (SimplePolygon (Point 2 Rational))
 -> Identity (Vertex (SimplePolygon (Point 2 (RealNumber p)))))
-> SimplePolygon (Point 2 Rational)
-> Identity (SimplePolygon (Point 2 (RealNumber p)))
(Point 2 Rational -> Identity (Point 2 (RealNumber p)))
-> SimplePolygon (Point 2 Rational)
-> Identity (SimplePolygon (Point 2 (RealNumber p)))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 Rational)))
  (SimplePolygon (Point 2 Rational))
  (SimplePolygon (Point 2 (RealNumber p)))
  (Vertex (SimplePolygon (Point 2 Rational)))
  (Vertex (SimplePolygon (Point 2 (RealNumber p))))
vertices((Point 2 Rational -> Identity (Point 2 (RealNumber p)))
 -> SimplePolygon (Point 2 Rational)
 -> Identity (SimplePolygon (Point 2 (RealNumber p))))
-> ((Rational -> Identity (RealNumber p))
    -> Point 2 Rational -> Identity (Point 2 (RealNumber p)))
-> ASetter
     (SimplePolygon (Point 2 Rational))
     (SimplePolygon (Point 2 (RealNumber p)))
     Rational
     (RealNumber p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Rational -> Identity (RealNumber p))
-> Point 2 Rational -> Identity (Point 2 (RealNumber p))
(NumType (Point 2 Rational)
 -> Identity (NumType (Point 2 (RealNumber p))))
-> Point 2 Rational -> Identity (Point 2 (RealNumber p))
forall point point'.
HasCoordinates point point' =>
IndexedTraversal1 Int point point' (NumType point) (NumType point')
IndexedTraversal1
  Int
  (Point 2 Rational)
  (Point 2 (RealNumber p))
  (NumType (Point 2 Rational))
  (NumType (Point 2 (RealNumber p)))
coordinates) Rational -> RealNumber p
forall a b. (Real a, Fractional b) => a -> b
realToFrac
           (SimplePolygon (Point 2 Rational)
 -> SimplePolygon (Point 2 (RealNumber p)))
-> Gen (SimplePolygon (Point 2 Rational))
-> Gen (SimplePolygon (Point 2 (RealNumber p)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Gen (SimplePolygon (Point 2 Rational))
forall a. Arbitrary a => Gen a
arbitrary :: Gen (SimplePolygon (Point 2 Rational)))
  shrink :: SimplePolygon (Point 2 (RealNumber p))
-> [SimplePolygon (Point 2 (RealNumber p))]
shrink = (SimplePolygon (Point 2 Rational)
 -> SimplePolygon (Point 2 (RealNumber p)))
-> [SimplePolygon (Point 2 Rational)]
-> [SimplePolygon (Point 2 (RealNumber p))]
forall a b. (a -> b) -> [a] -> [b]
map (ASetter
  (SimplePolygon (Point 2 Rational))
  (SimplePolygon (Point 2 (RealNumber p)))
  Rational
  (RealNumber p)
-> (Rational -> RealNumber p)
-> SimplePolygon (Point 2 Rational)
-> SimplePolygon (Point 2 (RealNumber p))
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((Vertex (SimplePolygon (Point 2 Rational))
 -> Identity (Vertex (SimplePolygon (Point 2 (RealNumber p)))))
-> SimplePolygon (Point 2 Rational)
-> Identity (SimplePolygon (Point 2 (RealNumber p)))
(Point 2 Rational -> Identity (Point 2 (RealNumber p)))
-> SimplePolygon (Point 2 Rational)
-> Identity (SimplePolygon (Point 2 (RealNumber p)))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 Rational)))
  (SimplePolygon (Point 2 Rational))
  (SimplePolygon (Point 2 (RealNumber p)))
  (Vertex (SimplePolygon (Point 2 Rational)))
  (Vertex (SimplePolygon (Point 2 (RealNumber p))))
vertices((Point 2 Rational -> Identity (Point 2 (RealNumber p)))
 -> SimplePolygon (Point 2 Rational)
 -> Identity (SimplePolygon (Point 2 (RealNumber p))))
-> ((Rational -> Identity (RealNumber p))
    -> Point 2 Rational -> Identity (Point 2 (RealNumber p)))
-> ASetter
     (SimplePolygon (Point 2 Rational))
     (SimplePolygon (Point 2 (RealNumber p)))
     Rational
     (RealNumber p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Rational -> Identity (RealNumber p))
-> Point 2 Rational -> Identity (Point 2 (RealNumber p))
(NumType (Point 2 Rational)
 -> Identity (NumType (Point 2 (RealNumber p))))
-> Point 2 Rational -> Identity (Point 2 (RealNumber p))
forall point point'.
HasCoordinates point point' =>
IndexedTraversal1 Int point point' (NumType point) (NumType point')
IndexedTraversal1
  Int
  (Point 2 Rational)
  (Point 2 (RealNumber p))
  (NumType (Point 2 Rational))
  (NumType (Point 2 (RealNumber p)))
coordinates) Rational -> RealNumber p
forall a b. (Real a, Fractional b) => a -> b
realToFrac) ([SimplePolygon (Point 2 Rational)]
 -> [SimplePolygon (Point 2 (RealNumber p))])
-> (SimplePolygon (Point 2 (RealNumber p))
    -> [SimplePolygon (Point 2 Rational)])
-> SimplePolygon (Point 2 (RealNumber p))
-> [SimplePolygon (Point 2 (RealNumber p))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimplePolygon (Point 2 Rational)
-> [SimplePolygon (Point 2 Rational)]
forall a. Arbitrary a => a -> [a]
shrink (SimplePolygon (Point 2 Rational)
 -> [SimplePolygon (Point 2 Rational)])
-> (SimplePolygon (Point 2 (RealNumber p))
    -> SimplePolygon (Point 2 Rational))
-> SimplePolygon (Point 2 (RealNumber p))
-> [SimplePolygon (Point 2 Rational)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimplePolygon (Point 2 (RealNumber p))
-> SimplePolygon (Point 2 Rational)
trunc
    where
      trunc :: SimplePolygon (Point 2 (RealNumber (p::Nat))) -> SimplePolygon (Point 2 Rational)
      trunc :: SimplePolygon (Point 2 (RealNumber p))
-> SimplePolygon (Point 2 Rational)
trunc = ASetter
  (SimplePolygon (Point 2 (RealNumber p)))
  (SimplePolygon (Point 2 Rational))
  (RealNumber p)
  Rational
-> (RealNumber p -> Rational)
-> SimplePolygon (Point 2 (RealNumber p))
-> SimplePolygon (Point 2 Rational)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((Vertex (SimplePolygon (Point 2 (RealNumber p)))
 -> Identity (Vertex (SimplePolygon (Point 2 Rational))))
-> SimplePolygon (Point 2 (RealNumber p))
-> Identity (SimplePolygon (Point 2 Rational))
(Point 2 (RealNumber p) -> Identity (Point 2 Rational))
-> SimplePolygon (Point 2 (RealNumber p))
-> Identity (SimplePolygon (Point 2 Rational))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 (RealNumber p))))
  (SimplePolygon (Point 2 (RealNumber p)))
  (SimplePolygon (Point 2 Rational))
  (Vertex (SimplePolygon (Point 2 (RealNumber p))))
  (Vertex (SimplePolygon (Point 2 Rational)))
vertices((Point 2 (RealNumber p) -> Identity (Point 2 Rational))
 -> SimplePolygon (Point 2 (RealNumber p))
 -> Identity (SimplePolygon (Point 2 Rational)))
-> ((RealNumber p -> Identity Rational)
    -> Point 2 (RealNumber p) -> Identity (Point 2 Rational))
-> ASetter
     (SimplePolygon (Point 2 (RealNumber p)))
     (SimplePolygon (Point 2 Rational))
     (RealNumber p)
     Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(RealNumber p -> Identity Rational)
-> Point 2 (RealNumber p) -> Identity (Point 2 Rational)
(NumType (Point 2 (RealNumber p))
 -> Identity (NumType (Point 2 Rational)))
-> Point 2 (RealNumber p) -> Identity (Point 2 Rational)
forall point point'.
HasCoordinates point point' =>
IndexedTraversal1 Int point point' (NumType point) (NumType point')
IndexedTraversal1
  Int
  (Point 2 (RealNumber p))
  (Point 2 Rational)
  (NumType (Point 2 (RealNumber p)))
  (NumType (Point 2 Rational))
coordinates) RealNumber p -> Rational
forall a b. (Real a, Fractional b) => a -> b
realToFrac

-- instance Arbitrary (MultiPolygon () Rational) where
--   arbitrary = elements allMultiPolygons'




-- instance (Uniform r, Ord r, Num r) => Arbitrary (MonotonePolygon (Point 2 r)) where
--   arbitrary = do
--                 n <- max 3    <$> getSize
--                 g <- mkStdGen <$> arbitrary
--                 let (v, g') = runState randomNonZeroVector g
--                 pure $ evalState (randomMonotoneDirected n v) g'


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

-- | Shifts the indices of the polygon to the left by n.
rotateLeft      :: SimplePolygon_ simplePolygon point r => Int -> simplePolygon -> simplePolygon
rotateLeft :: forall simplePolygon point r.
SimplePolygon_ simplePolygon point r =>
Int -> simplePolygon -> simplePolygon
rotateLeft Int
n simplePolygon
pg = NonEmpty point -> simplePolygon
forall simplePolygon point r (f :: * -> *).
(SimplePolygon_ simplePolygon point r, Foldable1 f) =>
f point -> simplePolygon
forall (f :: * -> *). Foldable1 f => f point -> simplePolygon
uncheckedFromCCWPoints
                (NonEmpty point -> simplePolygon)
-> NonEmpty point -> simplePolygon
forall a b. (a -> b) -> a -> b
$ Getting (NonEmptyDList point) simplePolygon point
-> simplePolygon -> NonEmpty point
forall a s. Getting (NonEmptyDList a) s a -> s -> NonEmpty a
toNonEmptyOf (VertexIx simplePolygon
-> IndexedTraversal1'
     (VertexIx simplePolygon) simplePolygon (Vertex simplePolygon)
forall polygon.
HasOuterBoundary polygon =>
VertexIx polygon
-> IndexedTraversal1' (VertexIx polygon) polygon (Vertex polygon)
ccwOuterBoundaryFrom (Int
n Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` simplePolygon -> Int
forall graph. HasVertices' graph => graph -> Int
numVertices simplePolygon
pg)) simplePolygon
pg

--------------------------------------------------------------------------------
-- * Polygon Shrinking

-- | Shrink a simple polygon.
--
-- The main idea is to try and remove every vertex (making sure that we still get a valid
-- polygon). At the end, we try to simplify the coordinates of the points involved as well.
shrinkPolygon      :: (Ord r, Fractional r, Real r)
                   => SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
shrinkPolygon :: forall r.
(Ord r, Fractional r, Real r) =>
SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
shrinkPolygon SimplePolygon (Point 2 r)
pg
  | SimplePolygon (Point 2 r) -> Bool
forall {graph}. HasVertices' graph => graph -> Bool
isTriangle SimplePolygon (Point 2 r)
pg = SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
forall r.
(Ord r, Fractional r, Real r) =>
SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
simplifyCoords SimplePolygon (Point 2 r)
pg
  | Bool
otherwise     = SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
forall r.
(Ord r, Fractional r) =>
SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
cutEars SimplePolygon (Point 2 r)
pg -- dropVertices <> simplifyCoords pg
  -- where
  --   dropVertices = mapMaybe (dropVertex pg) (pg^..vertices.asIndex)

{-
dropVertex      :: (Ord r, Fractional r, Real r)
                => SimplePolygon (Point 2 r) -> Int
                -> Maybe (SimplePolygon (Point 2 r))
dropVertex pg i = fromPoints' . NonEmpty.tail $ toNonEmptyOf (ccwOuterBoundaryFrom i) pg
  where
    fromPoints' pts = do pg' <- fromPoints pts
                         if hasNoSelfIntersections pg' then pure pg' else Nothing
-}

-- | Try to simplify the coordinates of the points in hte polygon
simplifyCoords     :: forall r. (Ord r, Fractional r, Real r)
                   => SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
simplifyCoords :: forall r.
(Ord r, Fractional r, Real r) =>
SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
simplifyCoords SimplePolygon (Point 2 r)
pg = let (Vector 2 r
v :| [Vector 2 r]
_) = Getting
  (NonEmptyDList (Vector 2 r))
  (SimplePolygon (Point 2 r))
  (Vector 2 r)
-> SimplePolygon (Point 2 r) -> NonEmpty (Vector 2 r)
forall a s. Getting (NonEmptyDList a) s a -> s -> NonEmpty a
toNonEmptyOf ((Vertex (SimplePolygon (Point 2 r))
 -> Const
      (NonEmptyDList (Vector 2 r)) (Vertex (SimplePolygon (Point 2 r))))
-> SimplePolygon (Point 2 r)
-> Const (NonEmptyDList (Vector 2 r)) (SimplePolygon (Point 2 r))
(Point 2 r -> Const (NonEmptyDList (Vector 2 r)) (Point 2 r))
-> SimplePolygon (Point 2 r)
-> Const (NonEmptyDList (Vector 2 r)) (SimplePolygon (Point 2 r))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 r)))
  (SimplePolygon (Point 2 r))
  (SimplePolygon (Point 2 r))
  (Vertex (SimplePolygon (Point 2 r)))
  (Vertex (SimplePolygon (Point 2 r)))
vertices((Point 2 r -> Const (NonEmptyDList (Vector 2 r)) (Point 2 r))
 -> SimplePolygon (Point 2 r)
 -> Const (NonEmptyDList (Vector 2 r)) (SimplePolygon (Point 2 r)))
-> ((Vector 2 r -> Const (NonEmptyDList (Vector 2 r)) (Vector 2 r))
    -> Point 2 r -> Const (NonEmptyDList (Vector 2 r)) (Point 2 r))
-> Getting
     (NonEmptyDList (Vector 2 r))
     (SimplePolygon (Point 2 r))
     (Vector 2 r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Vector 2 r -> Const (NonEmptyDList (Vector 2 r)) (Vector 2 r))
-> Point 2 r -> Const (NonEmptyDList (Vector 2 r)) (Point 2 r)
forall (d :: Nat) r s.
(Dimension (Point 2 r) ~ d, NumType (Point 2 r) ~ r,
 Dimension (Point 2 r) ~ d, NumType (Point 2 r) ~ s) =>
Lens (Point 2 r) (Point 2 r) (Vector d r) (Vector d s)
forall point point' (d :: Nat) r s.
(HasVector point point', Dimension point ~ d, NumType point ~ r,
 Dimension point' ~ d, NumType point' ~ s) =>
Lens point point' (Vector d r) (Vector d s)
Lens (Point 2 r) (Point 2 r) (Vector 2 r) (Vector 2 r)
vector) SimplePolygon (Point 2 r)
pg
                    in [SimplePolygon (Point 2 r)
pgSimplePolygon (Point 2 r)
-> (SimplePolygon (Point 2 r) -> SimplePolygon (Point 2 r))
-> SimplePolygon (Point 2 r)
forall a b. a -> (a -> b) -> b
&(Vertex (SimplePolygon (Point 2 r))
 -> Identity (Vertex (SimplePolygon (Point 2 r))))
-> SimplePolygon (Point 2 r)
-> Identity (SimplePolygon (Point 2 r))
(Point 2 r -> Identity (Point 2 r))
-> SimplePolygon (Point 2 r)
-> Identity (SimplePolygon (Point 2 r))
forall graph graph'.
HasVertices graph graph' =>
IndexedTraversal1
  (VertexIx graph) graph graph' (Vertex graph) (Vertex graph')
IndexedTraversal1
  (VertexIx (SimplePolygon (Point 2 r)))
  (SimplePolygon (Point 2 r))
  (SimplePolygon (Point 2 r))
  (Vertex (SimplePolygon (Point 2 r)))
  (Vertex (SimplePolygon (Point 2 r)))
vertices ((Point 2 r -> Identity (Point 2 r))
 -> SimplePolygon (Point 2 r)
 -> Identity (SimplePolygon (Point 2 r)))
-> (Point 2 r -> Point 2 r)
-> SimplePolygon (Point 2 r)
-> SimplePolygon (Point 2 r)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (Point 2 r -> Vector 2 r -> Point 2 r
forall point (d :: Nat) r.
(Affine_ point d r, Num r) =>
point -> Vector d r -> point
.-^ Vector 2 r
v)]

  --     -- Scale up polygon such that each coordinate is a whole number.
  --   | lcmP /= 1 = [ pg' | pg' <- fromPoints' $ multP lcmP <$> pg^..vertices ]
  --                -- we use fromPoints to make sure that we don't create repeated vertices.
  --     -- Scale down polygon maintaining each coordinate as a whole number
  --   | gcdP /= 1 = [ pg' | pg' <- fromPoints' $ divP gcdP <$> pg^..vertices ]
  --   | minX /= 0 || minY /= 0 = [ pg' | pg' <- fromPoints' $ align <$> pg^..vertices ]
  --   | otherwise =
  --     let pg' = pg&vertices %~ _div2
  --     in [ pg' | hasNoSelfIntersections $ toNonEmptyOf vertices pg' ]
  --   -- otherwise = []
  -- where
  --   fromPoints' = maybeToList . fromPoints
  --   align = alignZero pg

  --   lcmP = lcmPoint pg
  --   gcdP = gcdPoint pg

  --   minX = first1Of (minimumVertexBy (comparing (^.xCoord)).xCoord) pg
  --   minY = first1Of (minimumVertexBy (comparing (^.yCoord)).yCoord) pg

  --   multP v (Point2 c d) = Point2 (c*v) (d*v)
  --   divP v (Point2 c d) = Point2 (c/v) (d/v)
  --   _div2 p = let (Point2 a b) = p&coordinates %~ toRational
  --             in Point2 (fromRational $ numerator a `div` 2 % 1)
  --                       (fromRational $ numerator b `div` 2 % 1)

{-
-- | Aligns the polygon so that at least one point has x and y- coordinate zero
alignZero      :: (Polygon_ polygon (Point 2 r) r, Num r, Ord r)
               => polygon -> Point 2 r -> Point 2 r
alignZero pg v = Point (v .-. Point2 minX minY)
  where
    minX = first1Of (minimumVertexBy (comparing (^.xCoord)).xCoord) pg
    minY = first1Of (minimumVertexBy (comparing (^.yCoord)).yCoord) pg



lcmPoint :: (Ord r, Fractional r, Real r) => SimplePolygon (Point 2 r) -> r
lcmPoint p = realToFrac t
  where
    vs = p^..outerBoundary
    lst = concatMap ((\(Point2 x y) -> [denominator x, denominator y])
                    . over coordinates toRational
                    ) vs
    t = foldl1 lcm lst

gcdPoint :: (Ord r, Fractional r, Real r) => SimplePolygon (Point 2 r) -> r
gcdPoint p = realToFrac t
  where
    vs = p^..outerBoundary
    lst = concatMap ((\(Point2 x y) -> [denominator x, denominator y])
                    . over coordinates toRational)
                    vs
    t = foldl1 gcd lst


-}

isTriangle :: graph -> Bool
isTriangle graph
pg = graph -> Int
forall graph. HasVertices' graph => graph -> Int
numVertices graph
pg Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3

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


-- remove vertex i, thereby dropping a vertex
cutEarAt      :: (Ord r, Fractional r)
              => SimplePolygon (Point 2 r) -> Int -> Maybe (SimplePolygon (Point 2 r))
cutEarAt :: forall r.
(Ord r, Fractional r) =>
SimplePolygon (Point 2 r)
-> Int -> Maybe (SimplePolygon (Point 2 r))
cutEarAt SimplePolygon (Point 2 r)
pg Int
i = [Point 2 r] -> Maybe (SimplePolygon (Point 2 r))
forall simplePolygon point r (f :: * -> *).
(SimplePolygon_ simplePolygon point r, Foldable f,
 ConstructableSimplePolygon simplePolygon point r) =>
f point -> Maybe simplePolygon
forall (f :: * -> *).
(Foldable f,
 ConstructableSimplePolygon
   (SimplePolygon (Point 2 r)) (Point 2 r) r) =>
f (Point 2 r) -> Maybe (SimplePolygon (Point 2 r))
fromPoints [Point 2 r]
vs
  where
    vs :: [Point 2 r]
vs = IndexedGetting
  Int (Endo [Point 2 r]) (SimplePolygon (Point 2 r)) (Point 2 r)
-> (Int -> Point 2 r -> [Point 2 r] -> [Point 2 r])
-> [Point 2 r]
-> SimplePolygon (Point 2 r)
-> [Point 2 r]
forall i r s a.
IndexedGetting i (Endo r) s a -> (i -> a -> r -> r) -> r -> s -> r
ifoldrOf Indexed
  Int
  (Vertex (SimplePolygon (Point 2 r)))
  (Const (Endo [Point 2 r]) (Vertex (SimplePolygon (Point 2 r))))
-> SimplePolygon (Point 2 r)
-> Const (Endo [Point 2 r]) (SimplePolygon (Point 2 r))
IndexedGetting
  Int (Endo [Point 2 r]) (SimplePolygon (Point 2 r)) (Point 2 r)
forall polygon.
HasOuterBoundary polygon =>
IndexedTraversal1' (VertexIx polygon) polygon (Vertex polygon)
IndexedTraversal1'
  (VertexIx (SimplePolygon (Point 2 r)))
  (SimplePolygon (Point 2 r))
  (Vertex (SimplePolygon (Point 2 r)))
outerBoundary (\Int
j Point 2 r
v [Point 2 r]
vs' -> if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
j then [Point 2 r]
vs' else Point 2 r
vPoint 2 r -> [Point 2 r] -> [Point 2 r]
forall a. a -> [a] -> [a]
:[Point 2 r]
vs') [] SimplePolygon (Point 2 r)
pg

cutEars :: (Ord r, Fractional r)
  => SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
cutEars :: forall r.
(Ord r, Fractional r) =>
SimplePolygon (Point 2 r) -> [SimplePolygon (Point 2 r)]
cutEars SimplePolygon (Point 2 r)
pg | SimplePolygon (Point 2 r) -> Bool
forall {graph}. HasVertices' graph => graph -> Bool
isTriangle SimplePolygon (Point 2 r)
pg = []
           | Bool
otherwise     = [ SimplePolygon (Point 2 r)
pg' | Int
i <- [Int
0 .. (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)], Int -> Bool
isEar Int
i, SimplePolygon (Point 2 r)
pg' <- Maybe (SimplePolygon (Point 2 r)) -> [SimplePolygon (Point 2 r)]
forall a. Maybe a -> [a]
maybeToList (SimplePolygon (Point 2 r)
-> Int -> Maybe (SimplePolygon (Point 2 r))
forall r.
(Ord r, Fractional r) =>
SimplePolygon (Point 2 r)
-> Int -> Maybe (SimplePolygon (Point 2 r))
cutEarAt SimplePolygon (Point 2 r)
pg Int
i) ]
  where
    n :: Int
n = SimplePolygon (Point 2 r) -> Int
forall graph. HasVertices' graph => graph -> Int
numVertices SimplePolygon (Point 2 r)
pg
    isEar :: Int -> Bool
isEar Int
i = let prev :: Point 2 r
prev = SimplePolygon (Point 2 r)
pgSimplePolygon (Point 2 r)
-> Getting (Point 2 r) (SimplePolygon (Point 2 r)) (Point 2 r)
-> Point 2 r
forall s a. s -> Getting a s a -> a
^.VertexIx (SimplePolygon (Point 2 r))
-> IndexedGetter
     (VertexIx (SimplePolygon (Point 2 r)))
     (SimplePolygon (Point 2 r))
     (Vertex (SimplePolygon (Point 2 r)))
forall polygon.
HasOuterBoundary polygon =>
VertexIx polygon
-> IndexedGetter (VertexIx polygon) polygon (Vertex polygon)
outerBoundaryVertexAt ((Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
n)
                  cur :: Point 2 r
cur  = SimplePolygon (Point 2 r)
pgSimplePolygon (Point 2 r)
-> Getting (Point 2 r) (SimplePolygon (Point 2 r)) (Point 2 r)
-> Point 2 r
forall s a. s -> Getting a s a -> a
^.VertexIx (SimplePolygon (Point 2 r))
-> IndexedGetter
     (VertexIx (SimplePolygon (Point 2 r)))
     (SimplePolygon (Point 2 r))
     (Vertex (SimplePolygon (Point 2 r)))
forall polygon.
HasOuterBoundary polygon =>
VertexIx polygon
-> IndexedGetter (VertexIx polygon) polygon (Vertex polygon)
outerBoundaryVertexAt Int
VertexIx (SimplePolygon (Point 2 r))
i
                  nxt :: Point 2 r
nxt  = SimplePolygon (Point 2 r)
pgSimplePolygon (Point 2 r)
-> Getting (Point 2 r) (SimplePolygon (Point 2 r)) (Point 2 r)
-> Point 2 r
forall s a. s -> Getting a s a -> a
^.VertexIx (SimplePolygon (Point 2 r))
-> IndexedGetter
     (VertexIx (SimplePolygon (Point 2 r)))
     (SimplePolygon (Point 2 r))
     (Vertex (SimplePolygon (Point 2 r)))
forall polygon.
HasOuterBoundary polygon =>
VertexIx polygon
-> IndexedGetter (VertexIx polygon) polygon (Vertex polygon)
outerBoundaryVertexAt ((Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
n)
                  triangle :: Triangle (Point 2 r)
triangle = Point 2 r -> Point 2 r -> Point 2 r -> Triangle (Point 2 r)
forall point. point -> point -> point -> Triangle point
Triangle Point 2 r
prev Point 2 r
cur Point 2 r
nxt
              in Point 2 r -> Point 2 r -> Point 2 r -> CCW
forall point r point' point''.
(Point_ point 2 r, Point_ point' 2 r, Point_ point'' 2 r, Num r,
 Ord r) =>
point -> point' -> point'' -> CCW
ccw Point 2 r
prev Point 2 r
cur Point 2 r
nxt CCW -> CCW -> Bool
forall a. Eq a => a -> a -> Bool
== CCW
CCW -- left turn.
                 Bool -> Bool -> Bool
&&
                 Getting All (SimplePolygon (Point 2 r)) (Point 2 r)
-> (Point 2 r -> Bool) -> SimplePolygon (Point 2 r) -> Bool
forall s a. Getting All s a -> (a -> Bool) -> s -> Bool
allOf (Vertex (SimplePolygon (Point 2 r))
 -> Const All (Vertex (SimplePolygon (Point 2 r))))
-> SimplePolygon (Point 2 r)
-> Const All (SimplePolygon (Point 2 r))
Getting All (SimplePolygon (Point 2 r)) (Point 2 r)
forall polygon.
HasOuterBoundary polygon =>
IndexedTraversal1' (VertexIx polygon) polygon (Vertex polygon)
IndexedTraversal1'
  (VertexIx (SimplePolygon (Point 2 r)))
  (SimplePolygon (Point 2 r))
  (Vertex (SimplePolygon (Point 2 r)))
outerBoundary
                       (\Point 2 r
pt -> Point 2 r
pt Point 2 r -> [Point 2 r] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Point 2 r
prev,Point 2 r
cur,Point 2 r
nxt] Bool -> Bool -> Bool
|| Bool -> Bool
not (Point 2 r
pt Point 2 r -> Triangle (Point 2 r) -> Bool
forall g h. HasIntersectionWith g h => g -> h -> Bool
`intersects` Triangle (Point 2 r)
triangle)) SimplePolygon (Point 2 r)
pg