{-# OPTIONS -fno-warn-missing-methods #-}
{-# LANGUAGE TypeSynonymInstances #-}

-- | Geometric functions concerning vectors.
module Graphics.Gloss.Data.Vector
        ( Vector
        , magV
        , argV
        , dotV
        , detV
        , mulSV
        , rotateV
        , angleVV
        , normalizeV
        , unitVectorAtAngle )
where
import Graphics.Gloss.Data.Picture
import Graphics.Gloss.Geometry.Angle


-- | The magnitude of a vector.
magV :: Vector -> Float
magV :: Vector -> Float
magV (Float
x, Float
y)
        = Float -> Float
forall a. Floating a => a -> a
sqrt (Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y)
{-# INLINE magV #-}


-- | The angle of this vector, relative to the +ve x-axis.
argV :: Vector -> Float
argV :: Vector -> Float
argV (Float
x, Float
y)
        = Float -> Float
normalizeAngle (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
forall a. RealFloat a => a -> a -> a
atan2 Float
y Float
x
{-# INLINE argV #-}


-- | The dot product of two vectors.
dotV :: Vector -> Vector -> Float
dotV :: Vector -> Vector -> Float
dotV (Float
x1, Float
x2) (Float
y1, Float
y2)
        = Float
x1 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y1 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
x2 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y2
{-# INLINE dotV #-}


-- | The determinant of two vectors.
detV :: Vector -> Vector -> Float
detV :: Vector -> Vector -> Float
detV (Float
x1, Float
y1) (Float
x2, Float
y2)
        = Float
x1 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x2
{-# INLINE detV #-}


-- | Multiply a vector by a scalar.
mulSV :: Float -> Vector -> Vector
mulSV :: Float -> Vector -> Vector
mulSV Float
s (Float
x, Float
y)
        = (Float
s Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x, Float
s Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y)
{-# INLINE mulSV #-}


-- | Rotate a vector by an angle (in radians). +ve angle is counter-clockwise.
rotateV :: Float -> Vector -> Vector
rotateV :: Float -> Vector -> Vector
rotateV Float
r (Float
x, Float
y)
 =      (  Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin Float
r
        ,  Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos Float
r)
{-# INLINE rotateV #-}


-- | Compute the inner angle (in radians) between two vectors.
angleVV :: Vector -> Vector -> Float
angleVV :: Vector -> Vector -> Float
angleVV Vector
p1 Vector
p2
 = let  m1 :: Float
m1      = Vector -> Float
magV Vector
p1
        m2 :: Float
m2      = Vector -> Float
magV Vector
p2
        d :: Float
d       = Vector
p1 Vector -> Vector -> Float
`dotV` Vector
p2
        aDiff :: Float
aDiff   = Float -> Float
forall a. Floating a => a -> a
acos (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$ Float
d Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
m1 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
m2)

   in   Float
aDiff
{-# INLINE angleVV #-}


-- | Normalise a vector, so it has a magnitude of 1.
normalizeV :: Vector -> Vector
normalizeV :: Vector -> Vector
normalizeV Vector
v    = Float -> Vector -> Vector
mulSV (Float
1 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Vector -> Float
magV Vector
v) Vector
v
{-# INLINE normalizeV #-}


-- | Produce a unit vector at a given angle relative to the +ve x-axis.
--      The provided angle is in radians.
unitVectorAtAngle :: Float -> Vector
unitVectorAtAngle :: Float -> Vector
unitVectorAtAngle Float
r
        = (Float -> Float
forall a. Floating a => a -> a
cos Float
r, Float -> Float
forall a. Floating a => a -> a
sin Float
r)
{-# INLINE unitVectorAtAngle #-}