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

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

    -- | A vector can be treated as a point, and vis-versa.
    type Vector	= Point

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

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

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

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

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

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

    -- | Compute the inner angle (in radians) between two vectors.
    angleVV :: Vector -> Vector -> Float
    {-# INLINE angleVV #-}
    angleVV p1 p2
     = let 	m1	= magV p1
     	m2	= magV p2
    	d	= p1 `dotV` p2
    	aDiff	= acos $ d / (m1 * m2)

       in	aDiff

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

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