```{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}  -- Vertex3
----------------------------------------------------------------------
-- |
-- Module      :  Graphics.FieldTrip.Point3
-- Copyright   :  (c) Conal Elliott and Andy J Gill 2008
--
-- 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 -> Vertex3 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 s => AffineSpace (Vertex3 u) (Vector3 u) s where
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