;docformat = 'rst'
;+
;Do an affine transformation on an image, specified by an affine matrix
;
;:Params:
; img: in, required
; input image
; AA: in, required, type="float(3,3)"
; Affine transformation matrix -- 3x3 element matrix of the form [[a,b,c],[d,e,f],[0,0,1]].
; Last row is never referenced, so it may be omitted
; interp: in, optional
; If set, passed along to POLY_2D
; dimx: in, optional
; If set, passed along to POLY_2D
; dimy: in, optional
; If set, passed along to POLY_2D
;:Keywords:
; _extra: optional
; All other named parameters are passed to POLY_2D
;:Returns:
; Image of the same shape as input image, with transformed image data in it and clipped by it.
;
;:Description:
;Homogeneous coordinates: For our purposes, it just extends a 2-component
;vector into 3 components using 1 as the third coordinate.
;
;For each point on the input image z=[[x],[y],[1]] in homogeneous coordinates,
;transform by matrix A to get the point on the output image z'=[[x'],[y'],[1]]
;as follows::
;
; z'=[[x'],[y'],[1]] = A ## z = [[a,b,c],[d,e,f],[0,0,1]] ## [[x],[y],[1]]
;
;Written out, we get::
;
; x'=a*x+b*y+c
; y'=d*x+e*y+c
;
;The whole reason we use matrices here is becasue several affine transformations
;can be concatenated into one. An example use case is as follows: In Rocket EVE,
;the rocket can roll to any position and put solar north at any angle relative
;to the SAM CCD. We need to take an image taken with north at one angle and
;rotate it to that taken at some other angle. This is complicated by the fact that
;the SAM image is stretched in one axis. To reproject an image, perform the following
;transformations in order::
;
; Translate so that the center of the SAM image is at the origin: A1=T(-xc,-yc)
; Scale the image horizontally such that it is circular: A2=S(yr/xr,1)
; Rotate the image: A3=R(theta)
; Scale the image horizontally back to elliptical: A4=S(xr/yr,1)
; Translate the image back home: A5=T(xc,yc)
;
;The concatenation of those transformations is represented by a single affine matrix
;calculated by matrix multiplication::
;
; A = A5 ## A4 ## A3 ## A2 ## A1
;
;This function works by calculating from A the two polynomial coefficient matrices P and Q
;needed by the IDL library function POLY_2D, then calling that function. POLY2D requires
;two square matrices of coefficients and calculates the output location z'=[[x'],[y']] as follows:
;
;x'=sum_i=0^N(sum_j=0^N(P[i,j]*x^i*y^j))
;y'=sum_i=0^N(sum_j=0^N(Q[i,j]*x^i*y^j))
;
;The P and Q matrices are generated from A as follows::
;
; P=[[c,b],[a,0]]
; Q=[[f,e],[d,0]]
;
;
;:Examples:
; To solve the SAM problem above, do this::
; img=...;load SAM image
; xc=... ;center of SAM solar image X coordinate in pixels
; yc=... ;center of SAM solar image y coordinate in pixels
; rx=... ;Radius of SAM solar image in horizontal direction in pixels
; ry=... ;Radius of SAM solar image in vertical direction in pixels
; theta=.. ;Angle to rotate SAM image in radians
; s=sin(theta)
; k=cos(theta)
; A1=[[0,0,-xc],[0,0,-yc],[0,0,1]] ;T(-xc,-yc)
; A2=[[rx/ry,0,0],[0,1,0],[0,0,1]] ;S(rx/ry,1)
; A3=[[k,s,0],[-s,k,0],[0,0,1]] ;R(theta)
; A4=[[ry/rx,0,0],[0,1,0],[0,0,1]] ;S(ry/rx,1)
; A5=[[0,0,xc],[0,0,yc],[0,0,1]] ;T(xc,yc)
; AA=A5##A4##A3##A2##A1 ;Complete affine matrix
; img_rot=eve_affine_matrix(img,AA) ;Rotation performed
function eve_affine_matrix,img,AA,interp,dimx,dimy,_extra=extra
a=AA[0,0]
b=AA[1,0]
c=AA[2,0]
d=AA[0,1]
e=AA[1,1]
f=AA[2,1]
P=[[c,b],[a,0]]
Q=[[f,e],[d,0]]
return,poly_2d(img,P,Q,_extra=extra)
end