gelatin-0.1.0.0: src/Gelatin/Core/Utils.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Gelatin.Core.Utils where
import Data.Vector.Unboxed (Unbox, Vector)
import qualified Data.Vector.Unboxed as V
import Linear
-- | Determine if a point lies within a polygon path using the even/odd
-- rule.
-- A point is inside a path if it has an odd number of intersections with
-- the boundary (Jordan Curve theorem)
pathHasPoint :: (Ord a, Fractional a, Unbox a) => Vector (V2 a) -> V2 a -> Bool
pathHasPoint vs v = V.foldr' (\s a -> if s then not a else a) False $
V.zipWith3 f vv vs (V.drop 1 vs)
where vv = V.replicate (V.length vs) v
f a b c = t1 a b c && t2 a b c
t1 p p1 p2 = (y p2 > y p) /= (y p1 > y p)
t2 p p1 p2 = x p < (x p1 - x p2) * (y p - y p2) / (y p1 - y p2) + x p2
x (V2 a _) = a
y (V2 _ b) = b