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