{-# 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
, 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.TwoD.Types
import Diagrams.TwoD.Vector
import Control.Lens hiding (at, transform)
import Data.Semigroup
import Linear.Affine
import Linear.V2
import Linear.Vector
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
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