Affine Coordinate Transforms
TwoDimensional provides types and methods to deal with 2-dimensional affine coordinate transforms.
An affine 2D transform A is defined by 6 real coefficients, Axx, Axy, Ax, Ayx, Ayy and Ay. Such a transform maps (x,y) as (xp,yp) given by:
xp = Axx*x + Axy*y + Ax
yp = Ayx*x + Ayy*y + Aycoefficients Axx, Axy, Ayx, and Ayy are factors while coefficients Ax and Ay are offsets.
The immutable type AffineTransform{T} is used to store an affine 2D transform with coefficients of floating-point type T, it can be created by:
I = AffineTransform{T}() # yields the identity with type T
A = AffineTransform{T}(Axx, Axy, Ax, Ayx, Ayy, Ay)If the parameter T is omitted, it is guessed from the types of the coefficients.
Operations with affine 2D transforms
Many operations are available to manage or apply affine transforms.
Perform a coordinate transformation
There are several possibilities to apply an affine transform A to coordinates (x,y):
(xp, yp) = A(x,y) # apply affine transform A to coordinates (x,y)
(xp, yp) = A*(x,y) # idem
(xp, yp) = A(v) # idem, with v = (x,y)
(xp, yp) = A*v # idemwhere x, y, xp and yp are reals while v = (x,y) is a 2-tuple of real coordinates. Coordinates may also be specified as Point instances:
A(Point(x,y)) -> Point(xp, yp)
A*Point(x,y) -> Point(xp, yp)Reciprocal transform
The reciprocal transform of A is given by:
B = inv(A)Compose coordinate transformations
To compose 2 (or more) transforms A and B, do one of:
C = compose(A, B, ...)
C = A∘B
C = A*B
C = A⋅Ball these statements yields an object C which applies B then A. Note that ∘ and ⋅ can be typed by \\circ<tab> and \\cdot<tab>.
Left and right "divisions" of affine tansforms respectively write:
A/B -> A∘inv(B)
A\B -> inv(A)∘BTranslation of coordinates
An operator B which which applies a translations by (x,y) after a coordinate transform A (possibly the identity) can be created by one of the following statements:
B = translate(x, y, A)
B = translate(pnt, A)
B = pnt + Awhere pnt is a 2-tuple of coordinates, pnt = (x,y), a Point, pnt = Point(x,y), or 2-dimensional Cartesian index, CartesianIndex{2}(x,y).
To perform the translation before the coordinate transform A, do:
B = translate(A, x, y)
B = translate(A, pnt)
B = A + pntRotating an affine transform
There are two ways to combine a rotation by angle θ (in radians counterclockwise) with an affine transform A. Left-rotating as in:
B = rotate(θ, A)results in rotating the output of the transform; while right-rotating as in:
C = rotate(A, θ)results in rotating the input of the transform. The above examples are similar to:
B = R∘A
C = A∘Rwhere R implements rotation by angle θ counterclockwise around the origin at coordinates (0,0). The rotation angle θ is assumed to be in radians if it has no units.
Scaling of coordinates
There are two ways to combine a scaling by a factor ρ with an affine transform A. Left-scaling as in:
B = scale(ρ, A)
B = ρ*Awhich yields B such that B(x,y) = ρ*A(x,y); or right-scaling as in:
C = scale(A, ρ)
C = A*ρwhich yields C such that C(x,y) = A(ρ*x,ρ*y); or right-scaling as in:
Miscellaneous
det(A) returns the determinant of the linear part of the affine transform A.
Type conversion
As a general rule, the floating-point type T of an AffineTransform{T} is imposed for all operations and for the result. The floating-point type of the composition of several coordinate transforms is the promoted type of the transforms which have been composed.
The type of the coefficients of the affine transform A is given by:
eltype(A)To convert the floating-point type of the coefficients of A to be T, do one of:
B = T.(A)
B = AffineTransform{T}(A)
B = convert(AffineTransform{T}, A)