{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}  -- Vertex3
----------------------------------------------------------------------
-- |
-- Module      :  Graphics.FieldTrip.Point3
-- Copyright   :  (c) Conal Elliott and Andy J Gill 2008
-- License     :  BSD3
-- 
-- Maintainer  :  conal@conal.net, andygill@ku.edu
-- Stability   :  experimental
-- 
-- Points in 3D
----------------------------------------------------------------------

module Graphics.FieldTrip.Point3
  (
    Point3, point3, origin3, Vertex3(..)
  , point3Spherical
  , point3SphericalCoords
  ) where

import Graphics.Rendering.OpenGL (Vertex3(..))

import Data.VectorSpace
import Data.AffineSpace
import Graphics.FieldTrip.Vector3

-- | Synonym for Vertex3, a 3D point, parameterized over coordinate type.
type Point3 = Vertex3

-- | Construct a 3D point in rectangular coordinates.
point3 :: s -> s -> s -> Point3 s
point3 = Vertex3

origin3 :: Num s => Point3 s
origin3 = point3 0 0 0

-- or substitute zeroV for 0 above to relax Num s to VectorSpace s s

-- -- | 3D point, parameterized over coordinate type.
-- data Point3 s = Point3 !s !s !s deriving (Eq, Show)

-- UndecidableInstances because "the Coverage Condition fails" below

instance VectorSpace u => AffineSpace (Vertex3 u) where
  type AVector (Vertex3 u) = Vector3 u
  Vertex3 u v w .-. Vertex3 u' v' w' = Vector3 (u ^-^ u') (v ^-^ v') (w ^-^ w')
  Vertex3 u v w .+^ Vector3 dx dv dw = Vertex3 (u ^+^ dx) (v ^+^ dv) (w ^+^ dw)

vToP :: Vector3 s -> Point3 s
vToP (Vector3 u v w) = Vertex3 u v w

pToV :: Point3 s -> Vector3 s
pToV (Vertex3 u v w) = Vector3 u v w

-- | Vector from spherical coordinates.  See also 'vectorSphericalCoords'.
point3Spherical :: Floating s => s -> s -> s -> Point3 s
point3Spherical = (fmap.fmap.fmap) vToP vector3Spherical

-- | Spherical coordinates of a point.  See also 'point3Spherical'.
point3SphericalCoords :: (InnerSpace s, Floating s, s ~ Scalar s)
                      => Point3 s -> (s,s,s)
point3SphericalCoords = vector3SphericalCoords . pToV