content: {-# 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 (x, y)
          = sqrt (x * x + y * y)
  {-# INLINE magV #-}
  
  
  -- | The angle of this vector, relative to the +ve x-axis.
  argV :: Vector -> Float
  argV (x, y)
          = normalizeAngle $ atan2 y x
  {-# INLINE argV #-}
  
  
  -- | The dot product of two vectors.
  dotV :: Vector -> Vector -> Float
  dotV (x1, x2) (y1, y2)
          = x1 * y1 + x2 * y2
  {-# INLINE dotV #-}
  
  
  -- | The determinant of two vectors.
  detV :: Vector -> Vector -> Float
  detV (x1, y1) (x2, y2)
          = x1 * y2 - y1 * x2
  {-# INLINE detV #-}
  
  
  -- | Multiply a vector by a scalar.
  mulSV :: Float -> Vector -> Vector
  mulSV s (x, y)
          = (s * x, s * y)
  {-# INLINE mulSV #-}
  
  
  -- | Rotate a vector by an angle (in radians). +ve angle is counter-clockwise.
  rotateV :: Float -> Vector -> Vector
  rotateV r (x, y)
   =      (  x * cos r - y * sin r
          ,  x * sin r + y * cos r)
  {-# INLINE rotateV #-}
  
  
  -- | Compute the inner angle (in radians) between two vectors.
  angleVV :: Vector -> Vector -> Float
  angleVV p1 p2
   = let  m1      = magV p1
          m2      = magV p2
          d       = p1 `dotV` p2
          aDiff   = acos $ d / (m1 * m2)
  
     in   aDiff
  {-# INLINE angleVV #-}
  
  
  -- | Normalise a vector, so it has a magnitude of 1.
  normalizeV :: Vector -> Vector
  normalizeV v    = mulSV (1 / magV v) 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 r
          = (cos r, sin r)
  {-# INLINE unitVectorAtAngle #-}
  
  