{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE UndecidableInstances #-}
-- --------------------------------------------------------------------------------
-- |
-- Module      :  HGeometry.Transformation.Internal
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--------------------------------------------------------------------------------
module HGeometry.Transformation.Internal where

import Control.Lens (iso,set,Iso,over,iover)
import Data.List.NonEmpty (NonEmpty(..))
import GHC.TypeLits
import HGeometry.Ext
import HGeometry.Matrix
import HGeometry.Point
import HGeometry.Properties
import HGeometry.Vector

--------------------------------------------------------------------------------

-- $setup
-- >>> import HGeometry.Point
-- >>> import HGeometry.Vector

--------------------------------------------------------------------------------
-- * Transformations

-- | A type representing a Transformation for d dimensional objects
newtype Transformation d r = Transformation { forall (d :: Natural) r.
Transformation d r -> Matrix (d + 1) (d + 1) r
_transformationMatrix :: Matrix (d + 1) (d + 1) r }


-- | Transformations and Matrices are isomorphic.
transformationMatrix :: Iso (Transformation d r)       (Transformation d       s)
                            (Matrix (d + 1) (d + 1) r) (Matrix (d + 1) (d + 1) s)
transformationMatrix :: forall (d :: Natural) r s (p :: * -> * -> *) (f :: * -> *).
(Profunctor p, Functor f) =>
p (Matrix (d + 1) (d + 1) r) (f (Matrix (d + 1) (d + 1) s))
-> p (Transformation d r) (f (Transformation d s))
transformationMatrix = (Transformation d r -> Matrix (d + 1) (d + 1) r)
-> (Matrix (d + 1) (d + 1) s -> Transformation d s)
-> Iso
     (Transformation d r)
     (Transformation d s)
     (Matrix (d + 1) (d + 1) r)
     (Matrix (d + 1) (d + 1) s)
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso Transformation d r -> Matrix (d + 1) (d + 1) r
forall (d :: Natural) r.
Transformation d r -> Matrix (d + 1) (d + 1) r
_transformationMatrix Matrix (d + 1) (d + 1) s -> Transformation d s
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation

deriving stock   instance (Show (Matrix (d+1) (d+1) r)) => Show (Transformation d r)
deriving newtype instance (Eq (Matrix (d+1) (d+1) r))   => Eq (Transformation d r)
deriving newtype instance (Ord (Matrix (d+1) (d+1) r))  => Ord (Transformation d r)



type instance NumType (Transformation d r) = r

-- | Compose transformations (right to left)
(|.|)                                     :: (Num r, OptMatrix_ (d+1) r)
                                          => Transformation d r -> Transformation d r
                                          -> Transformation d r
(Transformation Matrix (d + 1) (d + 1) r
f) |.| :: forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r -> Transformation d r -> Transformation d r
|.| (Transformation Matrix (d + 1) (d + 1) r
g) = Matrix (d + 1) (d + 1) r -> Transformation d r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix (d + 1) (d + 1) r -> Transformation d r)
-> Matrix (d + 1) (d + 1) r -> Transformation d r
forall a b. (a -> b) -> a -> b
$ Matrix (d + 1) (d + 1) r
f Matrix (d + 1) (d + 1) r
-> Matrix (d + 1) (d + 1) r -> Matrix (d + 1) (d + 1) r
forall matrix (n :: Natural) (m :: Natural) r matrix'
       (m' :: Natural) matrix''.
(Matrix_ matrix n m r, Matrix_ matrix' m m' r,
 Matrix_ matrix'' n m' r, Num r, Has_ Additive_ m r) =>
matrix -> matrix' -> matrix''
forall matrix' (m' :: Natural) matrix''.
(Matrix_ matrix' (d + 1) m' r, Matrix_ matrix'' (d + 1) m' r,
 Num r, Has_ Additive_ (d + 1) r) =>
Matrix (d + 1) (d + 1) r -> matrix' -> matrix''
!*! Matrix (d + 1) (d + 1) r
g
{-# INLINE (|.|) #-}

-- | Identity transformation; i.e. the transformation which does not change anything.
identity :: (Num r, OptMatrix_ (d+1) r) => Transformation d r
identity :: forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r
identity = Matrix (d + 1) (d + 1) r -> Transformation d r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation Matrix (d + 1) (d + 1) r
forall matrix (n :: Natural) (m :: Natural) r.
(Matrix_ matrix n m r, Num r) =>
matrix
identityMatrix


instance (Num r, OptMatrix_ (d+1) r) => Semigroup (Transformation d r) where
  <> :: Transformation d r -> Transformation d r -> Transformation d r
(<>) = Transformation d r -> Transformation d r -> Transformation d r
forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r -> Transformation d r -> Transformation d r
(|.|)
  {-# INLINE (<>) #-}
instance (Num r, OptMatrix_ (d+1) r) => Monoid (Transformation d r) where
  mempty :: Transformation d r
mempty = Transformation d r
forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r
identity

-- if it exists?

-- | Compute the inverse transformation
--
-- >>> inverseOf $ translation (Vector2 (10.0) (5.0))
-- Transformation {_transformationMatrix = Matrix (Vector3 (Vector3 1.0 0.0 (-10.0)) (Vector3 0.0 1.0 (-5.0)) (Vector3 0.0 0.0 1.0))}
inverseOf :: (  Fractional r, OptMatrix_ (d+1) r, Invertible (d + 1)
             ) => Transformation d r -> Transformation d r
inverseOf :: forall r (d :: Natural).
(Fractional r, OptMatrix_ (d + 1) r, Invertible (d + 1)) =>
Transformation d r -> Transformation d r
inverseOf = Matrix (d + 1) (d + 1) r -> Transformation d r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix (d + 1) (d + 1) r -> Transformation d r)
-> (Transformation d r -> Matrix (d + 1) (d + 1) r)
-> Transformation d r
-> Transformation d r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix (d + 1) (d + 1) r -> Matrix (d + 1) (d + 1) r
forall (n :: Natural) r matrix.
(Invertible n, Fractional r, Matrix_ matrix n n r,
 Has_ Vector_ n r) =>
matrix -> matrix
forall r matrix.
(Fractional r, Matrix_ matrix (d + 1) (d + 1) r,
 Has_ Vector_ (d + 1) r) =>
matrix -> matrix
inverseMatrix (Matrix (d + 1) (d + 1) r -> Matrix (d + 1) (d + 1) r)
-> (Transformation d r -> Matrix (d + 1) (d + 1) r)
-> Transformation d r
-> Matrix (d + 1) (d + 1) r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Transformation d r -> Matrix (d + 1) (d + 1) r
forall (d :: Natural) r.
Transformation d r -> Matrix (d + 1) (d + 1) r
_transformationMatrix
{-# INLINE inverseOf #-}

--------------------------------------------------------------------------------
-- * Transformable geometry objects

-- | Some constraints that we will pretty much need to transform a d
-- dimensional object whose numtype is r
type TransformationConstraints d r =
  ( KnownNat d
  , Has_ Vector_ d r
  , OptMatrix_ (d+1) r
  , HasComponents (Vector (d+1) r)
                  (Vector (d+1) (Vector (d+1) r))
  , Has_ Additive_ (d+1) r
  )

-- | Bunch of constraints we need for the default implementation of transformBy
type DefaultTransformByConstraints g d r =
  ( d ~ Dimension g, r ~ NumType g
  -- , forall point. HasPoints g g point point
  -- , Point_ point d r
  , OptMatrix_ (d+1) r
  , Fractional r
  , Has_ Additive_ d r
  , HasComponents (Vector (d+1) (Vector (d+1) r)) (Vector (d+1) r)
  , d <= d+1, d <= (d+1) - 1
  )

-- | A class representing types that can be transformed using a transformation
class IsTransformable g where
  transformBy :: Transformation (Dimension g) (NumType g) -> g -> g
  default transformBy :: forall d r point.
                         ( DefaultTransformByConstraints g d r
                         , Point_ point d r
                         , HasPoints g g point point
                         )
                      => Transformation (Dimension g) (NumType g) -> g -> g
  transformBy Transformation (Dimension g) (NumType g)
t = ASetter g g (Point d r) (Point d r)
-> (Point d r -> Point d r) -> g -> g
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((point -> Identity point) -> g -> Identity g
forall (d :: Natural) r r'.
(Point_ point d r, Point_ point d r', NumType g ~ r,
 NumType g ~ r', Dimension g ~ d, Dimension g ~ d) =>
Traversal1 g g point point
forall s t point point' (d :: Natural) r r'.
(HasPoints s t point point', Point_ point d r, Point_ point' d r',
 NumType s ~ r, NumType t ~ r', Dimension s ~ d, Dimension t ~ d) =>
Traversal1 s t point point'
Traversal1 g g point point
allPoints((point -> Identity point) -> g -> Identity g)
-> ((Point d r -> Identity (Point d r)) -> point -> Identity point)
-> ASetter g g (Point d r) (Point d r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Point d r -> Identity (Point d r)) -> point -> Identity point
forall point (d :: Natural) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' point (Point d r)
asPoint) (Transformation (Dimension (Point d r)) (NumType (Point d r))
-> Point d r -> Point d r
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy Transformation (Dimension g) (NumType g)
Transformation (Dimension (Point d r)) (NumType (Point d r))
t)
  {-# INLINE transformBy #-}

instance (Fractional r, Has_ Vector_ d r, OptMatrix_ (d+1) r
         , HasComponents (Vector (d+1) (Vector (d+1) r)) (Vector (d+1) r)
         , d <= (d + 1) - 1, d <= d + 1
         ) => IsTransformable (Point d r) where
  transformBy :: Transformation (Dimension (Point d r)) (NumType (Point d r))
-> Point d r -> Point d r
transformBy Transformation (Dimension (Point d r)) (NumType (Point d r))
t = Vector d r -> Point d r
forall v. v -> PointF v
Point (Vector d r -> Point d r)
-> (Point d r -> Vector d r) -> Point d r -> Point d r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Transformation (Dimension (Vector d r)) (NumType (Vector d r))
-> Vector d r -> Vector d r
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy Transformation (Dimension (Point d r)) (NumType (Point d r))
Transformation (Dimension (Vector d r)) (NumType (Vector d r))
t (Vector d r -> Vector d r)
-> (Point d r -> Vector d r) -> Point d r -> Vector d r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point d r -> Vector d r
forall v. PointF v -> v
toVec
  {-# INLINE transformBy #-}

instance ( Fractional r
         , Has_ Vector_ d r
         , OptMatrix_ (d+1) r
         , HasComponents (Vector (d+1) (Vector (d+1) r)) (Vector (d+1) r)
         , d <= (d + 1) - 1, d <= d + 1
         ) => IsTransformable (Vector d r) where
  transformBy :: Transformation (Dimension (Vector d r)) (NumType (Vector d r))
-> Vector d r -> Vector d r
transformBy (Transformation Matrix
  (Dimension (Vector d r) + 1)
  (Dimension (Vector d r) + 1)
  (NumType (Vector d r))
m) Vector d r
v = Vector (d + 1) r -> Vector d r
f (Vector (d + 1) r -> Vector d r) -> Vector (d + 1) r -> Vector d r
forall a b. (a -> b) -> a -> b
$ Matrix (d + 1) (d + 1) r
Matrix
  (Dimension (Vector d r) + 1)
  (Dimension (Vector d r) + 1)
  (NumType (Vector d r))
m Matrix (d + 1) (d + 1) r -> Vector (d + 1) r -> Vector (d + 1) r
forall matrix (n :: Natural) (m :: Natural) r.
(Matrix_ matrix n m r, Has_ Vector_ n (Vector m r),
 HasComponents (Vector n (Vector m r)) (Vector n r),
 Has_ Additive_ m r, Num r) =>
matrix -> Vector m r -> Vector n r
!* (Vector d r -> r -> Vector (d + 1) r
forall vector' vector (d :: Natural) r.
(Vector_ vector d r, Vector_ vector' (d + 1) r) =>
vector -> r -> vector'
snoc Vector d r
v r
1 :: Vector (d+1) r)
    where
      f   :: Vector (d+1) r -> Vector d r
      f :: Vector (d + 1) r -> Vector d r
f Vector (d + 1) r
u = let (Vector d r
u',r
x) = Vector (d + 1) r -> (Vector d r, r)
forall vector' vector (d :: Natural) r.
(Vector_ vector (d + 1) r, Vector_ vector' d r, d <= ((d + 1) - 1),
 d <= Dimension vector) =>
vector -> (vector', r)
unsnoc Vector (d + 1) r
u
            in Vector d r
u' Vector d r -> r -> Vector d r
forall vector (d :: Natural) r.
(Vector_ vector d r, Fractional r) =>
vector -> r -> vector
^/ r
x
  {-# INLINE transformBy #-}

instance IsTransformable core => IsTransformable (core :+ extra) where
  -- ^ transforms only the core.
  transformBy :: Transformation
  (Dimension (core :+ extra)) (NumType (core :+ extra))
-> (core :+ extra) -> core :+ extra
transformBy Transformation
  (Dimension (core :+ extra)) (NumType (core :+ extra))
t = ASetter (core :+ extra) (core :+ extra) core core
-> (core -> core) -> (core :+ extra) -> core :+ extra
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter (core :+ extra) (core :+ extra) core core
forall core extra core' (f :: * -> *).
Functor f =>
(core -> f core') -> (core :+ extra) -> f (core' :+ extra)
core (Transformation (Dimension core) (NumType core) -> core -> core
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy Transformation (Dimension core) (NumType core)
Transformation
  (Dimension (core :+ extra)) (NumType (core :+ extra))
t)

instance IsTransformable geom => IsTransformable [geom] where
  transformBy :: Transformation (Dimension [geom]) (NumType [geom])
-> [geom] -> [geom]
transformBy Transformation (Dimension [geom]) (NumType [geom])
t = (geom -> geom) -> [geom] -> [geom]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Transformation (Dimension geom) (NumType geom) -> geom -> geom
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy Transformation (Dimension geom) (NumType geom)
Transformation (Dimension [geom]) (NumType [geom])
t)

instance IsTransformable geom => IsTransformable (NonEmpty geom) where
  transformBy :: Transformation
  (Dimension (NonEmpty geom)) (NumType (NonEmpty geom))
-> NonEmpty geom -> NonEmpty geom
transformBy Transformation
  (Dimension (NonEmpty geom)) (NumType (NonEmpty geom))
t = (geom -> geom) -> NonEmpty geom -> NonEmpty geom
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Transformation (Dimension geom) (NumType geom) -> geom -> geom
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy Transformation (Dimension geom) (NumType geom)
Transformation
  (Dimension (NonEmpty geom)) (NumType (NonEmpty geom))
t)

--------------------------------------------------------------------------------
-- * Common transformations

-- | Create translation transformation from a vector.
--
-- >>> transformBy (translation $ Vector2 1 2) $ Point2 2 3
-- Point2 3.0 5.0
translation   :: forall d r vector. ( Num r
                                    , Vector_ vector d r
                                    , TransformationConstraints d r
                                    , d <= (d + 1) - 1
                                    )
              => vector -> Transformation d r
translation :: forall (d :: Natural) r vector.
(Num r, Vector_ vector d r, TransformationConstraints d r,
 d <= ((d + 1) - 1)) =>
vector -> Transformation d r
translation vector
v = Matrix (d + 1) (d + 1) r -> Transformation d r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix (d + 1) (d + 1) r -> Transformation d r)
-> (Vector (d + 1) (Vector (d + 1) r) -> Matrix (d + 1) (d + 1) r)
-> Vector (d + 1) (Vector (d + 1) r)
-> Transformation d r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (d + 1) (Vector (d + 1) r) -> Matrix (d + 1) (d + 1) r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix
             (Vector (d + 1) (Vector (d + 1) r) -> Transformation d r)
-> Vector (d + 1) (Vector (d + 1) r) -> Transformation d r
forall a b. (a -> b) -> a -> b
$ AnIndexedSetter
  Int
  (Vector (d + 1) r)
  (Vector (d + 1) (Vector (d + 1) r))
  (IxValue (Vector (d + 1) r))
  (Vector (d + 1) r)
-> (Int -> IxValue (Vector (d + 1) r) -> Vector (d + 1) r)
-> Vector (d + 1) r
-> Vector (d + 1) (Vector (d + 1) r)
forall i s t a b.
AnIndexedSetter i s t a b -> (i -> a -> b) -> s -> t
iover AnIndexedSetter
  Int
  (Vector (d + 1) r)
  (Vector (d + 1) (Vector (d + 1) r))
  (IxValue (Vector (d + 1) r))
  (Vector (d + 1) r)
Indexed
  Int
  (IxValue (Vector (d + 1) r))
  (Identity (IxValue (Vector (d + 1) (Vector (d + 1) r))))
-> Vector (d + 1) r -> Identity (Vector (d + 1) (Vector (d + 1) r))
forall vector vector'.
HasComponents vector vector' =>
IndexedTraversal1
  Int vector vector' (IxValue vector) (IxValue vector')
IndexedTraversal1
  Int
  (Vector (d + 1) r)
  (Vector (d + 1) (Vector (d + 1) r))
  (IxValue (Vector (d + 1) r))
  (IxValue (Vector (d + 1) (Vector (d + 1) r)))
components Int -> IxValue (Vector (d + 1) r) -> Vector (d + 1) r
Int
-> IxValue (Vector (d + 1) r)
-> Vector (d + 1) (IxValue (Vector (d + 1) r))
forall (n :: Natural) r.
(Num r, Has_ Additive_ (n + 1) r, n <= ((n + 1) - 1),
 KnownNat n) =>
Int -> r -> Vector (n + 1) r
transRow (vector -> r -> Vector (d + 1) r
forall vector' vector (d :: Natural) r.
(Vector_ vector d r, Vector_ vector' (d + 1) r) =>
vector -> r -> vector'
snoc vector
v r
1 :: Vector (d+1) r)
{-# INLINE translation #-}

-- class CFunctorWithIndex


-- type TransformationConstraints d r =
--   ( KnownNat d
--   , OptMatrix_ d r
--   , HasComponents (Vector (d+1) r)
--                   (Vector (d+1) (Vector (d+1) r))
--   , OptAdditive_ d r
--   , d < d + 1 -- TODO: get rid of this constraint somehow
--   )


-- | Create scaling transformation from a vector.
--
-- >>> transformBy (scaling $ Vector2 2 (-1)) $ Point2 2 3
-- Point2 4.0 (-3.0)
scaling   :: forall d r vector. ( Num r
             , Vector_ vector d r
             , TransformationConstraints d r
             )
          => vector -> Transformation d r
scaling :: forall (d :: Natural) r vector.
(Num r, Vector_ vector d r, TransformationConstraints d r) =>
vector -> Transformation d r
scaling vector
v = Matrix (d + 1) (d + 1) r -> Transformation d r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix (d + 1) (d + 1) r -> Transformation d r)
-> (Vector (d + 1) (Vector (d + 1) r) -> Matrix (d + 1) (d + 1) r)
-> Vector (d + 1) (Vector (d + 1) r)
-> Transformation d r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (d + 1) (Vector (d + 1) r) -> Matrix (d + 1) (d + 1) r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix
          (Vector (d + 1) (Vector (d + 1) r) -> Transformation d r)
-> Vector (d + 1) (Vector (d + 1) r) -> Transformation d r
forall a b. (a -> b) -> a -> b
$ AnIndexedSetter
  Int
  (Vector (d + 1) r)
  (Vector (d + 1) (Vector (d + 1) r))
  r
  (Vector (d + 1) r)
-> (Int -> r -> Vector (d + 1) r)
-> Vector (d + 1) r
-> Vector (d + 1) (Vector (d + 1) r)
forall i s t a b.
AnIndexedSetter i s t a b -> (i -> a -> b) -> s -> t
iover AnIndexedSetter
  Int
  (Vector (d + 1) r)
  (Vector (d + 1) (Vector (d + 1) r))
  r
  (Vector (d + 1) r)
Indexed
  Int
  (IxValue (Vector (d + 1) r))
  (Identity (IxValue (Vector (d + 1) (Vector (d + 1) r))))
-> Vector (d + 1) r -> Identity (Vector (d + 1) (Vector (d + 1) r))
forall vector vector'.
HasComponents vector vector' =>
IndexedTraversal1
  Int vector vector' (IxValue vector) (IxValue vector')
IndexedTraversal1
  Int
  (Vector (d + 1) r)
  (Vector (d + 1) (Vector (d + 1) r))
  (IxValue (Vector (d + 1) r))
  (IxValue (Vector (d + 1) (Vector (d + 1) r)))
components Int -> r -> Vector (d + 1) r
forall (d :: Natural) r.
(Num r, Has_ Vector_ d r) =>
Int -> r -> Vector d r
mkRow (vector -> r -> Vector (d + 1) r
forall vector' vector (d :: Natural) r.
(Vector_ vector d r, Vector_ vector' (d + 1) r) =>
vector -> r -> vector'
snoc vector
v r
1 :: Vector (d+1) r)
{-# INLINE scaling #-}

-- | Create scaling transformation from a scalar that is applied
--   to all dimensions.
--
-- >>> transformBy (uniformScaling 5) $ Point2 2 3
-- Point2 10.0 15.0
-- >>> uniformScaling 5 == scaling (Vector2 5 5)
-- True
-- >>> uniformScaling 5 == scaling (Vector3 5 5 5)
-- True
uniformScaling   :: forall d r. ( Num r, TransformationConstraints d r
                                ) => r -> Transformation d r
uniformScaling :: forall (d :: Natural) r.
(Num r, TransformationConstraints d r) =>
r -> Transformation d r
uniformScaling r
x = Vector d r -> Transformation d r
forall (d :: Natural) r vector.
(Num r, Vector_ vector d r, TransformationConstraints d r) =>
vector -> Transformation d r
scaling (Vector d r -> Transformation d r)
-> Vector d r -> Transformation d r
forall a b. (a -> b) -> a -> b
$ forall vector (d :: Natural) r.
Vector_ vector d r =>
(Int -> r) -> vector
generate @(Vector d r) (r -> Int -> r
forall a b. a -> b -> a
const r
x)
{-# INLINE uniformScaling #-}


-- test :: Point 2 Double
-- test = transformBy (uniformScaling 5) $ Point2 2 3

-- test2 :: Point 2 Double
-- test2 = transformBy (scaling $ Vector2 2 5) $ Point2 2 3





--------------------------------------------------------------------------------
-- * Functions that execute transformations

-- | Translate a given point.
--
-- >>> translateBy (Vector2 1 2) $ Point2 2 3
-- Point2 3.0 5.0
translateBy :: ( IsTransformable g
               , Num (NumType g)
               , Vector_ vector d (NumType g)
               , TransformationConstraints d (NumType g)
               , Dimension g ~ d
               , d <= (d + 1) - 1
               ) => vector -> g -> g
translateBy :: forall g vector (d :: Natural).
(IsTransformable g, Num (NumType g), Vector_ vector d (NumType g),
 TransformationConstraints d (NumType g), Dimension g ~ d,
 d <= ((d + 1) - 1)) =>
vector -> g -> g
translateBy = Transformation d (IxValue vector) -> g -> g
Transformation (Dimension g) (NumType g) -> g -> g
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy (Transformation d (IxValue vector) -> g -> g)
-> (vector -> Transformation d (IxValue vector))
-> vector
-> g
-> g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. vector -> Transformation d (IxValue vector)
forall (d :: Natural) r vector.
(Num r, Vector_ vector d r, TransformationConstraints d r,
 d <= ((d + 1) - 1)) =>
vector -> Transformation d r
translation
{-# INLINE translateBy #-}

-- | Scale a given point.
--
-- >>> scaleBy (Vector2 2 (-1)) $ Point2 2 3
-- Point2 4.0 (-3.0)
scaleBy :: ( IsTransformable g, Num (NumType g)
           , Vector_ vector d (NumType g)
           , TransformationConstraints d (NumType g)
           , Dimension g ~ d
           , d <= (d + 1) - 1
           ) => vector -> g -> g
scaleBy :: forall g vector (d :: Natural).
(IsTransformable g, Num (NumType g), Vector_ vector d (NumType g),
 TransformationConstraints d (NumType g), Dimension g ~ d,
 d <= ((d + 1) - 1)) =>
vector -> g -> g
scaleBy = Transformation d (IxValue vector) -> g -> g
Transformation (Dimension g) (NumType g) -> g -> g
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy (Transformation d (IxValue vector) -> g -> g)
-> (vector -> Transformation d (IxValue vector))
-> vector
-> g
-> g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. vector -> Transformation d (IxValue vector)
forall (d :: Natural) r vector.
(Num r, Vector_ vector d r, TransformationConstraints d r) =>
vector -> Transformation d r
scaling
{-# INLINE scaleBy #-}


-- | Scale a given point uniformly in all dimensions.
--
-- >>> scaleUniformlyBy 5 $ Point2 2 3
-- Point2 10.0 15.0
scaleUniformlyBy :: ( IsTransformable g, Num (NumType g)
                    , TransformationConstraints d (NumType g)
                    , Dimension g ~ d
                    , d <= (d + 1) - 1
                    ) => NumType g -> g -> g
scaleUniformlyBy :: forall g (d :: Natural).
(IsTransformable g, Num (NumType g),
 TransformationConstraints d (NumType g), Dimension g ~ d,
 d <= ((d + 1) - 1)) =>
NumType g -> g -> g
scaleUniformlyBy = Transformation d (NumType g) -> g -> g
Transformation (Dimension g) (NumType g) -> g -> g
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy  (Transformation d (NumType g) -> g -> g)
-> (NumType g -> Transformation d (NumType g))
-> NumType g
-> g
-> g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NumType g -> Transformation d (NumType g)
forall (d :: Natural) r.
(Num r, TransformationConstraints d r) =>
r -> Transformation d r
uniformScaling
{-# INLINE scaleUniformlyBy #-}


-- | Row in a translation matrix
transRow     :: forall n r . ( Num r
                             , Has_ Additive_ (n+1) r
                             , n <= (n + 1) - 1, KnownNat n
                             )
             => Int -> r -> Vector (n + 1) r
transRow :: forall (n :: Natural) r.
(Num r, Has_ Additive_ (n + 1) r, n <= ((n + 1) - 1),
 KnownNat n) =>
Int -> r -> Vector (n + 1) r
transRow Int
i r
x = ASetter (Vector (n + 1) r) (Vector (n + 1) r) r r
-> r -> Vector (n + 1) r -> Vector (n + 1) r
forall s t a b. ASetter s t a b -> b -> s -> t
set (forall (i :: Natural) vector r (d :: Natural).
(i <= (d - 1), KnownNat i, Vector_ vector d r) =>
IndexedLens' Int vector r
component @n) r
x (Vector (n + 1) r -> Vector (n + 1) r)
-> Vector (n + 1) r -> Vector (n + 1) r
forall a b. (a -> b) -> a -> b
$ Int -> r -> Vector (n + 1) r
forall (d :: Natural) r.
(Num r, Has_ Vector_ d r) =>
Int -> r -> Vector d r
mkRow Int
i r
1

-- | Creates a row with zeroes everywhere, except at position i, where the
-- value is the supplied value.
mkRow     :: forall d r. (Num r, Has_ Vector_ d r) => Int -> r -> Vector d r
mkRow :: forall (d :: Natural) r.
(Num r, Has_ Vector_ d r) =>
Int -> r -> Vector d r
mkRow Int
i r
x = (Int -> r) -> Vector d r
forall vector (d :: Natural) r.
Vector_ vector d r =>
(Int -> r) -> vector
generate ((Int -> r) -> Vector d r) -> (Int -> r) -> Vector d r
forall a b. (a -> b) -> a -> b
$ \Int
j -> if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
j then r
x else r
0

--------------------------------------------------------------------------------
-- * 3D Rotations

-- | Given three new unit-length basis vectors (u,v,w) that map to (x,y,z),
-- construct the appropriate rotation that does this.
--
--
rotateTo                 :: ( Num r
                            ) => Vector 3 (Vector 3 r) -> Transformation 3 r
rotateTo :: forall r. Num r => Vector 3 (Vector 3 r) -> Transformation 3 r
rotateTo (Vector3 Vector 3 r
u Vector 3 r
v Vector 3 r
w) = Matrix 4 4 r -> Transformation 3 r
Matrix (3 + 1) (3 + 1) r -> Transformation 3 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 4 4 r -> Transformation 3 r)
-> (Vector 4 (Vector 4 r) -> Matrix 4 4 r)
-> Vector 4 (Vector 4 r)
-> Transformation 3 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 4 (Vector 4 r) -> Matrix 4 4 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 4 (Vector 4 r) -> Transformation 3 r)
-> Vector 4 (Vector 4 r) -> Transformation 3 r
forall a b. (a -> b) -> a -> b
$ Vector 4 r
-> Vector 4 r -> Vector 4 r -> Vector 4 r -> Vector 4 (Vector 4 r)
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 (Vector 3 r -> r -> Vector 4 r
forall vector' vector (d :: Natural) r.
(Vector_ vector d r, Vector_ vector' (d + 1) r) =>
vector -> r -> vector'
snoc Vector 3 r
u        r
0)
                                                             (Vector 3 r -> r -> Vector 4 r
forall vector' vector (d :: Natural) r.
(Vector_ vector d r, Vector_ vector' (d + 1) r) =>
vector -> r -> vector'
snoc Vector 3 r
v        r
0)
                                                             (Vector 3 r -> r -> Vector 4 r
forall vector' vector (d :: Natural) r.
(Vector_ vector d r, Vector_ vector' (d + 1) r) =>
vector -> r -> vector'
snoc Vector 3 r
w        r
0)
                                                             (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0 r
0 r
0 r
1)
{-# INLINE rotateTo #-}

-- | Euler angle rotation; in order XYZ (from bottom to top in the gimbal hierarchy)
--
-- the angles CCW and given in radians.
rotateXYZ                 :: Floating r => Vector 3 r -> Transformation 3 r
rotateXYZ :: forall r. Floating r => Vector 3 r -> Transformation 3 r
rotateXYZ (Vector3 r
a r
b r
g) = r -> Transformation 3 r
forall r. Floating r => r -> Transformation 3 r
rotateZ r
g Transformation 3 r -> Transformation 3 r -> Transformation 3 r
forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r -> Transformation d r -> Transformation d r
|.| r -> Transformation 3 r
forall r. Floating r => r -> Transformation 3 r
rotateY r
b Transformation 3 r -> Transformation 3 r -> Transformation 3 r
forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r -> Transformation d r -> Transformation d r
|.| r -> Transformation 3 r
forall r. Floating r => r -> Transformation 3 r
rotateX r
a

-- rotateXYZ     :: Floating r => Vector 3 r -> Transformation 3 r
-- rotateXYZ rot = Transformation . Matrix $ Vector4
--      (Vector4 (cb*cg)            ((-1)*cb*sg)       (sb)         0)
--      (Vector4 (ca*sg + cg*sa*sb) (ca*cg - sa*sb*sg) ((-1)*cb*sa) 0)
--      (Vector4 (sa*sg - ca*cg*sb) (cg*sa + ca*sb*sg) (ca*cb)      0)
--      (Vector4 0                  0                  0            1)
--   where
--     Vector3 sa sb sg = sin <$> rot
--     Vector3 ca cb cg = cos <$> rot
-- -- see:
-- -- https://wikimedia.org/api/rest_v1/media/math/render/svg/55b6d5a59a72894c1d1659c1635b71a6e8b13ee7

-- rotateX x =

-- | Rotate $\gamma$-radians CCW around the z-axis
rotateZ       :: Floating r => r -> Transformation 3 r
rotateZ :: forall r. Floating r => r -> Transformation 3 r
rotateZ r
gamma = Matrix 4 4 r -> Transformation 3 r
Matrix (3 + 1) (3 + 1) r -> Transformation 3 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 4 4 r -> Transformation 3 r)
-> (Vector 4 (Vector 4 r) -> Matrix 4 4 r)
-> Vector 4 (Vector 4 r)
-> Transformation 3 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 4 (Vector 4 r) -> Matrix 4 4 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 4 (Vector 4 r) -> Transformation 3 r)
-> Vector 4 (Vector 4 r) -> Transformation 3 r
forall a b. (a -> b) -> a -> b
$ Vector 4 r
-> Vector 4 r -> Vector 4 r -> Vector 4 r -> Vector 4 (Vector 4 r)
forall r. r -> r -> r -> r -> Vector 4 r
Vector4
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
cg (-r
1r -> r -> r
forall a. Num a => a -> a -> a
*r
sg) r
0 r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
sg r
cg      r
0 r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0  r
0       r
1 r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0  r
0       r
0 r
1)
  where
    sg :: r
sg = r -> r
forall a. Floating a => a -> a
sin r
gamma
    cg :: r
cg = r -> r
forall a. Floating a => a -> a
cos r
gamma
  -- for whatever reason the wikipedia page claims this rotates CW ? i.e. the sg and -sg are
  -- flipped in the WP version: https://en.wikipedia.org/wiki/Rotation_matrix



-- | Rotate $\beta$-radians CCW around the y-axis
rotateY       :: Floating r => r -> Transformation 3 r
rotateY :: forall r. Floating r => r -> Transformation 3 r
rotateY r
beta = Matrix 4 4 r -> Transformation 3 r
Matrix (3 + 1) (3 + 1) r -> Transformation 3 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 4 4 r -> Transformation 3 r)
-> (Vector 4 (Vector 4 r) -> Matrix 4 4 r)
-> Vector 4 (Vector 4 r)
-> Transformation 3 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 4 (Vector 4 r) -> Matrix 4 4 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 4 (Vector 4 r) -> Transformation 3 r)
-> Vector 4 (Vector 4 r) -> Transformation 3 r
forall a b. (a -> b) -> a -> b
$ Vector 4 r
-> Vector 4 r -> Vector 4 r -> Vector 4 r -> Vector 4 (Vector 4 r)
forall r. r -> r -> r -> r -> Vector 4 r
Vector4
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
cb r
0 (-r
1r -> r -> r
forall a. Num a => a -> a -> a
*r
sb)  r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0  r
1       r
0  r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
sb r
0       r
cb r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0  r
0       r
0  r
1)
  where
    sb :: r
sb = r -> r
forall a. Floating a => a -> a
sin r
beta
    cb :: r
cb = r -> r
forall a. Floating a => a -> a
cos r
beta

-- | Rotate $\alpha$-radians CCW around the x-axis
rotateX       :: Floating r => r -> Transformation 3 r
rotateX :: forall r. Floating r => r -> Transformation 3 r
rotateX r
alpha = Matrix 4 4 r -> Transformation 3 r
Matrix (3 + 1) (3 + 1) r -> Transformation 3 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 4 4 r -> Transformation 3 r)
-> (Vector 4 (Vector 4 r) -> Matrix 4 4 r)
-> Vector 4 (Vector 4 r)
-> Transformation 3 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 4 (Vector 4 r) -> Matrix 4 4 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 4 (Vector 4 r) -> Transformation 3 r)
-> Vector 4 (Vector 4 r) -> Transformation 3 r
forall a b. (a -> b) -> a -> b
$ Vector 4 r
-> Vector 4 r -> Vector 4 r -> Vector 4 r -> Vector 4 (Vector 4 r)
forall r. r -> r -> r -> r -> Vector 4 r
Vector4
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
1  r
0     r
0  r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0  r
ca    r
sa r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0  (-r
sa) r
ca r
0)
     (r -> r -> r -> r -> Vector 4 r
forall r. r -> r -> r -> r -> Vector 4 r
Vector4 r
0  r
0     r
0  r
1)
  where
    sa :: r
sa = r -> r
forall a. Floating a => a -> a
sin r
alpha
    ca :: r
ca = r -> r
forall a. Floating a => a -> a
cos r
alpha

--------------------------------------------------------------------------------
-- * 2D Transformations

-- | Skew transformation that keeps the y-coordinates fixed and shifts
-- the x coordinates.
skewX        :: ( Num r
                ) => r -> Transformation 2 r
skewX :: forall r. Num r => r -> Transformation 2 r
skewX r
lambda = Matrix 3 3 r -> Transformation 2 r
Matrix (2 + 1) (2 + 1) r -> Transformation 2 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 3 3 r -> Transformation 2 r)
-> (Vector 3 (Vector 3 r) -> Matrix 3 3 r)
-> Vector 3 (Vector 3 r)
-> Transformation 2 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 3 (Vector 3 r) -> Matrix 3 3 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 3 (Vector 3 r) -> Transformation 2 r)
-> Vector 3 (Vector 3 r) -> Transformation 2 r
forall a b. (a -> b) -> a -> b
$ Vector 3 r -> Vector 3 r -> Vector 3 r -> Vector 3 (Vector 3 r)
forall r. r -> r -> r -> Vector 3 r
Vector3 (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 r
1 r
lambda r
0)
                                                 (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 r
0 r
1      r
0)
                                                 (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 r
0 r
0      r
1)


-- | Create a matrix that corresponds to a rotation by 'a' radians counter-clockwise
--   around the origin.
rotation   :: (Floating r) => r -> Transformation 2 r
rotation :: forall r. Floating r => r -> Transformation 2 r
rotation r
a = Matrix 3 3 r -> Transformation 2 r
Matrix (2 + 1) (2 + 1) r -> Transformation 2 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 3 3 r -> Transformation 2 r)
-> (Vector 3 (Vector 3 r) -> Matrix 3 3 r)
-> Vector 3 (Vector 3 r)
-> Transformation 2 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 3 (Vector 3 r) -> Matrix 3 3 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 3 (Vector 3 r) -> Transformation 2 r)
-> Vector 3 (Vector 3 r) -> Transformation 2 r
forall a b. (a -> b) -> a -> b
$ Vector 3 r -> Vector 3 r -> Vector 3 r -> Vector 3 (Vector 3 r)
forall r. r -> r -> r -> Vector 3 r
Vector3 (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 (r -> r
forall a. Floating a => a -> a
cos r
a) (- r -> r
forall a. Floating a => a -> a
sin r
a) r
0)
                                               (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 (r -> r
forall a. Floating a => a -> a
sin r
a) (  r -> r
forall a. Floating a => a -> a
cos r
a) r
0)
                                               (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 r
0       r
0         r
1)

-- | Create a matrix that corresponds to a reflection in a line through the origin
--   which makes an angle of 'a' radians with the positive 'x'-asis, in counter-clockwise
--   orientation.
reflection   :: ( Floating r
                ) => r -> Transformation 2 r
reflection :: forall r. Floating r => r -> Transformation 2 r
reflection r
a = r -> Transformation 2 r
forall r. Floating r => r -> Transformation 2 r
rotation r
a Transformation 2 r -> Transformation 2 r -> Transformation 2 r
forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r -> Transformation d r -> Transformation d r
|.| Transformation 2 r
forall r. Num r => Transformation 2 r
reflectionV Transformation 2 r -> Transformation 2 r -> Transformation 2 r
forall r (d :: Natural).
(Num r, OptMatrix_ (d + 1) r) =>
Transformation d r -> Transformation d r -> Transformation d r
|.| r -> Transformation 2 r
forall r. Floating r => r -> Transformation 2 r
rotation (-r
a)

-- | Vertical reflection
reflectionV :: (Num r) => Transformation 2 r
reflectionV :: forall r. Num r => Transformation 2 r
reflectionV = Matrix 3 3 r -> Transformation 2 r
Matrix (2 + 1) (2 + 1) r -> Transformation 2 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 3 3 r -> Transformation 2 r)
-> (Vector 3 (Vector 3 r) -> Matrix 3 3 r)
-> Vector 3 (Vector 3 r)
-> Transformation 2 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 3 (Vector 3 r) -> Matrix 3 3 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 3 (Vector 3 r) -> Transformation 2 r)
-> Vector 3 (Vector 3 r) -> Transformation 2 r
forall a b. (a -> b) -> a -> b
$ Vector 3 r -> Vector 3 r -> Vector 3 r -> Vector 3 (Vector 3 r)
forall r. r -> r -> r -> Vector 3 r
Vector3 (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 r
1   r
0  r
0)
                                                (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 r
0 (-r
1) r
0)
                                                (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 r
0   r
0  r
1)

-- | Horizontal reflection
reflectionH :: (Num r) => Transformation 2 r
reflectionH :: forall r. Num r => Transformation 2 r
reflectionH = Matrix 3 3 r -> Transformation 2 r
Matrix (2 + 1) (2 + 1) r -> Transformation 2 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation (Matrix 3 3 r -> Transformation 2 r)
-> (Vector 3 (Vector 3 r) -> Matrix 3 3 r)
-> Vector 3 (Vector 3 r)
-> Transformation 2 r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector 3 (Vector 3 r) -> Matrix 3 3 r
forall (n :: Natural) (m :: Natural) r.
Vector n (Vector m r) -> Matrix n m r
Matrix (Vector 3 (Vector 3 r) -> Transformation 2 r)
-> Vector 3 (Vector 3 r) -> Transformation 2 r
forall a b. (a -> b) -> a -> b
$ Vector 3 r -> Vector 3 r -> Vector 3 r -> Vector 3 (Vector 3 r)
forall r. r -> r -> r -> Vector 3 r
Vector3 (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3 (-r
1) r
0  r
0)
                                                (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3   r
0  r
1  r
0)
                                                (r -> r -> r -> Vector 3 r
forall r. r -> r -> r -> Vector 3 r
Vector3   r
0  r
0  r
1)