{-# 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.-------------------------------------------------------------------------------moduleDiagrams.TwoD.Transform(-- * Rotationrotation,rotate,rotateBy,rotationAbout,rotateAbout-- * Scaling,scalingX,scaleX,scalingY,scaleY,scaling,scale,scaleToX,scaleToY,scaleUToX,scaleUToY-- * Translation,translationX,translateX,translationY,translateY,translation,translate-- * Reflection,reflectionX,reflectX,reflectionY,reflectY,reflectionAbout,reflectAbout)whereimportGraphics.Rendering.DiagramsimportDiagrams.TwoD.TypesimportDiagrams.TwoD.Size(width,height)importDiagrams.TwoD.Vector(direction)importDiagrams.TransformimportDiagrams.UtilimportData.AffineSpaceimportControl.Arrow(first,second)-- Rotation -------------------------------------------------- | Create a transformation which performs a rotation by the given-- angle. See also 'rotate'.rotation::Anglea=>a->T2rotationang=fromLinearr(linvr)wherer=rottheta<->rot(-theta)Radtheta=convertAngleangrotth(x,y)=(costh*x-sinth*y,sinth*x+costh*y)-- | Rotate by the given angle. Positive angles correspond to-- counterclockwise rotation, negative to clockwise. The angle can-- be expressed using any type which is an instance of 'Angle'. For-- example, @rotate (1\/4 :: 'CircleFrac')@, @rotate (tau\/4 :: 'Rad')@, and-- @rotate (90 :: 'Deg')@ all represent the same transformation, namely,-- a counterclockwise rotation by a right angle.---- Note that writing @rotate (1\/4)@, with no type annotation, will-- yield an error since GHC cannot figure out which sort of angle-- you want to use. In this common situation you can use-- 'rotateBy', which is specialized to take a 'CircleFrac' argument.rotate::(Transformablet,Vt~R2,Anglea)=>a->t->trotate=transform.rotation-- | A synonym for 'rotate', specialized to only work with-- @CircleFrac@ arguments; it can be more convenient to write-- @rotateBy (1\/4)@ than @'rotate' (1\/4 :: 'CircleFrac')@.rotateBy::(Transformablet,Vt~R2)=>CircleFrac->t->trotateBy=transform.rotation-- | @rotationAbout p@ is a rotation about the point @p@ (instead of-- around the local origin).rotationAbout::Anglea=>P2->a->T2rotationAboutpangle=conjugate(translation(origin.-.p))(rotationangle)-- | @rotateAbout p@ is like 'rotate', except it rotates around the-- point @p@ instead of around the local origin.rotateAbout::(Transformablet,Vt~R2,Anglea)=>P2->a->t->trotateAboutpangle=rotateangle`under`(translation(origin.-.p))-- Scaling --------------------------------------------------- | Construct a transformation which scales by the given factor in-- the x (horizontal) direction.scalingX::Double->T2scalingXc=fromLinearsswheres=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::(Transformablet,Vt~R2)=>Double->t->tscaleX=transform.scalingX-- | Construct a transformation which scales by the given factor in-- the y (vertical) direction.scalingY::Double->T2scalingYc=fromLinearsswheres=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::(Transformablet,Vt~R2)=>Double->t->tscaleY=transform.scalingY-- | @scaleToX w@ scales a diagram in the x (horizontal) direction by-- whatever factor required to make its width @w@. @scaleToX@-- should not be applied to diagrams with a width of 0, such as-- 'vrule'.scaleToX::(Boundablet,Transformablet,Vt~R2)=>Double->t->tscaleToXwd=scaleX(w/widthd)d-- | @scaleToY h@ scales a diagram in the y (vertical) direction by-- whatever factor required to make its height @h@. @scaleToY@-- should not be applied to diagrams with a width of 0, such as-- 'hrule'.scaleToY::(Boundablet,Transformablet,Vt~R2)=>Double->t->tscaleToYhd=scaleY(h/heightd)d-- | @scaleUToX w@ scales a diagram /uniformly/ by whatever factor-- required to make its width @w@. @scaleUToX@ should not be-- applied to diagrams with a width of 0, such as 'vrule'.scaleUToX::(Boundablet,Transformablet,Vt~R2)=>Double->t->tscaleUToXwd=scale(w/widthd)d-- | @scaleUToY h@ scales a diagram in the y (vertical) direction by-- whatever factor required to make its height @h@. @scaleUToY@-- should not be applied to diagrams with a width of 0, such as-- 'hrule'.scaleUToY::(Boundablet,Transformablet,Vt~R2)=>Double->t->tscaleUToYhd=scale(h/heightd)d-- Translation ----------------------------------------------- | Construct a transformation which translates by the given distance-- in the x (horizontal) direction.translationX::Double->T2translationXx=translation(x,0)-- | Translate a diagram by the given distance in the x (horizontal)-- direction.translateX::(Transformablet,Vt~R2)=>Double->t->ttranslateX=transform.translationX-- | Construct a transformation which translates by the given distance-- in the y (vertical) direction.translationY::Double->T2translationYy=translation(0,y)-- | Translate a diagram by the given distance in the y (vertical)-- direction.translateY::(Transformablet,Vt~R2)=>Double->t->ttranslateY=transform.translationY-- Reflection ------------------------------------------------ | Construct a transformation which flips a diagram from left to-- right, i.e. sends the point (x,y) to (-x,y).reflectionX::T2reflectionX=scalingX(-1)-- | Flip a diagram from left to right, i.e. send the point (x,y) to-- (-x,y).reflectX::(Transformablet,Vt~R2)=>t->treflectX=transformreflectionX-- | Construct a transformation which flips a diagram from top to-- bottom, i.e. sends the point (x,y) to (x,-y).reflectionY::T2reflectionY=scalingY(-1)-- | Flip a diagram from top to bottom, i.e. send the point (x,y) to-- (x,-y).reflectY::(Transformablet,Vt~R2)=>t->treflectY=transformreflectionY-- | @reflectionAbout p v@ is a reflection in the line determined by-- the point @p@ and vector @v@.reflectionAbout::P2->R2->T2reflectionAboutpv=conjugate(rotation(-directionv::Rad)<>translation(origin.-.p))reflectionY-- | @reflectAbout p v@ reflects a diagram in the line determined by-- the point @p@ and the vector @v@.reflectAbout::(Transformablet,Vt~R2)=>P2->R2->t->treflectAboutpv=transform(reflectionAboutpv)