module Graphics.Rasterific.Line
( lineFromPath
, clipLine
, sanitizeLine
, lineBreakAt
, flattenLine
, lineLength
) where
import Control.Applicative( Applicative, (<$>), pure )
import Data.Monoid( Monoid, (<>), mempty )
import Linear( V2( .. ), (^-^), norm )
import Graphics.Rasterific.Operators
import Graphics.Rasterific.Types
lineFromPath :: [Point] -> [Line]
lineFromPath [] = []
lineFromPath lst@(_:rest) =
uncurry Line <$> zip lst rest
lineLength :: Line -> Float
lineLength (Line a b) = norm (b ^-^ a)
sanitizeLine :: Line -> Container Primitive
sanitizeLine l@(Line p1 p2)
| p1 `isNearby` p2 = mempty
| otherwise = pure $ LinePrim l
lineBreakAt :: Line -> Float -> (Line, Line)
lineBreakAt (Line a b) t = (Line a ab, Line ab b)
where ab = lerpPoint a b t
flattenLine :: Line -> Container Primitive
flattenLine = pure . LinePrim
clipLine :: Point
-> Point
-> Line
-> Container Primitive
clipLine mini maxi poly@(Line a b)
| insideX && insideY = pure . LinePrim $ poly
| outsideX || outsideY = pure . LinePrim $ Line clampedA clampedB
| otherwise = recurse (Line a m) <> recurse (Line m b)
where
bmin = vmin a b
bmax = vmax a b
recurse = clipLine mini maxi
clamper = clampPoint mini maxi
clampedA = clamper a
clampedB = clamper b
V2 insideX insideY = mini ^<=^ bmin ^&&^ bmax ^<=^ maxi
V2 outsideX outsideY = bmax ^<=^ mini ^||^ maxi ^<=^ bmin
ab = (a `midPoint` b)
edgeSeparator =
vabs (ab ^-^ mini) ^<^ vabs (ab ^-^ maxi)
edge = vpartition edgeSeparator mini maxi
m = vpartition (vabs (ab ^-^ edge) ^< 0.1) edge ab