moonlight-triangulation-0.1.0.0: src-core/Moonlight/Triangulation/LineSideInfo.hs
-- | Which side of a directed line a point falls on, as a total three-valued
-- answer that carries the collinear case rather than rounding it away.
module Moonlight.Triangulation.LineSideInfo
( LineSideInfo
, fromDeterminant
, fromOrdering
, sideOrdering
, isOnLeftSide
, isOnRightSide
, isOnLine
, isOnLeftSideOrLine
, isOnRightSideOrLine
, reverseSide
) where
-- | A three-valued side: the collinear case is a value, not a rounding.
newtype LineSideInfo = LineSideInfo Ordering
deriving stock (Show)
deriving newtype (Eq, Ord)
-- | The side an orientation determinant's sign names.
fromDeterminant :: Double -> LineSideInfo
fromDeterminant value = LineSideInfo (compare value 0)
{-# INLINE fromDeterminant #-}
-- | The side an 'Ordering' names.
fromOrdering :: Ordering -> LineSideInfo
fromOrdering = LineSideInfo
{-# INLINE fromOrdering #-}
-- | The underlying 'Ordering'.
sideOrdering :: LineSideInfo -> Ordering
sideOrdering (LineSideInfo ordering) = ordering
{-# INLINE sideOrdering #-}
-- | The five side tests; the @OrLine@ pair admit the collinear case.
isOnLeftSide, isOnRightSide, isOnLine, isOnLeftSideOrLine, isOnRightSideOrLine :: LineSideInfo -> Bool
isOnLeftSide (LineSideInfo ordering) = ordering == GT
isOnRightSide (LineSideInfo ordering) = ordering == LT
isOnLine (LineSideInfo ordering) = ordering == EQ
isOnLeftSideOrLine side = not (isOnRightSide side)
isOnRightSideOrLine side = not (isOnLeftSide side)
{-# INLINE isOnLeftSide #-}
{-# INLINE isOnRightSide #-}
{-# INLINE isOnLine #-}
{-# INLINE isOnLeftSideOrLine #-}
{-# INLINE isOnRightSideOrLine #-}
-- | The same point, seen along the reversed line.
reverseSide :: LineSideInfo -> LineSideInfo
reverseSide (LineSideInfo ordering) = LineSideInfo $ case ordering of
LT -> GT
EQ -> EQ
GT -> LT
{-# INLINE reverseSide #-}