{- |
  2-dimensional linear transformations.
-}

module Data.Vector.Transform.T2 where

import Data.Semigroup
import Data.Monoid

import Data.Vector.Class
import Data.Vector.V2

{- |
  The type of 2D linear transformations.

  Note the @Monoid@ instance, which gives you access to the identity transform (@mempty@) and the ability to combine a series of transforms into a single transform (@mappend@).
-}
data Transform2 =
    Transform2
    {
      Transform2 -> Scalar
t2_XX, Transform2 -> Scalar
t2_YX, Transform2 -> Scalar
t2_1X,
      Transform2 -> Scalar
t2_XY, Transform2 -> Scalar
t2_YY, Transform2 -> Scalar
t2_1Y :: {-# UNPACK #-} !Scalar
    }
  deriving (Transform2 -> Transform2 -> Bool
(Transform2 -> Transform2 -> Bool)
-> (Transform2 -> Transform2 -> Bool) -> Eq Transform2
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Transform2 -> Transform2 -> Bool
== :: Transform2 -> Transform2 -> Bool
$c/= :: Transform2 -> Transform2 -> Bool
/= :: Transform2 -> Transform2 -> Bool
Eq, Int -> Transform2 -> ShowS
[Transform2] -> ShowS
Transform2 -> String
(Int -> Transform2 -> ShowS)
-> (Transform2 -> String)
-> ([Transform2] -> ShowS)
-> Show Transform2
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Transform2 -> ShowS
showsPrec :: Int -> Transform2 -> ShowS
$cshow :: Transform2 -> String
show :: Transform2 -> String
$cshowList :: [Transform2] -> ShowS
showList :: [Transform2] -> ShowS
Show)

instance Monoid Transform2 where
  mempty :: Transform2
mempty = Scalar
-> Scalar -> Scalar -> Scalar -> Scalar -> Scalar -> Transform2
Transform2  Scalar
1 Scalar
0 Scalar
0  Scalar
0 Scalar
1 Scalar
0

instance Semigroup Transform2 where
  Transform2
a <> :: Transform2 -> Transform2 -> Transform2
<> Transform2
b =
    Transform2
    {
      t2_XX :: Scalar
t2_XX = Transform2 -> Scalar
t2_XX Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_XX Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_XY Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_YX Transform2
b,
      t2_YX :: Scalar
t2_YX = Transform2 -> Scalar
t2_YX Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_XX Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_YY Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_YX Transform2
b,
      t2_1X :: Scalar
t2_1X = Transform2 -> Scalar
t2_1X Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_XX Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_1Y Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_YX Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_1X Transform2
b,

      t2_XY :: Scalar
t2_XY = Transform2 -> Scalar
t2_XX Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_XY Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_XY Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_YY Transform2
b,
      t2_YY :: Scalar
t2_YY = Transform2 -> Scalar
t2_YX Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_XY Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_YY Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_YY Transform2
b,
      t2_1Y :: Scalar
t2_1Y = Transform2 -> Scalar
t2_1X Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_XY Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_1Y Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Transform2 -> Scalar
t2_YY Transform2
b  Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+  Transform2 -> Scalar
t2_1Y Transform2
b
    }

-- | Apply a 2D transformation to a 2D point, yielding a new 2D point.
transformP2 :: Transform2 -> Vector2 -> Vector2
transformP2 :: Transform2 -> Vector2 -> Vector2
transformP2 Transform2
a (Vector2 Scalar
x Scalar
y) =
  Vector2
  {
    v2x :: Scalar
v2x = Transform2 -> Scalar
t2_XX Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
x Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+ Transform2 -> Scalar
t2_YX Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
y Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+ Transform2 -> Scalar
t2_1X Transform2
a,
    v2y :: Scalar
v2y = Transform2 -> Scalar
t2_XY Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
x Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+ Transform2 -> Scalar
t2_YY Transform2
a Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
y Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
+ Transform2 -> Scalar
t2_1Y Transform2
a
  }