{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ViewPatterns #-}
module Diagrams.TwoD.Transform
(
T2
, rotation, rotate, rotateBy, rotated
, rotationAround, rotateAround
, rotationTo, rotateTo
, scalingX, scaleX
, scalingY, scaleY
, scaling, scale
, scaleToX, scaleToY
, scaleUToX, scaleUToY
, translationX, translateX
, translationY, translateY
, translation, translate
, scalingRotationTo, scaleRotateTo
, reflectionX, reflectX
, reflectionY, reflectY
, reflectionXY, reflectXY
, reflectionAbout, reflectAbout
, shearingX, shearX
, shearingY, shearY
) where
import Diagrams.Angle
import Diagrams.Core
import Diagrams.Core.Transform
import Diagrams.Direction
import Diagrams.Transform
import Diagrams.Transform.Matrix
import Diagrams.TwoD.Types
import Diagrams.TwoD.Vector
import Control.Lens hiding (at, transform)
import Data.Semigroup
import Linear.Affine
import Linear.V2
import Linear.Vector
import Linear.Metric
rotateBy :: (InSpace V2 n t, Transformable t, Floating n) => n -> t -> t
rotateBy = transform . rotation . review turn
rotated :: (InSpace V2 n a, Floating n, SameSpace a b, Transformable a, Transformable b)
=> Angle n -> Iso a b a b
rotated = transformed . rotation
rotationAround :: Floating n => P2 n -> Angle n -> T2 n
rotationAround p theta =
conjugate (translation (origin .-. p)) (rotation theta)
rotateAround :: (InSpace V2 n t, Transformable t, Floating n)
=> P2 n -> Angle n -> t -> t
rotateAround p theta = transform (rotationAround p theta)
rotationTo :: OrderedField n => Direction V2 n -> T2 n
rotationTo (view _Dir -> V2 x y) = rotation (atan2A' y x)
rotateTo :: (InSpace V2 n t, OrderedField n, Transformable t) => Direction V2 n -> t -> t
rotateTo = transform . rotationTo
scalingX :: (Additive v, R1 v, Fractional n) => n -> Transformation v n
scalingX c = fromSymmetric $ (_x *~ c) <-> (_x //~ c)
scaleX :: (InSpace v n t, R2 v, Fractional n, Transformable t) => n -> t -> t
scaleX = transform . scalingX
scalingY :: (Additive v, R2 v, Fractional n) => n -> Transformation v n
scalingY c = fromSymmetric $ (_y *~ c) <-> (_y //~ c)
scaleY :: (InSpace v n t, R2 v, Fractional n, Transformable t)
=> n -> t -> t
scaleY = transform . scalingY
scaleToX :: (InSpace v n t, R2 v, Enveloped t, Transformable t) => n -> t -> t
scaleToX w d = scaleX (w / diameter unitX d) d
scaleToY :: (InSpace v n t, R2 v, Enveloped t, Transformable t) => n -> t -> t
scaleToY h d = scaleY (h / diameter unitY d) d
scaleUToX :: (InSpace v n t, R1 v, Enveloped t, Transformable t) => n -> t -> t
scaleUToX w d = scale (w / diameter unitX d) d
scaleUToY :: (InSpace v n t, R2 v, Enveloped t, Transformable t) => n -> t -> t
scaleUToY h d = scale (h / diameter unitY d) d
translationX :: (Additive v, R1 v, Num n) => n -> Transformation v n
translationX x = translation (zero & _x .~ x)
translateX :: (InSpace v n t, R1 v, Transformable t) => n -> t -> t
translateX = transform . translationX
translationY :: (Additive v, R2 v, Num n) => n -> Transformation v n
translationY y = translation (zero & _y .~ y)
translateY :: (InSpace v n t, R2 v, Transformable t)
=> n -> t -> t
translateY = transform . translationY
scalingRotationTo :: (Floating n) => V2 n -> T2 n
scalingRotationTo v = fromMatWithInv (conf v) (conf w) zero
where
w = reflectY (v ^/ quadrance v)
conf (V2 a b) = (V2 (V2 a (-b)) (V2 b a))
scaleRotateTo :: (InSpace V2 n t, Transformable t, Floating n)
=> V2 n -> t -> t
scaleRotateTo = transform . scalingRotationTo
reflectionX :: (Additive v, R1 v, Num n) => Transformation v n
reflectionX = fromSymmetric $ (_x *~ (-1)) <-> (_x *~ (-1))
reflectX :: (InSpace v n t, R1 v, Transformable t) => t -> t
reflectX = transform reflectionX
reflectionY :: (Additive v, R2 v, Num n) => Transformation v n
reflectionY = fromSymmetric $ (_y *~ (-1)) <-> (_y *~ (-1))
reflectY :: (InSpace v n t, R2 v, Transformable t) => t -> t
reflectY = transform reflectionY
reflectionXY :: (Additive v, R2 v, Num n) => Transformation v n
reflectionXY = fromSymmetric $ (_xy %~ view _yx) <-> (_xy %~ view _yx)
reflectXY :: (InSpace v n t, R2 v, Transformable t) => t -> t
reflectXY = transform reflectionXY
reflectionAbout :: OrderedField n => P2 n -> Direction V2 n -> T2 n
reflectionAbout p d =
conjugate (rotationTo (reflectY d) <> translation (origin .-. p))
reflectionY
reflectAbout :: (InSpace V2 n t, OrderedField n, Transformable t)
=> P2 n -> Direction V2 n -> t -> t
reflectAbout p v = transform (reflectionAbout p v)
sh :: (n -> n -> n -> n) -> (n -> n -> n -> n) -> n -> V2 n -> V2 n
sh f g k (V2 x y) = V2 (f k x y) (g k x y)
sh' :: (n -> n -> n -> n) -> (n -> n -> n -> n) -> n -> V2 n -> V2 n
sh' f g k = swap . sh f g k . swap
swap :: V2 n -> V2 n
swap (V2 x y) = V2 y x
{-# INLINE swap #-}
shearingX :: Num n => n -> T2 n
shearingX d = fromLinear (sh f g d <-> sh f g (-d))
(sh' f g d <-> sh' f g (-d))
where
f k x y = x + k*y
g _ _ y = y
shearX :: (InSpace V2 n t, Transformable t) => n -> t -> t
shearX = transform . shearingX
shearingY :: Num n => n -> T2 n
shearingY d = fromLinear (sh f g d <-> sh f g (-d))
(sh' f g d <-> sh' f g (-d))
where
f _ x _ = x
g k x y = y + k*x
shearY :: (InSpace V2 n t, Transformable t) => n -> t -> t
shearY = transform . shearingY