content: {-# LANGUAGE RankNTypes   #-}
  {-# LANGUAGE TypeFamilies #-}
  
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Diagrams.Core.Points
  -- Copyright   :  (c) 2011 diagrams-core team (see LICENSE)
  -- License     :  BSD-style (see LICENSE)
  -- Maintainer  :  diagrams-discuss@googlegroups.com
  --
  -- A type for /points/ (as distinct from vectors).
  --
  -----------------------------------------------------------------------------
  
  module Diagrams.Core.Points
         ( -- * Points
  
           Point(..), origin, (*.), relative, _Point
  
         , reflectThrough, mirror, relative2, relative3
         ) where
  
  import           Control.Lens    (over)
  
  import           Linear.Affine
  import           Linear.Vector
  
  import           Diagrams.Core.V
  
  type instance V (Point v n) = v
  type instance N (Point v n) = n
  
  -- | Reflect a point across the origin.
  mirror :: (Additive v, Num n) => Point v n -> Point v n
  mirror = reflectThrough origin
  
  -- | Scale a point by a scalar. Specialized version of '(*^)'.
  (*.) :: (Functor v, Num n) => n -> Point v n -> Point v n
  (*.) = (*^)
  
  -- | Apply a transformation relative to the given point.
  relative2 :: (Additive v, Num n)
    => Point v n -> (v n -> v n -> v n)
    -> Point v n -> Point v n -> Point v n
  relative2 p f x y = (p .+^) $ f (inj x) (inj y) where inj = (.-. p)
  
  -- | Apply a transformation relative to the given point.
  relative3 :: (Additive v, Num n)
    => Point v n -> (v n -> v n -> v n -> v n)
    -> Point v n -> Point v n -> Point v n -> Point v n
  relative3 p f x y z = (p .+^) $ f (inj x) (inj y) (inj z) where inj = (.-. p)
  
  -- | Mirror a point through a given point.
  reflectThrough :: (Additive v, Num n) => Point v n -> Point v n -> Point v n
  reflectThrough o = over (relative o) negated
  
  