content: {-# LANGUAGE TypeFamilies #-}
  
  {-# OPTIONS_GHC -fno-warn-orphans #-}
  
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Diagrams.TwoD.Types
  -- Copyright   :  (c) 2011 diagrams-lib team (see LICENSE)
  -- License     :  BSD-style (see LICENSE)
  -- Maintainer  :  diagrams-discuss@googlegroups.com
  --
  -- Basic types for two-dimensional Euclidean space.
  --
  -----------------------------------------------------------------------------
  
  module Diagrams.TwoD.Types
         ( -- * 2D Euclidean space
           V2 (..), R1 (..), R2 (..)
         , P2, T2
         , r2, unr2, mkR2, r2Iso
         , p2, mkP2, unp2, p2Iso
         , r2PolarIso
         , HasR (..)
         ) where
  
  import           Control.Lens            (Iso', Lens', iso, _1, _2)
  
  import           Diagrams.Angle
  import           Diagrams.Points
  
  import           Diagrams.Core.Transform
  import           Diagrams.Core.V
  import           Linear.Metric
  import           Linear.V2
  
  type P2 = Point V2
  type T2 = Transformation V2
  
  type instance V (V2 n) = V2
  type instance N (V2 n) = n
  
  -- | Construct a 2D vector from a pair of components.  See also '&'.
  r2 :: (n, n) -> V2 n
  r2 = uncurry V2
  
  -- | Convert a 2D vector back into a pair of components.  See also 'coords'.
  unr2 :: V2 n -> (n, n)
  unr2 (V2 x y) = (x, y)
  
  -- | Curried form of `r2`.
  mkR2 :: n -> n -> V2 n
  mkR2 = V2
  
  r2Iso :: Iso' (V2 n) (n, n)
  r2Iso = iso unr2 r2
  
  -- | Construct a 2D point from a pair of coordinates.  See also '^&'.
  p2 :: (n, n) -> P2 n
  p2 = P . uncurry V2
  
  -- | Convert a 2D point back into a pair of coordinates.  See also 'coords'.
  unp2 :: P2 n -> (n,n)
  unp2 (P (V2 x y)) = (x,y)
  
  -- | Curried form of `p2`.
  mkP2 :: n -> n -> P2 n
  mkP2 x y = P (V2 x y)
  
  p2Iso :: Iso' (Point V2 n) (n, n)
  p2Iso = iso unp2 p2
  
  instance Transformable (V2 n) where
    transform = apply
  
  r2PolarIso :: RealFloat n => Iso' (V2 n) (n, Angle n)
  r2PolarIso = iso (\v@(V2 x y) -> (norm v, atan2A y x))
                (\(r,θ)      -> V2 (r * cosA θ) (r * sinA θ))
  {-# INLINE r2PolarIso #-}
  
  -- | A space which has magnitude '_r' that can be calculated numerically.
  class HasR t where
    _r :: RealFloat n => Lens' (t n) n
  
  instance HasR v => HasR (Point v) where
    _r = lensP . _r
    {-# INLINE _r #-}
  
  instance HasR V2 where
    _r = r2PolarIso . _1
    {-# INLINE _r #-}
  
  instance HasTheta V2 where
    _theta = r2PolarIso . _2
    {-# INLINE _theta #-}
  