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