-- | Functions to cut things into pieces.
--
-- <<docs/haddock/Geometry/Algorithms/Clipping/complicated_intersection.svg>>
--
-- === __(image code)__
-- >>> import Draw
-- >>> import qualified Graphics.Rendering.Cairo as C
-- >>> :{
-- haddockRender "Geometry/Algorithms/Clipping/complicated_intersection.svg" 200 160 $ \_ -> do
--     let p1 = Polygon
--             [ Vec2 40 30, Vec2 140 30, Vec2 140 140, Vec2 120 140, Vec2 120 80, Vec2 100 80
--             , Vec2 100 140, Vec2 80 140, Vec2 80 60, Vec2 60 60, Vec2 60 140, Vec2 40 140 ]
--         p2 = Polygon
--             [ Vec2 180 20, Vec2 130 20, Vec2 130 35, Vec2 120 35, Vec2 120 20, Vec2 110 20
--             , Vec2 110 35, Vec2 100 35, Vec2 100 20, Vec2 90 20, Vec2 90 35, Vec2 80 35
--             , Vec2 80 20, Vec2 70 20, Vec2 70 35, Vec2 60 35, Vec2 60 20, Vec2 20 20
--             , Vec2 20 40, Vec2 170 60, Vec2 50 80, Vec2 170 100, Vec2 10 120, Vec2 180 140 ]
--         cutResult = intersectionPP p1 p2
--     setLineJoin LineJoinRound
--     cairoScope $ do
--         setLineWidth 1
--         setColor (mma 0)
--         sketch p1
--         stroke
--     cairoScope $ do
--         setLineWidth 1
--         setColor (mma 1)
--         sketch p2
--         stroke
--     for_ (zip [2..] cutResult) $ \(i, (polygon, _islandOrHole)) -> cairoScope $ do
--         setLineWidth 2
--         sketch polygon
--         setColor (mma i `withOpacity` 0.2)
--         fillPreserve
--         setColor (mma i)
--         stroke
-- :}
-- Generated file: size 5KB, crc32: 0xd81cbd60
module Geometry.Algorithms.Clipping (
      cutLineWithLine
    , CutLine(..)
    , cutPolygon
    , cohenSutherland

    , LineType(..)
    , clipPolygonWithLine
    , clipPolygonWithLineSegment

    , sutherlandHodgman
    , IslandOrHole(..)
    , intersectionPP
    , unionPP
    , differencePP

    , hatch
) where



import Geometry.Algorithms.Clipping.CohenSutherland
import Geometry.Algorithms.Clipping.Internal
import Geometry.Algorithms.Clipping.MargalitKnott
    (IslandOrHole (..), differencePP, intersectionPP, unionPP)
import Geometry.Algorithms.Clipping.SutherlandHodgman
import Geometry.Core

-- $setup
-- >>> import Draw
-- >>> import Graphics.Rendering.Cairo

-- | Add shading lines to a polygon. This is especially useful for a pen plotter to
-- do shading, hence the name.
--
-- <<docs/haddock/Geometry/Algorithms/Clipping/hatched_polygon.svg>>
--
-- === __(image code)__
-- >>> :{
-- haddockRender "Geometry/Algorithms/Clipping/hatched_polygon.svg" 100 100 $ \_ -> do
--     let polygon = Polygon [Vec2 10 10, Vec2 70 45, Vec2 90 10, Vec2 90 90, Vec2 50 55, Vec2 10 90]
--     let hatching = hatch polygon (deg 30) 10 0
--     cairoScope $ do
--         for_ hatching sketch
--         setColor (mma 1)
--         stroke
--     sketch polygon
--     stroke
-- :}
-- Generated file: size 2KB, crc32: 0x81dce6d7
hatch
    :: Polygon
    -> Angle -- ^ Direction in which the lines will point. @'deg' 0@ is parallel to the x axis.
    -> Double -- ^ Distance between shading lines
    -> Double -- ^ An offset of 0 means a line will go through the center of the polygon's 'BoundingBox'.
    -> [Line]
hatch :: Polygon -> Angle -> Double -> Double -> [Line]
hatch Polygon
polygon Angle
angle Double
interval Double
offset = do
    let transformation :: Transformation
transformation = Angle -> Transformation
rotate (Angle -> Angle
forall v. VectorSpace v => v -> v
negateV Angle
angle)
        polygonAligned :: Polygon
polygonAligned = Transformation -> Polygon -> Polygon
forall geo. Transform geo => Transformation -> geo -> geo
transform Transformation
transformation Polygon
polygon
        BoundingBox (Vec2 Double
xLo Double
yLo) (Vec2 Double
xHi Double
yHi) = Polygon -> BoundingBox
forall a. HasBoundingBox a => a -> BoundingBox
boundingBox Polygon
polygonAligned
        yMid :: Double
yMid = (Double
yLo Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
yHi) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
offset
        yUp :: [Double]
yUp = (Double -> Bool) -> [Double] -> [Double]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
yHi) ((Double -> Double) -> Double -> [Double]
forall a. (a -> a) -> a -> [a]
iterate (Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
interval) Double
yMid)
        yDown :: [Double]
yDown = (Double -> Bool) -> [Double] -> [Double]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
yLo) ([Double] -> [Double]
forall a. HasCallStack => [a] -> [a]
tail ((Double -> Double) -> Double -> [Double]
forall a. (a -> a) -> a -> [a]
iterate (Double -> Double -> Double
forall a. Num a => a -> a -> a
subtract Double
interval) Double
yMid))
    Line
horizontalScissors <- do
            Double
y <- [Double]
yUp [Double] -> [Double] -> [Double]
forall a. [a] -> [a] -> [a]
++ [Double]
yDown
            Line -> [Line]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Vec2 -> Vec2 -> Line
Line (Double -> Double -> Vec2
Vec2 Double
xLo Double
y) (Double -> Double -> Vec2
Vec2 Double
xHi Double
y))
    Line
horizontalHatches <- [Line
line | (Line
line, LineType
LineInsidePolygon) <- Polygon -> Line -> [(Line, LineType)]
clipPolygonWithLine Polygon
polygonAligned Line
horizontalScissors]
    Line -> [Line]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Transformation -> Line -> Line
forall geo. Transform geo => Transformation -> geo -> geo
transform (Transformation -> Transformation
forall a. Group a => a -> a
inverse Transformation
transformation) Line
horizontalHatches)