{-# 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