diagrams-lib-0.1: src/Diagrams/TwoD/Transform.hs
{-# LANGUAGE FlexibleContexts
, TypeFamilies
#-}
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.TwoD.Transform
-- Copyright : (c) 2011 diagrams-lib team (see LICENSE)
-- License : BSD-style (see LICENSE)
-- Maintainer : diagrams-discuss@googlegroups.com
--
-- Transformations specific to two dimensions, with a few generic
-- transformations (uniform scaling, translation) also re-exported for
-- convenience.
--
-----------------------------------------------------------------------------
module Diagrams.TwoD.Transform
(
-- * Rotation
rotation, rotate
, rotationBy, rotateBy
-- * Scaling
, scalingX, scaleX
, scalingY, scaleY
, scaling, scale
-- * Translation
, translationX, translateX
, translationY, translateY
, translation, translate
-- * Reflection
, reflectionX, reflectX
, reflectionY, reflectY
) where
import Graphics.Rendering.Diagrams
import Diagrams.TwoD.Types
import Control.Arrow (first, second)
-- | Create a transformation which performs a rotation by the given
-- angle in radians.
rotation :: Angle -> Transformation R2
rotation theta = fromLinear r (linv r)
where
rot th (x,y) = (cos th * x - sin th * y, sin th * x + cos th * y)
r = rot theta <-> rot (-theta)
-- | Rotate by the given angle in radians.
rotate :: (Transformable t, V t ~ R2) => Angle -> t -> t
rotate = transform . rotation
-- | Create a transformation which performs a rotation by the given
-- fraction of a circle. For example, @rotationBy (1/4)@ rotates by
-- one quarter of a circle (i.e. 90 degrees, i.e. pi/2 radians).
rotationBy :: Double -> Transformation R2
rotationBy = rotation . (*(2*pi))
-- | Rotate by the given fraction of a circle.
rotateBy :: (Transformable t, V t ~ R2) => Angle -> t -> t
rotateBy = transform . rotationBy
-- | Construct a transformation which scales by the given factor in
-- the x (horizontal) direction.
scalingX :: Double -> Transformation R2
scalingX c = fromLinear s s
where s = first (*c) <-> first (/c)
-- | Scale a diagram by the given factor in the x (horizontal)
-- direction. To scale uniformly, use
-- 'Graphics.Rendering.Diagrams.Transform.scale'.
scaleX :: (Transformable t, V t ~ R2) => Double -> t -> t
scaleX = transform . scalingX
-- | Construct a transformation which scales by the given factor in
-- the y (vertical) direction.
scalingY :: Double -> Transformation R2
scalingY c = fromLinear s s
where s = second (*c) <-> second (/c)
-- | Scale a diagram by the given factor in the y (vertical)
-- direction. To scale uniformly, use
-- 'Graphics.Rendering.Diagrams.Transform.scale'.
scaleY :: (Transformable t, V t ~ R2) => Double -> t -> t
scaleY = transform . scalingY
-- | Construct a transformation which translates by the given distance
-- in the x (horizontal) direction.
translationX :: Double -> Transformation R2
translationX x = translation (x,0)
-- | Translate a diagram by the given distance in the x (horizontal)
-- direction.
translateX :: (Transformable t, V t ~ R2) => Double -> t -> t
translateX = transform . translationX
-- | Construct a transformation which translates by the given distance
-- in the y (vertical) direction.
translationY :: Double -> Transformation R2
translationY y = translation (0,y)
-- | Translate a diagram by the given distance in the y (vertical)
-- direction.
translateY :: (Transformable t, V t ~ R2) => Double -> t -> t
translateY = transform . translationY
-- | Construct a transformation which flips a diagram from left to
-- right, i.e. sends the point (x,y) to (-x,y).
reflectionX :: Transformation R2
reflectionX = scalingX (-1)
-- | Flip a diagram from left to right, i.e. send the point (x,y) to
-- (-x,y).
reflectX :: (Transformable t, V t ~ R2) => t -> t
reflectX = transform reflectionX
-- | Construct a transformation which flips a diagram from top to
-- bottom, i.e. sends the point (x,y) to (x,-y).
reflectionY :: Transformation R2
reflectionY = scalingY (-1)
-- | Flip a diagram from top to bottom, i.e. send the point (x,y) to
-- (x,-y).
reflectY :: (Transformable t, V t ~ R2) => t -> t
reflectY = transform reflectionY
-- XXX todo: add general reflection/reflect operators which reflect
-- around an arbitrary axis (taking a vector as an argument).