geom2d-0.1.2.0: Geom2d/Point.hs
module Geom2d.Point
( Point (..)
, Point'
, Triangle
, Scale (..)
, normalize
, magnitude
, dot
, cross
, triArea
, pointInTriangle
)
where
import Geom2d.Point.Internal
-- | A triangle is simply a tuple of three points.
type Triangle p = (p,p,p)
infixl 7 `dot`,`cross`
-- | This function defines the dot product of two vectors.
dot :: (Num a, Point p) => p a -> p a -> a
dot a b = x a * x b + y a * y b
-- | This function defined the cross product of two vectors.
cross :: (Num a, Point p) => p a -> p a -> a
cross a b = x a * y b - y a * x b
-- | Calculate the area of a triangle.
triArea :: (Point p, Num (p a), Fractional a) => Triangle (p a) -> a
triArea (a,b,c) = abs $ ((b - a) `cross` (c - a)) / 2
-- | Determin whether a point is in a triangle. A point being on the
-- edge is considered inside the triangle.
pointInTriangle :: (Eq (p a), Num (p a), Fractional a, Point p, Ord a) =>
Triangle (p a) -> p a -> Bool
pointInTriangle (a,b,c) p
-- barycentric coordinates
| b == a || c == a || b == c = False
| p == a = True
| otherwise = u >= 0 && v >= 0 && u + v <= 1
where
u = ( v1Square * v2v0 - v1v0 * v2v1 ) / denom
v = ( v0Square * v2v1 - v0v1 * v2v0 ) / denom
denom = v0Square * v1Square - v0v1 * v1v0
v1Square = v1 `dot` v1
v0Square = v0 `dot` v0
v1v0 = v1 `dot` v0
v0v1 = v0 `dot` v1
v2v0 = v2 `dot` v0
v2v1 = v2 `dot` v1
v0 = c-a
v1 = b-a
v2 = p-a
-- | This type class modells data that can be scaled by a factor.
class Scale p where
scale :: (Num a) => a -> p a -> p a
instance Scale Point' where
scale s (Point' (a,b)) = Point' (a * s, b * s)
-- | Normalizes a scaleable point to length 1.
normalize :: (Scale p, Point p, Fractional a, Eq a, Floating a) =>
p a -> Maybe (p a)
normalize v | magnitude v == 0 = Nothing
| otherwise = Just $ scale (1/magnitude v) v