module Graphics.FieldTrip.Vector3
(
Vector3(..), vector3
, xVector3, yVector3, zVector3
, vector3x, vector3y, vector3z
, vector3Spherical
, vector3SphericalCoords
, vector3D, unvector3D, cross3
) where
import Control.Applicative
import Graphics.Rendering.OpenGL (Vector3(..))
import Data.VectorSpace
import Data.MemoTrie
import Data.Basis
import Data.Derivative
import Data.Cross
import Graphics.FieldTrip.Vector2
vector3 :: s -> s -> s -> Vector3 s
vector3 = Vector3
xVector3 :: Num s => Vector3 s
xVector3 = Vector3 1 0 0
yVector3 :: Num s => Vector3 s
yVector3 = Vector3 0 1 0
zVector3 :: Num s => Vector3 s
zVector3 = Vector3 0 0 1
vector3x, vector3y, vector3z :: Vector3 s -> s
vector3x (Vector3 x _ _) = x
vector3y (Vector3 _ y _) = y
vector3z (Vector3 _ _ z) = z
vector3Spherical :: Floating s => s -> s -> s -> Vector3 s
vector3Spherical rho theta phi =
Vector3 (rho * sinPhi * cosTheta)
(rho * sinPhi * sinTheta)
(rho * cosPhi)
where
cosTheta = cos theta; cosPhi = cos phi
sinTheta = sin theta; sinPhi = sin phi
vector3SphericalCoords :: (InnerSpace s, Floating s, Scalar s ~ s)
=> Vector3 s -> (s,s,s)
vector3SphericalCoords v@(Vector3 x y z) = (rho, theta, phi)
where
rho = magnitude v
theta = atan (y/x)
phi = acos (z / rho)
instance Functor Vector3 where
fmap f (Vector3 x y z) = Vector3 (f x) (f y) (f z)
instance Applicative Vector3 where
pure x = Vector3 x x x
Vector3 f g h <*> Vector3 x y z = Vector3 (f x) (g y) (h z)
instance AdditiveGroup u => AdditiveGroup (Vector3 u) where
zeroV = Vector3 zeroV zeroV zeroV
Vector3 u v w ^+^ Vector3 u' v' w'
= Vector3 (u^+^u') (v^+^v') (w^+^w')
negateV (Vector3 u v w) = Vector3 (negateV u) (negateV v) (negateV w)
instance VectorSpace u => VectorSpace (Vector3 u) where
type Scalar (Vector3 u) = Scalar u
s *^ Vector3 u v w = Vector3 (s*^u) (s*^v) (s*^w)
instance (InnerSpace u, AdditiveGroup (Scalar u))
=> InnerSpace (Vector3 u) where
Vector3 u v w <.> Vector3 u' v' w' = u<.>u' ^+^ v<.>v' ^+^ w<.>w'
instance HasBasis u => HasBasis (Vector3 u) where
type Basis (Vector3 u) = Basis (u,u,u)
basisValue = toV3 . basisValue
decompose = decompose . fromV3
decompose' = decompose' . fromV3
toV3 :: (u,u,u) -> Vector3 u
toV3 (u,v,w) = Vector3 u v w
fromV3 :: Vector3 u -> (u,u,u)
fromV3 (Vector3 u v w) = (u,v,w)
instance ( Num s, VectorSpace s
, HasBasis s, HasTrie (Basis s), Basis s ~ () )
=> HasNormal (Vector2 s :> Vector3 s) where
normalVec v = d (Left ()) `cross3` d (Right ())
where
d = untrie (derivative v)
instance Num s => HasCross3 (Vector3 s) where
Vector3 ax ay az `cross3` Vector3 bx by bz =
Vector3 (ay * bz az * by)
(az * bx ax * bz)
(ax * by ay * bx)
instance HasNormal (Three (Vector2 Float :> Float)) where
normalVec = unvector3D . normalVec . vector3D
instance HasNormal (Three (Vector2 Double :> Double)) where
normalVec = unvector3D . normalVec . vector3D
vector3D :: (VectorSpace s, HasTrie (Basis a)) =>
Three (a :> s) -> a :> (Vector3 s)
vector3D (u,v,w) = liftD3 Vector3 u v w
unvector3D :: (VectorSpace s, HasTrie (Basis a)) =>
a :> (Vector3 s) -> Three (a :> s)
unvector3D d = (vector3x <$>> d, vector3y <$>> d, vector3z <$>> d)