    {-# 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 :: forall n. (n, n) -> V2 n
    r2 = (n -> n -> V2 n) -> (n, n) -> V2 n
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2

    -- | Convert a 2D vector back into a pair of components.  See also 'coords'.
    unr2 :: V2 n -> (n, n)
    unr2 :: forall n. V2 n -> (n, n)
    unr2 (V2 n
    x n
    y) = (n
    x, n
    y)

    -- | Curried form of `r2`.
    mkR2 :: n -> n -> V2 n
    mkR2 :: forall a. a -> a -> V2 a
    mkR2 = n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2

    r2Iso :: Iso' (V2 n) (n, n)
    r2Iso :: forall n (p :: * -> * -> *) (f :: * -> *).
    (Profunctor p, Functor f) =>
    p (n, n) (f (n, n)) -> p (V2 n) (f (V2 n))
    r2Iso = (V2 n -> (n, n))
    -> ((n, n) -> V2 n) -> Iso (V2 n) (V2 n) (n, n) (n, n)
    forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
    iso V2 n -> (n, n)
    forall n. V2 n -> (n, n)
    unr2 (n, n) -> V2 n
    forall n. (n, n) -> V2 n
    r2

    -- | Construct a 2D point from a pair of coordinates.  See also '^&'.
    p2 :: (n, n) -> P2 n
    p2 :: forall n. (n, n) -> P2 n
    p2 = V2 n -> Point V2 n
    forall (f :: * -> *) a. f a -> Point f a
    P (V2 n -> Point V2 n) -> ((n, n) -> V2 n) -> (n, n) -> Point V2 n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (n -> n -> V2 n) -> (n, n) -> V2 n
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2

    -- | Convert a 2D point back into a pair of coordinates.  See also 'coords'.
    unp2 :: P2 n -> (n,n)
    unp2 :: forall n. P2 n -> (n, n)
    unp2 (P (V2 n
    x n
    y)) = (n
    x,n
    y)

    -- | Curried form of `p2`.
    mkP2 :: n -> n -> P2 n
    mkP2 :: forall n. n -> n -> P2 n
    mkP2 n
    x n
    y = V2 n -> Point V2 n
    forall (f :: * -> *) a. f a -> Point f a
    P (n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2 n
    x n
    y)

    p2Iso :: Iso' (Point V2 n) (n, n)
    p2Iso :: forall n (p :: * -> * -> *) (f :: * -> *).
    (Profunctor p, Functor f) =>
    p (n, n) (f (n, n)) -> p (Point V2 n) (f (Point V2 n))
    p2Iso = (Point V2 n -> (n, n))
    -> ((n, n) -> Point V2 n)
    -> Iso (Point V2 n) (Point V2 n) (n, n) (n, n)
    forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
    iso Point V2 n -> (n, n)
    forall n. P2 n -> (n, n)
    unp2 (n, n) -> Point V2 n
    forall n. (n, n) -> P2 n
    p2

    instance Transformable (V2 n) where
      transform :: Transformation (V (V2 n)) (N (V2 n)) -> V2 n -> V2 n
    transform = Transformation (V (V2 n)) (N (V2 n)) -> V2 n -> V2 n
    Transformation V2 n -> V2 n -> V2 n
    forall (v :: * -> *) n. Transformation v n -> v n -> v n
    apply

    r2PolarIso :: RealFloat n => Iso' (V2 n) (n, Angle n)
    r2PolarIso :: forall n. RealFloat n => Iso' (V2 n) (n, Angle n)
    r2PolarIso = (V2 n -> (n, Angle n))
    -> ((n, Angle n) -> V2 n)
    -> Iso (V2 n) (V2 n) (n, Angle n) (n, Angle n)
    forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
    iso (\v :: V2 n
    v@(V2 n
    x n
    y) -> (V2 n -> n
    forall a. Floating a => V2 a -> a
    forall (f :: * -> *) a. (Metric f, Floating a) => f a -> a
    norm V2 n
    v, n -> n -> Angle n
    forall n. RealFloat n => n -> n -> Angle n
    atan2A n
    y n
    x))
                  (\(n
    r,Angle n
    θ)      -> n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2 (n
    r n -> n -> n
    forall a. Num a => a -> a -> a
    * Angle n -> n
    forall n. Floating n => Angle n -> n
    cosA Angle n
    θ) (n
    r n -> n -> n
    forall a. Num a => a -> a -> a
    * Angle n -> n
    forall n. Floating n => Angle n -> n
    sinA Angle n
    θ))
    {-# 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 :: forall n. RealFloat n => Lens' (Point v n) n
    _r = (v n -> f (v n)) -> Point v n -> f (Point v n)
    forall (f1 :: * -> *) a (g :: * -> *) b (f2 :: * -> *).
    Functor f2 =>
    (f1 a -> f2 (g b)) -> Point f1 a -> f2 (Point g b)
    lensP ((v n -> f (v n)) -> Point v n -> f (Point v n))
    -> ((n -> f n) -> v n -> f (v n))
    -> (n -> f n)
    -> Point v n
    -> f (Point v n)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (n -> f n) -> v n -> f (v n)
    forall n. RealFloat n => Lens' (v n) n
    Lens' (v n) n
    forall (t :: * -> *) n. (HasR t, RealFloat n) => Lens' (t n) n
    _r
      {-# INLINE _r #-}

    instance HasR V2 where
      _r :: forall n. RealFloat n => Lens' (V2 n) n
    _r = ((n, Angle n) -> f (n, Angle n)) -> V2 n -> f (V2 n)
    forall n. RealFloat n => Iso' (V2 n) (n, Angle n)
    Iso' (V2 n) (n, Angle n)
    r2PolarIso (((n, Angle n) -> f (n, Angle n)) -> V2 n -> f (V2 n))
    -> ((n -> f n) -> (n, Angle n) -> f (n, Angle n))
    -> (n -> f n)
    -> V2 n
    -> f (V2 n)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (n -> f n) -> (n, Angle n) -> f (n, Angle n)
    forall s t a b. Field1 s t a b => Lens s t a b
    Lens (n, Angle n) (n, Angle n) n n
    _1
      {-# INLINE _r #-}

    instance HasTheta V2 where
      _theta :: forall n. RealFloat n => Lens' (V2 n) (Angle n)
    _theta = ((n, Angle n) -> f (n, Angle n)) -> V2 n -> f (V2 n)
    forall n. RealFloat n => Iso' (V2 n) (n, Angle n)
    Iso' (V2 n) (n, Angle n)
    r2PolarIso (((n, Angle n) -> f (n, Angle n)) -> V2 n -> f (V2 n))
    -> ((Angle n -> f (Angle n)) -> (n, Angle n) -> f (n, Angle n))
    -> (Angle n -> f (Angle n))
    -> V2 n
    -> f (V2 n)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Angle n -> f (Angle n)) -> (n, Angle n) -> f (n, Angle n)
    forall s t a b. Field2 s t a b => Lens s t a b
    Lens (n, Angle n) (n, Angle n) (Angle n) (Angle n)
    _2
      {-# INLINE _theta #-}