diagrams-lib-1.4: src/Diagrams/TwoD/Vector.hs
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.TwoD.Vector
-- Copyright : (c) 2011 diagrams-lib team (see LICENSE)
-- License : BSD-style (see LICENSE)
-- Maintainer : diagrams-discuss@googlegroups.com
--
-- Two-dimensional vectors.
--
-----------------------------------------------------------------------------
module Diagrams.TwoD.Vector
( -- * Special 2D vectors
unitX, unitY, unit_X, unit_Y
, xDir, yDir
-- * Converting between vectors and angles
, angleV, angleDir, e, signedAngleBetween, signedAngleBetweenDirs
-- * 2D vector utilities
, perp, leftTurn, cross2
) where
import Control.Lens (view, (&), (.~), (^.))
import Diagrams.Angle
import Diagrams.Direction
import Diagrams.TwoD.Types
import Linear.Metric
import Linear.V2
import Linear.Vector
-- | The unit vector in the positive X direction.
unitX :: (R1 v, Additive v, Num n) => v n
unitX = zero & _x .~ 1
-- | The unit vector in the negative X direction.
unit_X :: (R1 v, Additive v, Num n) => v n
unit_X = zero & _x .~ (-1)
-- | The unit vector in the positive Y direction.
unitY :: (R2 v, Additive v, Num n) => v n
unitY = zero & _y .~ 1
-- | The unit vector in the negative Y direction.
unit_Y :: (R2 v, Additive v, Num n) => v n
unit_Y = zero & _y .~ (-1)
-- | A 'Direction' pointing in the X direction.
xDir :: (R1 v, Additive v, Num n) => Direction v n
xDir = dir unitX
-- | A 'Direction' pointing in the Y direction.
yDir :: (R2 v, Additive v, Num n) => Direction v n
yDir = dir unitY
-- | A direction at a specified angle counter-clockwise from the 'xDir'.
angleDir :: Floating n => Angle n -> Direction V2 n
angleDir = dir . angleV
-- | A unit vector at a specified angle counter-clockwise from the
-- positive x-axis
angleV :: Floating n => Angle n -> V2 n
angleV = angle . view rad
-- | A unit vector at a specified angle counter-clockwise from the
-- positive X axis.
e :: Floating n => Angle n -> V2 n
e = angleV
-- | @leftTurn v1 v2@ tests whether the direction of @v2@ is a left
-- turn from @v1@ (that is, if the direction of @v2@ can be obtained
-- from that of @v1@ by adding an angle 0 <= theta <= tau/2).
leftTurn :: (Num n, Ord n) => V2 n -> V2 n -> Bool
leftTurn v1 v2 = (v1 `dot` perp v2) < 0
-- | Cross product on vectors in R2.
cross2 :: Num n => V2 n -> V2 n -> n
cross2 (V2 x1 y1) (V2 x2 y2) = x1 * y2 - y1 * x2
-- | Signed angle between two vectors. Currently defined as
--
-- @
-- signedAngleBetween u v = (u ^. _theta) ^-^ (v ^. _theta)
-- @
signedAngleBetween :: RealFloat n => V2 n -> V2 n -> Angle n
signedAngleBetween u v = (u ^. _theta) ^-^ (v ^. _theta)
-- | Same as 'signedAngleBetween' but for 'Directions's.
signedAngleBetweenDirs :: RealFloat n => Direction V2 n -> Direction V2 n -> Angle n
signedAngleBetweenDirs u v = (u ^. _theta) ^-^ (v ^. _theta)