module Graphics.Rasterific.Transformations
( Transformation( .. )
, applyTransformation
, applyVectorTransformation
, translate
, scale
, rotate
, rotateCenter
, skewX
, skewY
, toNewXBase
, inverseTransformation
) where
import Graphics.Rasterific.Types
import Graphics.Rasterific.Linear( V2( .. ), normalize )
data Transformation = Transformation
{ Transformation -> Float
_transformA :: {-# UNPACK #-} !Float
, Transformation -> Float
_transformC :: {-# UNPACK #-} !Float
, Transformation -> Float
_transformE :: {-# UNPACK #-} !Float
, Transformation -> Float
_transformB :: {-# UNPACK #-} !Float
, Transformation -> Float
_transformD :: {-# UNPACK #-} !Float
, Transformation -> Float
_transformF :: {-# UNPACK #-} !Float
}
deriving (Transformation -> Transformation -> Bool
(Transformation -> Transformation -> Bool)
-> (Transformation -> Transformation -> Bool) -> Eq Transformation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Transformation -> Transformation -> Bool
$c/= :: Transformation -> Transformation -> Bool
== :: Transformation -> Transformation -> Bool
$c== :: Transformation -> Transformation -> Bool
Eq, Int -> Transformation -> ShowS
[Transformation] -> ShowS
Transformation -> String
(Int -> Transformation -> ShowS)
-> (Transformation -> String)
-> ([Transformation] -> ShowS)
-> Show Transformation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Transformation] -> ShowS
$cshowList :: [Transformation] -> ShowS
show :: Transformation -> String
$cshow :: Transformation -> String
showsPrec :: Int -> Transformation -> ShowS
$cshowsPrec :: Int -> Transformation -> ShowS
Show)
transformCombine :: Transformation -> Transformation -> Transformation
transformCombine :: Transformation -> Transformation -> Transformation
transformCombine (Transformation Float
a Float
c Float
e
Float
b Float
d Float
f)
(Transformation Float
a' Float
c' Float
e'
Float
b' Float
d' Float
f') =
Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation (Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
a' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
c Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
b' )
(Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
c Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
d' )
(Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
e' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
c Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
f' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
e )
(Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
a' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
b' )
(Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
d' )
(Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
e' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
f' Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
f )
instance Semigroup Transformation where
<> :: Transformation -> Transformation -> Transformation
(<>) = Transformation -> Transformation -> Transformation
transformCombine
instance Monoid Transformation where
mappend :: Transformation -> Transformation -> Transformation
mappend = Transformation -> Transformation -> Transformation
forall a. Semigroup a => a -> a -> a
(<>)
mempty :: Transformation
mempty = Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
1 Float
0 Float
0
Float
0 Float
1 Float
0
applyTransformation :: Transformation -> Point -> Point
applyTransformation :: Transformation -> Point -> Point
applyTransformation (Transformation Float
a Float
c Float
e
Float
b Float
d Float
f) (V2 Float
x Float
y) =
Float -> Float -> Point
forall a. a -> a -> V2 a
V2 (Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
e) (Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
f)
applyVectorTransformation :: Transformation -> Vector -> Vector
applyVectorTransformation :: Transformation -> Point -> Point
applyVectorTransformation
(Transformation Float
a Float
c Float
_e
Float
b Float
d Float
_f) (V2 Float
x Float
y) =
Float -> Float -> Point
forall a. a -> a -> V2 a
V2 (Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c) (Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y)
rotate :: Float
-> Transformation
rotate :: Float -> Transformation
rotate Float
angle = Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
ca (-Float
sa) Float
0
Float
sa Float
ca Float
0
where ca :: Float
ca = Float -> Float
forall a. Floating a => a -> a
cos Float
angle
sa :: Float
sa = Float -> Float
forall a. Floating a => a -> a
sin Float
angle
rotateCenter :: Float
-> Point
-> Transformation
rotateCenter :: Float -> Point -> Transformation
rotateCenter Float
angle Point
p =
Point -> Transformation
translate Point
p Transformation -> Transformation -> Transformation
forall a. Semigroup a => a -> a -> a
<> Float -> Transformation
rotate Float
angle Transformation -> Transformation -> Transformation
forall a. Semigroup a => a -> a -> a
<> Point -> Transformation
translate (Point -> Point
forall a. Num a => a -> a
negate Point
p)
scale :: Float -> Float -> Transformation
scale :: Float -> Float -> Transformation
scale Float
scaleX Float
scaleY =
Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
scaleX Float
0 Float
0
Float
0 Float
scaleY Float
0
translate :: Vector -> Transformation
translate :: Point -> Transformation
translate (V2 Float
x Float
y) =
Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
1 Float
0 Float
x
Float
0 Float
1 Float
y
skewX :: Float -> Transformation
skewX :: Float -> Transformation
skewX Float
v =
Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
1 Float
t Float
0
Float
0 Float
1 Float
0
where t :: Float
t = Float -> Float
forall a. Floating a => a -> a
tan Float
v
skewY :: Float -> Transformation
skewY :: Float -> Transformation
skewY Float
v =
Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
1 Float
0 Float
0
Float
t Float
1 Float
0
where t :: Float
t = Float -> Float
forall a. Floating a => a -> a
tan Float
v
toNewXBase :: Vector -> Transformation
toNewXBase :: Point -> Transformation
toNewXBase Point
vec =
Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
dx (-Float
dy) Float
0
Float
dy Float
dx Float
0
where V2 Float
dx Float
dy = Point -> Point
forall a (f :: * -> *).
(Floating a, Metric f, Epsilon a) =>
f a -> f a
normalize Point
vec
transformationDeterminant :: Transformation -> Float
transformationDeterminant :: Transformation -> Float
transformationDeterminant (Transformation Float
a Float
c Float
_e
Float
b Float
d Float
_f) = Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
c Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
b
inverseTransformation :: Transformation -> Maybe Transformation
inverseTransformation :: Transformation -> Maybe Transformation
inverseTransformation Transformation
trans
| Transformation -> Float
transformationDeterminant Transformation
trans Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
0 = Maybe Transformation
forall a. Maybe a
Nothing
inverseTransformation (Transformation Float
a Float
c Float
e
Float
b Float
d Float
f) =
Transformation -> Maybe Transformation
forall a. a -> Maybe a
Just (Transformation -> Maybe Transformation)
-> Transformation -> Maybe Transformation
forall a b. (a -> b) -> a -> b
$ Float
-> Float -> Float -> Float -> Float -> Float -> Transformation
Transformation Float
a' Float
c' Float
e' Float
b' Float
d' Float
f'
where det :: Float
det = Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
c
a' :: Float
a' = Float
d Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
det
c' :: Float
c' = (- Float
c) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
det
e' :: Float
e' = (Float
c Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
f Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
e Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
d) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
det
b' :: Float
b' = (- Float
b) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
det
d' :: Float
d' = Float
a Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
det
f' :: Float
f' = (Float
e Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
a Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
f) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
det