module Diagrams.TwoD.Types
       ( 
         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
r2 :: (n, n) -> V2 n
r2 = uncurry V2
unr2 :: V2 n -> (n, n)
unr2 (V2 x y) = (x, y)
mkR2 :: n -> n -> V2 n
mkR2 = V2
r2Iso :: Iso' (V2 n) (n, n)
r2Iso = iso unr2 r2
p2 :: (n, n) -> P2 n
p2 = P . uncurry V2
unp2 :: P2 n -> (n,n)
unp2 (P (V2 x y)) = (x,y)
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 θ))
class HasR t where
  _r :: RealFloat n => Lens' (t n) n
instance HasR v => HasR (Point v) where
  _r = lensP . _r
  
instance HasR V2 where
  _r = r2PolarIso . _1
  
instance HasTheta V2 where
  _theta = r2PolarIso . _2