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