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 + Ay

coefficients 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          # idem

where 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⋅B

all 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)∘B

Translation 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 + A

where 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 + pnt

Rotating 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∘R

where 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 = ρ*A

which 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)